面向对象
创造对象
示例代码:类的名字用小驼峰命名法
#编写Person类
class Person():
pass
class Cat: #,小括号可以省略
pass
#对象名=类名
per=Person()
c=Cat() #小括号不能省略
print(type(per))
print(type(c))
代码结果:
<class '__main__.Person'>
<class '__main__.Cat'>
类的基本组成
示例代码:
class School:
#类属性,定义在类中,方法外的变量
school="北京XXX教育"
#创建初始方法,定义实例属性
def __init__(self,xm,age):#xm,age是参数,属于局部变量
self.name=xm #左边是实例属性,右边是局部变量,进行赋值
self.age=age #可以相同
#定义类的函数,称为方法,自带参数self
def show(self):
print(f"我叫{self.name},今年{self.age}")#运用实例属性
#静态方法
@staticmethod
def sm():
print("这是静态方法,不能调用实例属性,也不能调用实例方法")
@classmethod
def cm(cls):#自带cls
print("这是类方法,不能调用实例属性,也不能调用实例方法")
#创建类的对象
# __int__(self,xm,age):两个参数需要传入
stu=School("111",18)
print(type(stu))
#实例属性,运用对象名打点调用
print(stu.name,stu.age)
#类属性,用类名打点调用
print(School.school)
#实例方法,使用对象名打点调用
stu.show()
#静态方法
School.sm()
#类方法
School.cm()
代码结果:
<class '__main__.School'>
111 18
北京XXX教育
我叫111,今年18
这是静态方法,不能调用实例属性,也不能调用实例方法
这是类方法,不能调用实例属性,也不能调用实例方法
动态绑定属性和方法
就是在类的外面书写实例属性或者实例方法
示例代码:
class School:
#类属性,定义在类中,方法外的变量
school="北京XXX教育"
#创建初始方法,定义实例属性
def __init__(self,xm,age):#xm,age是参数,属于局部变量
self.name=xm #左边是实例属性,右边是局部变量,进行赋值
self.age=age #可以相同
#定义类的函数,称为方法,自带参数self
def show(self):
print(f"我叫{self.name},今年{self.age}")#运用实例属性
stu=School("001",18)
stu2=School("009",18)
print(stu.name,stu.age)
print(stu2.name,stu2.age)
#为stu2动态绑定一个实例属性
stu2.gender="男"
print(stu2.name,stu2.age,stu2.gender)
#为stu2动态绑定一个实例方法
def introduce():
print("将这个函数动态绑定给stu2")
stu2.fun=introduce #函数的一个赋值
#fun为方法和show一样
#打点调用
stu2.fun()
代码结果:
001 18
009 18
009 18 男
将这个函数动态绑定给stu2
属性设置
将方法改为属性,属性可直接赋值
示例代码:
class Student:
def __init__(self,name,gender):
self.name=name
self.__gender=gender
#使用@property将方法转换为属性
@property
def gender(self):
return self.__gender
#将gender这个属性设置为可写属性,解决stu.gender不能直接赋值的问题
@gender.setter
def gender(self,value):
if value!="男" and value!="女":
print("性别输入错误,默认为男")
self.__gender="男"
else:
self.__gender=value
stu=Student("李佳怡","女")
print(stu.name,"的年龄是",stu.gender)
stu.gender="其他"
print(stu.name,"的年龄是",stu.gender)
代码结果:
李佳怡 的年龄是 女
性别输入错误,默认为男
李佳怡 的年龄是 男
多态
示例代码:
class Person:
def eat(self):
print("人,吃五谷杂粮")
class Cat:
def eat(self):
print("猫,吃鱼")
class Dog:
def eat(self):
print("狗,吃骨头")
def fun(obj):
obj.eat()
per=Person()
cat=Cat()
dog=Dog()
#python的多态不关心对象数据类型,只关心对象是否有同名方法
fun(per)
fun(cat)
fun(dog)
代码结果:
人,吃五谷杂粮
猫,吃鱼
狗,吃骨头
继承
示例代码:可以继承别人的属性或者方法,,被继承的称为父类
class Person:#不写括号,默认object类
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
print(f"我叫{self.name},今年{self.age}岁")
class Student(Person):
def __init__(self,name,age,sno):
super().__init__(name,age) #调用父类的初始化方法
self.sno=sno
class Doctor(Person):
def __init__(self,name,age,department):
super().__init__(name,age) #调用父类的初始化方法
self.department=department
#创建对象
stu=Student("联名卡",18,1001)
stu.show()#可以直接调用父类的方法
doctor=Doctor("藏宝阁",54,"外科")
doctor.show()
代码结果:
我叫联名卡,今年18岁
我叫藏宝阁,今年54岁
多继承
示例代码:
class Fathera:
def __init__(self,name):
self.name=name
def showa(self):
print("这是父类a的方法")
class Fatherb:
def __init__(self,age):
self.age=age
def showb(self):
print("这是父类b的方法")
class Son(Fathera,Fatherb):
def __init__(self,name,age,gender):
Fathera.__init__(self,name)
Fatherb.__init__(self,age)
self.gender=gender
son=Son("李佳怡",18,"男")
son.showa()
son.showb()
代码结果:
这是父类a的方法
这是父类b的方法
方法重写
示例代码:
class Person:#不写括号,默认object类
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
print(f"我叫{self.name},今年{self.age}岁")
class Student(Person):
def __init__(self,name,age,sno):
super().__init__(name,age) #调用父类的初始化方法
self.sno=sno
def show(self): #改写方法名字要和父类一样
super().show() #调用父类的show方法
print(f"我的学号是{self.sno}")
class Doctor(Person):
def __init__(self,name,age,department):
super().__init__(name,age) #调用父类的初始化方法
self.department=department
def show(self): # 改写方法名字要和父类一样
# super().show() #调用父类的show方法
# 可以不继承父类全部重写
print(f"我叫{self.name},今年{self.age},我的工作科室为是{self.department}")
#创建对象
stu=Student("联名卡",18,1001)
stu.show()
doctor=Doctor("藏宝阁",54,"外科")
doctor.show()
代码结果:
我叫联名卡,今年18岁
我的学号是1001
我叫藏宝阁,今年54,我的工作科室为是外科
权限控制
示例代码:
class School:
#类属性,定义在类中,方法外的变量
school="北京XXX教育"
#创建初始方法
def __init__(self,xm,age,gender):#xm,age是参数,属于局部变量
self._name=xm #受保护,只能子类和本类进行访问
self.__age=age #表示私有的,只能类本身进行访问
self.gender = gender#普通实例属性,内部,外部,子类都可以进行访问
def _fun1(self):
print("受保护,只能子类和本类进行访问")
def __fun2(self):
print("表示私有的,只能类本身进行访问")
def show(self):
self._fun1() #类本身访问受保护方法
self.__fun2()#类本身访问受私有方法
print(self._name)#受保护实例属性
print(self.__age)#私有的实例属性
stu=School("搓麻将",18,"man")
#类的外部
print(stu._name)
# print(stu.__age) 会报错 私有,出了类的定义范围就不能用了
#调用受保护的实例方法
stu._fun1()
#stu.__fun2() 会报错 私有,出了类的定义范围就不能用了
#私有的实例方法和属性也可以访问,但是有自己的形式
print(stu._School__age)
stu._School__fun2()
print(dir(stu)) #展示出所有的属性和方法
代码结果:
搓麻将
受保护,只能子类和本类进行访问
18
表示私有的,只能类本身进行访问
['_School__age', '_School__fun2', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_fun1', '_name', 'gender', 'school', 'show']
查看指定对象的属性,全部方法(dir)
示例代码:
class School:
#类属性,定义在类中,方法外的变量
school="北京XXX教育"
#创建初始方法,定义实例属性
def __init__(self,xm,age):#xm,age是参数,属于局部变量
self.name=xm #左边是实例属性,右边是局部变量,进行赋值
self.age=age #可以相同
#定义类的函数,称为方法,自带参数self
def show(self):
print(f"我叫{self.name},今年{self.age}")#运用实例属性
stu=School("李佳怡",18)
print(dir(stu))
print(stu)#自动调用__str__方法
代码结果:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name', 'school', 'show']
<__main__.School object at 0x00000119EB827CD0>
特殊属性
示例代码:
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,age):
self.name=name
self.age=age
a=A()
b=B()
c=C("李佳怡",18)
print("对象a的属性字典",a.__dict__)
print("对象b的属性字典",b.__dict__)
print("对象c的属性字典",c.__dict__)
print()
print("对象a所属的类",a.__class__)
print()
print("A类的父类元组",A.__bases__)
print("C类的父类元组",C.__bases__)
print()
print("A类的父类",A.__base__)
print("C类的父类",C.__base__)#显示第一个父类,如果n个父类具有同名的方法,调用第一个父类的方法
print()
print("A类的层次结构:",A.__mro__)
print("C类的层次结构:",C.__mro__)
print()
print("A类的子类列表",A.__subclasses__())#方法,要带括号
print("B类的子类列表",B.__subclasses__())
print("C类的子类列表",C.__subclasses__())
代码结果:
对象a的属性字典 {}
对象b的属性字典 {}
对象c的属性字典 {'name': '李佳怡', 'age': 18}
对象a所属的类 <class '__main__.A'>
A类的父类元组 (<class 'object'>,)
C类的父类元组 (<class '__main__.A'>, <class '__main__.B'>)
A类的父类 <class 'object'>
C类的父类 <class '__main__.A'>
A类的层次结构: (<class '__main__.A'>, <class 'object'>)
C类的层次结构: (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
A类的子类列表 [<class '__main__.C'>]
B类的子类列表 [<class '__main__.C'>]
C类的子类列表 []
特殊方法
示例代码:
a=10
b=20
print(dir(a))
print(a.__add__(b))
print(a.__sub__(b))
print(f"{a}<{b}?",a.__lt__(b))
print(f"{a}<={b}?",a.__le__(b))
print(f"{a}={b}?",a.__eq__(b))
print("-"*40)
print(f"{a}>{b}?",a.__gt__(b))
print(f"{a}>={b}?",a.__ge__(b))
print(f"{a}!={b}?",a.__ne__(b))
print("-"*40)
print(a.__mul__(b))#乘法
print(a.__truediv__(b))#除法
print(a.__mod__(b))#取余
print(a.__floordiv__(b))#整除
print(a.__pow__(b))#幂运算
代码结果:
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
30
-10
10<20? True
10<=20? True
10=20? False
----------------------------------------
10>20? False
10>=20? False
10!=20? True
----------------------------------------
200
0.5
10
0
100000000000000000000
重写__str__方法
示例代码:
class School:
#类属性,定义在类中,方法外的变量
school="北京XXX教育"
#创建初始方法,定义实例属性
def __init__(self,xm,age):#xm,age是参数,属于局部变量
self.name=xm #左边是实例属性,右边是局部变量,进行赋值
self.age=age #可以相同
#方法重写
def __str__(self):
return "他具有姓名和年龄两个实例属性"
stu=School("李佳怡",18)
print(stu)#自动调用__str__方法,默认输出内存地址,修改后按修改的内容输出
#也可以手动调用
print(stu.__str__())
运行结果:
他具有姓名和年龄两个实例属性
他具有姓名和年龄两个实例属性
类的浅拷贝和深拷贝
针对于内存地址,直接赋值和浅拷贝,深拷贝各不相同
示例代码:
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk):
self.cpu=cpu
self.disk=disk
cpu=CPU()
disk=Disk()
com=Computer(cpu,disk)
#变量赋值
com1=com
print(com,"子对象的内存地址:",com.cpu,com.disk)
print(com1,"子对象的内存地址:",com1.cpu,com1.disk)
print()
#类对象的浅拷贝
import copy
com2=copy.copy(com)
print(com) #com和com2的内存地址不同,但是子对象内存地址相同
print(com2)
print(com,"子对象的内存地址:",com.cpu,com.disk)
print(com2,"子对象的内存地址:",com2.cpu,com2.disk)
print()
#深拷贝
com3=copy.deepcopy(com)#连子对象的内存空间也会重新去创建
print(com,"子对象的内存地址:",com.cpu,com.disk)
print(com3,"子对象的内存地址:",com3.cpu,com3.disk)
代码结果:(观察什么相同什么不同即可)
<__main__.Computer object at 0x0000020991C30190> 子对象的内存地址: <__main__.CPU object at 0x0000020991C30110> <__main__.Disk object at 0x0000020991C30150>
<__main__.Computer object at 0x0000020991C30190> 子对象的内存地址: <__main__.CPU object at 0x0000020991C30110> <__main__.Disk object at 0x0000020991C30150>
<__main__.Computer object at 0x0000020991C30190>
<__main__.Computer object at 0x0000020991C30210>
<__main__.Computer object at 0x0000020991C30190> 子对象的内存地址: <__main__.CPU object at 0x0000020991C30110> <__main__.Disk object at 0x0000020991C30150>
<__main__.Computer object at 0x0000020991C30210> 子对象的内存地址: <__main__.CPU object at 0x0000020991C30110> <__main__.Disk object at 0x0000020991C30150>
<__main__.Computer object at 0x0000020991C30190> 子对象的内存地址: <__main__.CPU object at 0x0000020991C30110> <__main__.Disk object at 0x0000020991C30150>
<__main__.Computer object at 0x00000209918D6F50> 子对象的内存地址: <__main__.CPU object at 0x0000020991C30310> <__main__.Disk object at 0x0000020991C30B90>
相关题目示例
计算圆的面积和周长
class Circle:
def __init__(self,r):
self.r=r
def get_area(self):
return 3.14*pow(self.r,2)
def get_perimeter(self):
return 3.14*2*self.r
r=eval(input("请输入圆的半径"))
c=Circle(r)
area=c.get_area()
perimeter=c.get_perimeter()
print("圆的面积为:",area)
print("圆的周长为",perimeter)
代码结果:
请输入圆的半径4
圆的面积为: 50.24
圆的周长为 25.12
银行账户
class Account_bank:
def __init__(self,account_number,owner,balance):
self.account_number=account_number
self.owner=owner
self.balance=balance
def display(self):
print(f"账号:{self.account_number}")
print(f"户主:{self.owner}")
print(f"账户余额:{self.balance}")
def deposit(self):
data=eval(input("请输入你要存多少钱:"))
money=self.balance
self.balance=data+money
self.get_balance()
def withdraw(self):
data2=eval(input("请输入你要取多少钱:"))
self.balance-=data2
self.get_balance()
def get_balance(self):
print(f"现有余额:{self.balance}")
data_1={
"账号":"127",
"户主":"张三",
"余额":4000
}
data_2={
"账号":"124",
"户主":"李四",
"余额":3000
}
data_3={
"账号":"128",
"户主":"王五",
"余额":6000
}
user=input("请输入你的账户:")
if user==data_1["账号"]:
account_number=user
owner=data_1["户主"]
balance = data_1["余额"]
elif user==data_2["账号"]:
account_number = user
owner=data_2["户主"]
balance = data_2["余额"]
else:
account_number = data_3["账号"]
owner=data_3["户主"]
balance = data_3["余额"]
account=Account_bank(account_number,owner,balance)
account.display()
account.deposit()
account.withdraw()
代码结果:
请输入你的账户:127
账号:127
户主:张三
账户余额:4000
请输入你要存多少钱:100
现有余额:4100
请输入你要取多少钱:0
现有余额:4100