魔法方法
1.__init__
类在实例化的时候会触发它的执行
2. __str__
打印对象的时候会触发
class A:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name
a = A('张三', 24)
print(a)
其实打印a
这个对象的时候,调用的就是 a.__str__
这个方法,先找自己类里面有没有__str__
这个方法,没有就到object去找,object里面的__str__
一旦被调用,返回的就是这个方法的内存地址
3.__repr__
class A:
def __init__(self, name, age):
self.name = name
self.age = age
# def __str__(self):
# return self.name
def __repr__(self):
return self.name
a = A('张三', 24)
print(a)
print(str(a))
print(repr(a))
__repr__
是__str__
的备胎,当你注释掉__str__
,他就会启用__repr__
,但是当你注释掉__repr__
print(repr(a))
打印的是object里面repr 的内存地址
4.__call__
class A:
def __init__(self,name):
self.name =name
def __call__(self):
for k in self.__dict__:
print(k,self.__dict__[k])
a = A('aax')
a()
a = A('aax')()
a()对象加一个括号就是调用__call__
5.item系列
class Foo:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def __getitem__(self, item):
if hasattr(self,item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
del self.__dict__[key]
f = Foo('zz', '38', '男')
print(f['name'])
f['hobby'] = 'base'
print(f.hobby,f['hobby'])
print(f.__dict__)
del f['hobby'] # 自己实现的
def f.name # object 原生支持的 __delattr__
print(f.__dict__)
以前我们查找属性 只能f.name并不能像字典那样f['name'],我们可以用item自定义我们自己的
6 __new__
构造方法,创建一个对象
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()
print(a.x)
in new function
in init function
1
new创建self,在我们执行new的时候还没有self,所以new只能默认传类,这个时候__new__
也没有self,借助object.new(A, *args, **kwargs)创建一个新的对象,return给__init__ self。 (__new__就是一个新的裸体的人,__init__就是穿了衣服的人)
7 __eq__
class A:
def __init__(self,x,y):
self.x=x
self.y = y
def __eq__(self, other):
if self.x + self.y == other.x + other.y:
return True
else:
return False
a = A(1,2)
b = A(99,33)
print(a == b)
False
正常的情况是比较内存地址,我们重新定制这个eq方法会用我们定制的
8.__getattr__
和__setattr__
class A:
def __init__(self, name):
self.name = name
def __setattr__(self, key, value):
if type(value) is str:
self.__dict__[key] = value
else:
print('必须是字符串')
def __getattr__(self, item):
return self[item]
a = A('123')
a.name = 121
print(a.name)
__getattr__
和__setattr__
是 .拦截方法,不能用a['name'] ,对象.属性会调用__setattr__,当我们赋值的时候如果不是字符串它返回的是信息是必须是字符串,当我们用a.name修改属性值的时候如果不是字符串,返回的也是必须是字符串,当我们打印的时候就是123
9 上下文管理
class A:
def __enter__(self):
print('我在管理的时候会触发')
return 'xx'
def __exit__(self, exc_type, exc_val, exc_tb):
print('我用完了')
print('1',exc_type)
print('2',exc_val)
print('3',exc_tb)
with A() as f:# 触发类__enter__
print(f)
# 当管理完了,会触发__exit__