常用魔术方法总结
python 中常见的魔术方法:
1、__init__(self, item):方法
在实例化对象时自动执行,多用于对对象属性进行初始化。
2、__new__(cls,item):方法
实例化对象时自触发,在__init__ 方法之前执行,作为控制对象的生成过程,实现单例设计模式。
class Human:
__instance = None
def __init__(self, name):
print('init method for {}'.format(name))
def __new__(cls, *args,**kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(Human)
return cls.__instance
3、__del__(self):方法
对象被系统回收的时候自动触发(del
不一定触发)
4、__getattr__(self, item): 方法
在访问对象的item属性的时候,如果对象和他的父类并没有这个相应的属性,方法,那么将会调用这个方法来处理。有相应的属性或方法时调用对象实例的相应属性或方法。
参数 item 代表 调用的属性或方法。
class Foo:
def __init__(self, x):
self.x = x
@property
def get_01(self):
print(111)
return self.x
def __getattr__(self, item):
# 当实例对象的的 f.a属性不存再时执行的操作
print('执行的是我')
print(item)
return self.x
f1 = Foo(10)
print(f1.get_01) # 111,10
print(f1.a) # 执行的是我 , a, 10
print(f1.get_02) # 执行的是我 , get_02, 10
5.__setattr__(self, item, value): 方法
会拦截所有属性的的赋值语句。如果定义了这个方法,self.arrt = value 就会变成self,__setattr__("attr", value).这个需要注意。
当在__setattr__方法内对属性进行赋值是,不可使用self.attr = value,因为他会再次调用self,__setattr__("attr", value),则会形成无穷递归循环,
最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name'] = value.
class Student:
def __init__(self,item):
self.x=item
def __getattr__(self, item):
return item + ' is not exits'
def __setattr__(self, key, value):
print("执行我")
self.__dict__[key] = value+2
s = Student(10) # # 调用__setattr__ 方法 执行我
print(s.x) # 12
print(s.name) # 调用__getattr__方法 输出'name is not exits'
s.age = 1 # 调用__setattr__ 方法
print(s.age) # 输出 3
6、__getattribute__(self,item):方法
访问成员属性时自动触发,无论成员属性是否存在
lass Human:
def __init__(self):
self.name = 'Python'
self.sex = 'male'
self.age = 18
def __getattribute__(self, item):
print('getattribute call by %s' % self)
# return self.name 如果返回的是self.name,则会报错
return super().__getattribute__(item)
def eat(self):
print('eat method is running')
human = Human()
print(human.name)
>>>>>>>>getattribute call by <__main__.Human object at 0x000001D633849240>
>>>>>>>>Python
7、__delattr__(sefl,item):方法
删除对象时自动执行,可以在删除对象时做一些其他工作
class Human:
def __init__(self):
self.name = 'Python'
self.sex = 'male'
def __delattr__(self, item):
if item == 'name': # 当删除的对象成员名称为name时,不执行删除操作,即限制了删除name成员
pass
else:
# del self.sex 如果执行此行,则会报错,递归数过大
return super().__delattr__(item)
def eat(self):
print('eat method is running')
human = Human()
del human.name # 不会删除name属性
del human.sex # 会删除sex属性
print(human.name)
print(human.sex)
>>>>Python
>>>>AttributeError: 'Human' object has no attribute 'sex'
8、__str__(self): 方法 打印实例对象时 自动被调用
class Student:
def __init__(self,item):
self.x=item
def __str__(self):
print("打印对象时调用")
return "111"
s=Student(10)
print(s) # 打印对象时调用 111
9、__len__(self):方法
使用 len检测对象的长度时自动触发
class Human:
def __init__(self, name):
self.name = name
def __len__(self):
# 必须有返回值,而且必须是整形
return len(self.name)
human = Human('chengjie')
print(len(human)) #如果没有实现__len__, 则无法直接使用len(human), 否则报TypeError: object of type 'Human' has no len(), 实现了__len__后,可以根据需要
>>>>8
10、__call__(self,*args,**kwargs):方法
实例化对象当做函数调用时自动触发。
class MakeCake:
def buy_yuan_liao(self):
print('购买原料')
def huo_mian(self):
print('和面')
def __call__(self, *args, **kwargs):
self.buy_yuan_liao()
self.huo_mian()
print('蛋糕制作完成')
maek_cake = MakeCake() # 实例化一个类MakeCake的对象make_cake
maek_cake() # 把对象make_cake当做一个函数调用
>>>>购买原料
和面
蛋糕制作完成