19 面向对象 — 高阶
19.1 内置成员
class A():
pass
class C():
pass
class B(C):
pass
class Demo(A,B):
'''
此处是类的文档说明
'''
name = "XX"
age = 30
def sing(self):
print('the songs rhythm and melody')
pass
obj = Demo()
# 获取类/对象的所属成员
res = Demo.__dict__ # {'__module__': '__main__', 'name': 'XX', 'age': 30, 'sing': <function Demo.sing at 0x00000000021BA1F8>, '__dict__': <attribute '__dict__' of 'Demo' objects>, '__weakref__': <attribute '__weakref__' of 'Demo' objects>, '__doc__': None}
ree = obj.__dict__ # {} 当前对象没有属于自己的属性
obj.music = 'one'
ree = obj.__dict__ # {'music': 'one'}
print(ree)
# 获取类的文档说明 类/对象.__doc__
res = Demo.__doc__
res = obj.__doc__
# 获取类名称组成的字符串
res = Demo.__name__
# 获取类所在的文件名称,如果是当前文档,显示为__main__
res = Demo.__module__
# 获取当前类的父类列表 bases
res = Demo.__bases__ # (<class '__main__.A'>, <class '__main__.B'>)
res = Demo.__base__ # 获取继承的第一个父类 <class '__main__.A'>
# 获取当前类的继承链 MRO列表
res = Demo.mro() # [<class '__main__.Demo'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
19.2 方法的分类
19.2.1 对象方法
特征:
1.类中定义的方法,含有self参数
2.含有self的方法,只能使用self进行调用
3.该方法会把调用的对象传进来
class Demo():
# 对象方法
def f1(self):
print('this is f1')
# 实例化对象
o = Demo()
o.f1()
# 不能直接使用类调用 对象方法,除非传递一个对象,不推荐
Demo.f1('a')
19.2.2 类方法
特征:
1.在类中的方法,使用装饰器 @classmethod 进行了装饰
2.方法中有 cls形参
3.不需要实例化对象,直接使用类进行调用
4.会把调用这个方法的类传递进来
class Demo():
# 类方法
@classmethod
def f2(cls,a):
print(cls,a)
print('this is class function f2')
obj = Demo()
Demo.f2('')
obj.f2('') # 即便使用对象调用,传递进去的依然是类
# <class '__main__.Demo'>
# this is class function f2
19.2.3 绑定类方法
特征:
1.类中定义的方法,没有任何参数
2.只能使用类进行调用
3.不会传递对象或者类进来
class Demo():
# 绑定类方法
def f3():
print('this is bind class function f3')
Demo.f3()
# 不能使用对象调用
19.2.4 静态方法
特征:
1.类中定义的方法,使用了 装饰器 @staticmethod 进行了装饰
2.可以使用对象或者类进行调用
3.不会传递对象或类进来
class Demo():
# 静态方法
@staticmethod
def f4():
print('this is static function f4')
@staticmethod
def f5(a,b):
print(a,b)
print('this is static f5')
Demo.f4()
o = Demo()
o.f4()
Demo.f5(3,4)
o.f5(6,7)
19.3 常用函数
19.3.1 检测类和对象相关
- issubclass(子类,父类) 检测一个类是否为另一个类的子类
res = issubclass(B,C)
print(res)
- isinstance(对象,类) 检测一个对象是否是指定类或指定类的子类的实例化
class A():
pass
class B(A):
pass
class C(A):
pass
class D(B,C):
pass
a = A()
b = B()
d = D()
res = isinstance(d,A)
print(res) # True
- hasattr(对象/类,'成员名称') 检测类/对象是否包含指定名称的成员
class A():
age = 20
_one = ''
class B(A):
pass
class C(A):
pass
class D(B,C):
name = ''
_sex = ''
__age = 20
def say(self):
print('say sth')
a = A()
b = B()
d = D()
res = hasattr(d,'age') # True
res = hasattr(B,'age') # True
res = hasattr(d,'say') # True
res = hasattr(d,'__age') # False 私有成员 注意!
res = hasattr(d,'_sex') # True
res = hasattr(d,'_one') # True
19.3.2 操作类和对象相关
- getattr(类/对象,'成员名') 获取类/对象的成员的值,除了私有成员
class A():
age = 20
_one = 'two'
class B(A):
pass
class C(A):
pass
class D(B,C):
name = ''
_sex = ''
__age = 18
def say(self):
print('say sth')
a = A()
b = B()
d = D()
res = getattr(d,'_one') # two
res = getattr(d,'say') # <bound method D.say of <__main__.D object at 0x00000000023CF388>>
print(res)
- setattr(对象/类,'成员名','成员值') 可以设置对象/类的成员的属性值
setattr(d,'name','ll')
print(d.name)
- delattr() 删除对象/类的成员,和 del 直接删除对象的成员是一样的
print(d.age) # 20
delattr(A,'age')
print(d.age) # error, no attribute
- dir() 获取当前对象所有可以访问的成员的列表
print(dir(d))
19.4 魔术方法
19.4.1 类相关魔术方法
不需要手动调用就可自动执行的方法
1. __init__ 初始化方法
触发机制:当实例化对象后,就会立即触发的方法
作用:为当前创建的对象,完成一系列初始化的操作。如,成员属性的赋值,方法的调用,打开或创建一些资源等
参数:一个self,接收当前对象,其他参数根据需求定义
返回值: 无
注意事项: 无
2. __del__ 析构方法
触发机制:当该类对象被销毁时,自动触发
作用: 关闭或释放在对象创建时打开或创建的一些资源
参数: 一个self,接收当前对象
返回值:无
注意事项:无
3. __new__ 构造方法
触发机制: 实例化对象时,自动触发(在__init__之前触发)
作用: 管理控制对象创建的过程
参数: 一个cls,接受当前类,其他参数根据初始化方法的参数进行决定
返回值: 必须返回object.__new__(cls)进行对象的创建,若无返回值,则实例化对象的结果为None
注意事项:
1. __new__方法的参数和__init__的参数保持一致,除了第一个参数
2. 必须返回object.__new__(cls)进行对象的创建,若无返回值,则实例化对象的结果为None
应用场景:设计模式中的单例设计模式
class Person():
# 构造方法
def __new__(cls, *args):
print('触发构造方法')
print(args)
# 若在该方法中没有返回对象(如下格式),则对象无法创建,实例化对象后返回如下结果:
# 触发构造方法
# ('zhang', 55, 'male')
return object.__new__(cls)
# 初始化方法
def __init__(self,name,age,sex):
print('触发初始化方法')
self.name = name
self.age = age
self.sex = sex
# 析构方法
def __del__(self):
print('触发析构方法')
# 实例化对象
one = Person('zhang',55,'male')
# 触发构造方法
# ('zhang', 55, 'male')
# 触发初始化方法
# 触发析构方法
4.__call__
触发机制: 把对象当作函数直接调用时,自动触发
作用: 一般用于归纳类或对象的操作步骤,方便调用
参数: 一个self,接受对象,其他根据需求
返回值: 可有可无
5.__len__
触发机制: 当时有len函数去检测当前对象的时候,自动触发
作用: 可以使用len函数检测当前对象某个数据的信息
参数: 一个self
返回值: 必须是一个整型
注意事项: len要获取什么属性的值,就在返回值中返回哪个属性的长度即可
class Demo():
alist = [1,2,3]
# 可以代替对象使用len函数,并返回一个指定的整型
def __len__(self):
return len(self.alist)
one = Demo()
res = len(one)
print(res)
6.__str__
触发机制: 当使用str或者print函数对对象进行操作时,自动触发
作用: 代替对象进行字符串的返回,可以自定义打印的信息
参数: 一个self
返回值: 必须是字符串类型
注意事项:该方法中 return 的内容 自行决定
class Demo():
alist = [1,2,3]
# 可以代替对象进行str或print的字符串信息返回
def __str__(self):
return 'whatever and wherever str'
one = Demo()
res = str(one)
print(res) # # whatever and wherever str
print(one) # whatever and wherever str
7.__repr__
触发机制:使用repr方法对当前对象进行转换时自动触发
作用: 可以设置repr函数操作对象的结果
参数: 一个self
返回值: 必须是字符串类型
注意事项:正常情况下,若没有__str__这个魔术方法,__repr__就会代替其执行
8.__bool__
触发机制: 当前使用bool函数转换对象时,自动触发。默认情况下,对象会转为True
作用: 可以代替对象进行bool类型转换,可以转换任何数据
参数: 一个self
返回值: 必须是一个bool类型的返回值
class Demo():
alist = [1,2,3]
def __bool__(self):
return bool(self.alist)
one = Demo()
res = bool(one)
print(res)
* str和repr 以及对应魔术方法的区别
1.str 和 repr函数都可以把其他类型的值专为字符串
2.若数据对象没有更明显的区别,二者结果是一样的
1.str函数会把对象转为 更适合阅读的形式
2.repr函数会把对象转为 解释器 读取的形式
n = 3398
r1 = str(n)
r2 = repr(n)
print(r1,type(r1))
print(r2,type(r2))
# 3398 <class 'str'>
# 3398 <class 'str'>
n = '398'
r1 = str(n)
r2 = repr(n)
print(r1,type(r1))
print(r2,type(r2))
# 398 <class 'str'>
# '398' <class 'str'>
19.4.2 成员相关魔术方法
1.__getattribute__
触发机制: 把访问对象成员时,自动触发,无论对象成员是否存在
作用: 可以在获取对象成员时,对数据进行一些处理
参数: 一个self接受对象,一个item接收当前访问的成员名称
返回值: 可有可无,返回的值就是访问的结果
注意事项:在当前魔术方法中,禁止对当前对象的成员进行访问,会触发递归
若想要在当前方法中访问成员,必须使用 object.__getattribute__(self,item)
2. __getattr__
触发机制:当访问对象中不存在的成员时,自动触发
作用: 防止访问不存在的成员时报错,也可以为不存在的成员进行赋值操作
参数: 一个self接受对象,一个item接收当前访问的成员名称
返回值: 可有可无
注意事项:当存在__getattribute__时,会去执行此方法
3. __setattr__
触发机制:给对象成员进行赋值时,自动触发,包括修改、添加
作用: 可以限制或管理对象成员的添加和修改操作
参数: 1.self接受对象 2.设置的成员名称 3.设置的成员值
返回值: 无
注意事项:在当前方法中 禁止给当前对象成员直接进行赋值操作,否则会触发递归
若想要赋值,使用 object.__setattr__(self,key,val)
4. __delattr__
触发机制:删除对象成员时,自动触发
作用: 可以限制对象成员的删除,还可以防止在删除不存在成员时报错
参数: 1.self接受对象 2.删除的成员名称
返回值: 无
注意事项: 当前方法中,禁止直接删除对象成员,会触发递归
若要删除,使用 object.__delattr__(self,item)
- try: except
class Person():
name = 'zhang'
age = 40
sex = 'male'
def __init__(self,n,a,s):
self.name = n
self.age = a
self.sex = s
def say(self):
print('make a speech')
# 获取对象成员时,自动触发
def __getattribute__(self, item):
# print(self.name) 不允许此操作,会报错
# 判断是否存在属性,注意!!
# try:
res = object.__getattribute__(self,item)
# 方法中可以对访问的成员数据进行处理
return res[0]+'**'+res[-1]
# except:
# return False
# 当访问不存在的成员时,自动触发
def __getattr__(self, item):
print(item)
return False
def __setattr__(self, key, value):
print(self,key,value)
object.__setattr__(self,key,value)
def __delattr__(self, item):
print(item)
z = Person('zhangs',45,'male')
print(z.one)
z.one = 'this is new'
print(z.one)
del z.one
访问成员调用顺序 !!!
1.__getattribute__
2.数据描述符
3.调用当前对象的成员
4.调用当前类的成员
5.非数据描述符
6.调用父类的成员
7.__getattr__
- 以上步骤是调用某个成员的顺序,前面的能够调用成功,后面的就不再执行
数据描述符:同时具备三个魔术方法的类就是
非数据描述符:不同时具备