目录
5. __repr__ < print(repr(对象名)) 触发 >
6. __call__ < 对象名() 或者 类名()() 触发 >
8. __del__ < del 变量名 或者 类 或者 方法名时会执行> 不需要去程序员去关心,垃圾处理机制帮助处理
提示:不知不觉就触发了这些方法, 但是,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更有益于我们阅读源码。
1. __new__ < 类名加() 触发 >
- __new__ 是真正的构造函数 ,他会将类对象 传到 cls
- 执行完后 会创造一个 真正的类空间,并赋值公共属性
- 当 类名加括号时, 会率先执行 __new__ 方法,构造出来一个 类
- 然后才 通过__init__ 方法 在真正的实例化出来一个 具体的实例
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A, *args, **kwargs)
a = A() #此时就会先去 执行 __new__ 再去执行 __init__
print(a.x)
利用 __new__ 写单例模式:
class A:
__msg = None #用来记录对象信息
def __new__(cls,*args,**kwargs):
if not cls.__msg: #当 __msg 为 None 时,证明是第一次创建对象空间
cls__msg = super().__new__(cls) #调用父类的__new__方法。 记得参数为 cls(类本身)
return cls.__msg #将对象空间返回
def __init__(self):pass
a = A()
a1 = A()
print(a)
print(a1) #两个地址相同
2. __len__ < len() 触发 >
len() 方法其实执行的是 __len__ 当类中没有__len__ 这个方法时,使用len()就会报错
class B:
def __len__(self):
print(666)
b = B()
len(b) # len 一个对象就会触发 __len__方法。
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__) #返回一个 数值型(int...)
a = A()
print(len(a)) # 返回的是 对象的属性个数
3. __hash__ < hash() 触发 >
hash() 方法其实执行的是 __hash__ 当类中没有__hash__ 这个方法时,会去执行父类的 __hash__
不可哈希的 数据类型中 __hash__ = None
class A:
def __init__(self):
self.a = 1
self.b = 2
def __hash__(self):
return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))
4. __str__ < print(对象名) 触发 >
其实 print(对象名) 执行的是 __str__ 方法
如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class A:
def __init__(self):
pass
def __str__(self):
return '太白'
a = A()
print(a) # '太白'
print('%s' % a) # '太白'
5. __item__ 系列
1 )__getitem__
class A:
def __getitem__(self,item):
print("执行我了",item) #item == 阿瑟东
return "1111"
a = A()
print(a["阿瑟东"]) # 打印出 "1111"
2)__setitem__
class A:
def __setitem__(self,key,value):
print(key,value) # k , v
a = A()
a["k"] = "v" #触发 __setitem__
1 和 2 一起连用:
class B:
def __getitem__(self,item):
return getattr(self,item) #其实返回的就是 self.item 即 self.key的值
def __setitem__(self,key,value):
setattr(self,key,value) #其实是 self.key = value
b = B()
b["k1"] = "v1"
print(b["k1"])
3)__delitem__
class B:
def __delitem__(self,key):
delattr(self,key) #手动删除
def __setitem__(self,key,value):
setattr(self,key,value) #其实是 self.key = value
b = B()
b["k1"] = "v1"
del b["k1"] #触发 __delitem__ 方法
4)__delattr__
例子二:
class B:
def __init__(self,lst):
self.lst = lst
def __getitem__(self,item):
return self.lst[item]
def __setitem__(self,key,value):
self.lst[key] = value
def __delitem__(self,key):
self.lst.pop(key)
b = B([1,2,3,4])
print(b[1]) # 2
b[2] = "as"
print(b.lst) # [1,2,"as",4]
del b[2]
print(b.lst) # [1,2,4]
例子一:
class Foo:
def __init__(self,name,key,value):
self.name=name
self.dict = {}
self.dict[key] = value
def __getitem__(self, key):
print("1313",self.dict[key])
# return self.dict[key]
def __setitem__(self, key, value):
self.__dict__[key]=value
print(key,"创建新的键值对")
def __delitem__(self, key):
print('del obj[',key,']时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.',item,'时,我执行')
self.__dict__.pop(item)
f1 = Foo("sb","A","1")
f1["A"] #会去执行 __getitem__ 方法
f1['age']=18 #会去执行 __setitem__ 方法
f1['age']=112 #修改也会去执行 __setitem__ 方法
f1['age1']=250 #修改也会去执行 __setitem__ 方法
del f1.age1 #会去执行 __delattr__ 方法
del f1['age'] #会去执行 __delitem__ 方法
f1['name']='alex' #会去执行 __setitem__ 方法
print(f1.__dict__)
6. __repr__ < print(repr(对象名)) 触发 >
简称:原形毕露
如果一个类中定义了__repr__方法,那么在repr(对象) 时,默认输出该方法的返回值。
class A:
def __init__(self):
pass
def __repr__(self):
return '太白'
a = A()
print(repr(a)) # '太白' 输出结果带引号
print('%r'%a) # '太白' 输出结果带引号
7. __call__ < 对象名() 或者 类名()() 触发 >
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
8. __eq__ < 对象名 == 对象名 会触发 >
class A:
def __init__(self):
self.a = 1
self.b = 2
def __eq__(self,obj):
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
print(a == b)
9. __del__ < del 变量名 或者 类 或者 方法名时会执行> 不需要去程序员去关心,垃圾处理机制帮助处理
析构方法,当对象在内存中被释放时,自动触发执行。
class A:
def __del__(self):
#析构方法 del A的对象会自动触发这个方法 先执行这个方法,然后才真正将其从内存中删掉
print("执行我了")
a = A()
del a
print(a)
其对象借用了操作系统的资源,还要通过析构方法归还回去:文件资源,网络资源
#一般使用情况
class A:
def __init__(self,file_path)
self.f = open(file_path)
def __del__(self):
self.f.close() #用来归还 占用的资源
a = A("文件")
10. __enter__ 和 __exit__
class A:
def __init__(self, text):
self.text = text
def __enter__(self): # 开启上下文管理器对象时触发此方法
self.text = self.text + '您来啦'
return self # 将实例化的对象返回f1
def __exit__(self, exc_type, exc_val, exc_tb): # 执行完上下文管理器对象f1时触发此方法
self.text = self.text + '这就走啦'
with A('大爷') as f1: #触发 __enter__
print(f1.text) #执行完毕后触发 #触发 __exit__
print(f1.text)
有他们可以这样操作
自定义文件管理器
class Diycontextor:
def __init__(self,name,mode):
self.name = name
self.mode = mode
def __enter__(self):
print "Hi enter here!!"
self.filehander = open(self.name,self.mode)
return self.filehander
def __exit__(self,*para):
print "Hi exit here"
self.filehander.close() #关闭文件流
with Diycontextor('py_ana.py','r') as f:
for i in f:
print i