面向对象-OOP-内置成员和魔术方法
1. 内置成员
#定义一个类A
class A():
name = 'cxy'
age = 24
def func(self):
print('学到头秃')
a = A()
a.h = '99'
# 获取类/对象的所属成员 类/对象.__dict__
res = A.__dict__ # 获取当前类的所属成员
res = a.__dict__ # 获取当前对象的所属成员
# 获取类的说明文档 类/对象.__doc__
【注意不管是通过类还是通过对象调用,获取的都是类的说明文档】
res = A.__doc__
res = a.__doc__
# 获取类名称组成的字符串
res = A.__name__
# 获取类所在的文件名称,如果是当前文件,显示为__main__
res = A.__module__
# __bases__ 获取当前类的父类列表
res = A.__base__ # 获取继承的第一个父类
res = A.__bases__ # 获取继承的所有的父类列表
# MRO列表 获取当前类的继承链列表
res = A.__mro__
2.方法的分类
-
对象方法:A.func(self)
特征:
-
在类中定义的方法,含有self参数
-
含有self的方法,只能使用对象进行调用,不能使用类去调用
(除非传递一个对象进去,但是不推荐:A.func(‘a’)))
-
该方法会把调用的对象传递进来
class A(): #对象方法 def func(self): print(self) a = A() a.func() >>><__main__.A object at 0x000001A6D3C05608> 【此时传递的是object】
-
-
类方法:使用装饰器 @classmethod
特征:
- 在类中定义的方法,使用装饰器 @classmethod 进行了装饰
- 方法中有cls这个行参。不需要实例化对象,直接使用类进行调用
- 会把调用这个方法的类传递进来
- 可以用对象调用,但是传递进去的依然是类
class A(): #类方法 @classmethod def func(cls): print(cls) a = A() a.func() A.func() >>><class '__main__.A'> 【此时传递的是class】 <class '__main__.A'> 【就算使用对象a去调用,传递进来的还是类】
-
绑定类方法
特征:
- 在类中定义的方法
- 只能使用类进行调用
- 不会传递对象或者类进来
class A(): # 绑定类方法 def func(): print('绑定类方法') A.func() #如果使用对象调用func(),则会报错
-
静态方法
特征:
- 在类中定义的方法,使用了 装饰器 @staticmethod 进行了装饰
- 可以使用对象或者类进行调用
- 不会传递对象或者类进来
class A(): # 静态方法 @staticmethod def func(): print('staticmethod') a = A() a.func() A.func() >>>staticmethod staticmethod
3.常用函数
class Demo():
pass
class A():
pass
class B(A):
pass
class C(A):
ccc = 'abc'
class D(B,C):
name = 'a'
__age = 20
def say(self):
pass
d = D()
'''检测类和对象相关'''
# 检测一个类是否为另一个类的子类
issubclass(子类,父类)
res = issubclass(D,B)
# 检测一个对象是否是该类或该类的子类的实例化结果
isinstance(对象,类)
res = isinstance(d,B)
print(res)
>>>True
res = isinstance(d,A)
print(res)
>>>True
res = isinstance(d,Demo)
print(res)
>>>False
'''操作类和对象成员相关'''
# 检测类/对象是否包含指定名称的成员
hasattr(对象/类,'成员名称')
res = hasattr(d,'name')
# 获取类/对象的成员(包括属性和方法)的值
getattr(对象/类,'成员名称')
res = getattr(d,'say')
# 设置类/对象的成员的值
setattr(对象/类,'成员名称','成员的值')
res = setattr(d,'name','ooo')
print(d.name)
>>>ooo
# 删除类/对象的成员,和 del 直接删除对象的成员是一样的结果
delattr(类/对象,'成员名称')
delattr(D,'name')
# 获取当前对象所以可以访问的成员的列表
# 不过一般用 对象.__dict__
dir(对象)
res = dir(d)
print(res)
4.类和对象相关的魔术方法
魔术方法就是不需要手动调用就可以自动执行的方法
1. __init__ 初始化方法 *****
触发机制:当实例化对象之后就会立即触发的方法
作用: 为当前创建的对象完成一些初始化的操作,比如:成员属性的赋值,方法的调用,打开或创建一些资源
参数: 一个self,用于接收当前对象,其它参数根据需求进行定义即可
返回值: 无
注意事项:无
2. __new__ 构造方法 ****
触发机制:实例化对象时自动触发(在__init__之前触发)
作用: 控制对象创建的过程:选择是创建还是不创建
【可以在__new__里写一些判断,以此来控制是否创建对象】
参数: 一个cls,用于接收当前类;其它参数根据初始化方法的参数进行决定
返回值: 必须返回object.__new__(cls)进行对象的创建,如果没有返回值,则实例化对象的结果为None
注意事项:
(1)__new__方法的参数和__init__方法的参数要保持一致,除了第一个参数
(2)必须返回object.__new__(cls)进行对象的创建,如果没有返回值,则实例化对象的结果为None
应用场景:设计模式中的单例设计模式(在一些特殊场景才会用到)
3. __del__ 析构方法 *****
触发机制:当该类对象被销毁时,自动触发
作用: 关闭或释放对象创建时打开或创建的一些资源
参数: 一个self,接收当前的对象
返回值:无
注意事项: 无
4. __call__ ***
触发机制: 把对象当作函数直接调用时自动触发
#比如说 a = A()
#然后 a()
作用: 一般用于归纳类或对象的操作步骤,方便调用;
【就可以直接把对象当成函数来调用,有些时候会很方便】
参数: 一个self接收当前对象,其它参数根据调用需求缺点
返回值: 可有可无
5.__len__
触发机制: 当使用len函数去检测当前对象的时候自动触发
#比如说 a = A()
#然后 len(a)
作用: 代替对象使用len函数,并返回一个指定的属性的值的整型
参数: 一个self,接收当前对象
返回值: 必须有,并且必须是一个整型
注意事项: 在__len__方法里的return代码为:
return len(self.想要获取的属性名)
6.__str__
触发机制: 当使用str或者print函数对对象进行操作时自动触发
作用: 代替对象进行字符串的返回,可以自定义打印的信息
同时也可以通过str(对象)的方式来对返回的字符串进行字符串相关操作:
#比如说:res = str(obj).split()
# print(res)
#此时就会把__str__方法返回的字符串进行切片
参数: 一个self,接收当前对象
返回值: 必须有,而且必须是字符串类型
7.__repr__
触发机制:在使用repr方法对当前对象进行转换时自动触发
作用: 可以设置repr函数操作对象的结果
参数: 一个self,接收当前对象
返回值: 必须有,而且必须是字符串类型的值
注意: 正常情况下,如果没有__str__这个魔术方法,__repr__方法就会代替__str__魔术方法
8.__bool__
触发机制: 当前使用bool函数转换当前对象时,自动触发;默认情况下,对象会转为True
作用: 可以代替对象进行bool类型的转换,可以转换任何数据
参数 : 一个self 接收对象
返回值: 必须是一个布尔类型的返回值
'''str、repr以及其对应魔术方法的区别'''
#str和repr函数都可以把其它类型的值转为字符串
num = 521
r1 = str(num)
r2 = repr(num)
print(r1,type(r1))
print(r2,type(r2))
>>>521 <class 'str'>
521 <class 'str'>
#repr解析的结果带了引号
num = '521'
r1 = str(num)
r2 = repr(num)
print(r1,type(r1))
print(r2,type(r2))
>>>521 <class 'str'>
'521' <class 'str'>
'''
str和repr函数都能够把其它类型的数据转为字符串类型
str函数会把对象 转为 更适合人类阅读的形式
repr函数会把对象 转为 解释器读取的形式
如果数据对象并没有更明显的区别,str和repr的结果是一样的
'''
5.成员相关魔术方法
## 1. __getattribute__ 优先级最高
def __getattribute__(self,item):
触发机制:访问对象成员时自动触发,无论当前成员是否存在
作用: 可以在获取对象成员时,对数据进行一些处理
参数: 一个self接收对象,一个item接收当前访问的成员名称
返回值: 可有可无,返回的值就是访问的结果
注意事项:在当前的魔术方法中,禁止对当前对象的成员进行访问,会触发递归。【就是不能使用 对象.成员 的方式】
如果想要在当前魔术方法中访问对象的成员必须使用 object 来进行访问
格式: object.__getattribute__(self,item)
## 2. __getattr__
def __getattr__(self,item):
触发机制: 当访问对象中不存在的成员时,自动触发
作用: 防止访问不存在的成员时报错,也可以为不存在的成员进行赋值操作
参数: 一个self接收当前对象,一个item接收当前访问的成员名称
返回值: 可有可无
注意事项: 当存在 __getattribute__ 方法时,会去执行 __getattribute__ 方法
也要注意,不要在当前的方法中再次去访问这个不存在的成员,会触发递归操作
## 3. __setattr__
def __setattr__(self,key,value):
触发机制: 当给对象的成员进行赋值操作时会自动触发(包括添加,修改)【注意!如果该方法中没有给对象成员赋值,那么对象成员赋值失败】
作用: 可以限制或管理对象成员的添加和修改操作
参数: 1. self 接收当前对象
2. key 设置的成员名
3. val 设置的成员值
返回值: 无
注意事项:在当前的魔术方法中禁止给当前对象的成员直接进行赋值操作,会触发递归操作
如果想要给当前对象的成员进行赋值,需要借助 object
格式: object.__setattr__(self,key,value)
## 4. __delattr__
def __delattr__(self,item):
触发机制: 当删除对象成员时自动触发。
【注意!如果该方法中没有删除对象成员,那么对象成员删除失败】
作用: 可以去限制对象成员的删除,还可以防止删除不存在成员时报错
参数: 1.self 接收当前对象
2.item 删除的成员名称
返回值: 无
注意事项: 在当前魔术方法中禁止直接删除对象的成员,会触发递归操作。
如果想要删除当前对象的成员,那么需要借助 object
格式: object.__delattr__(self,item)
#用__getattribute__方法,对接收的对象的属性进行一些操作
#比如说把name中间的字符隐藏(就是变为*)
class Person():
name = 'cxy'
def __getattribute__(self, item):
# 在方法中使用 object来获取属性值
res = object.__getattribute__(self,item)
# 在方法中可以对访问的成员数据进行处理
return res[0]+'*'+res[-1]
obj = Person()
print(obj.name)
>>>c*y
##6.访问成员的顺序
- 调用
__getattribute__
魔术方法(最先执行) - 调用数据描述符【后面会讲】
- 调用当前对象的成员
- 调用当前类的成员
- 调用非数据描述符【后面会讲】
- 调用父类的成员
- 调用
__getattr__
魔术方法(如果前面的全都不存在,才会调用“访问对象中不存在的成员时自动触发”的__getattr__魔术方法)
以上步骤时调用某个成员时的顺序,前面的能够调用成功,后面则不在执行;
也就是说,只有前面的不存在,才会去调用后面的。