1、__call__
如果在类中实现了 __call__ 方法,那么实例对象也将成为一个可调用对象
什么是可调用对象?
可调用对象:但凡是可以把一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为可调用对象可以用函数 callable
这个魔法方法可以让类的实例行为表现的像函数一样
示例:
class Demo:
def __init__(self, x, y):
self.x, self.y = x, y
def __call__(self):
self.x, self.y = self.y, self.x
return self.x, self.y
demo = Demo(1, 2) # 创建实例
res = demo() # 实例可以象函数那样执行,并传入x y值,修改对象的x y
print(res) # (2, 1)
2、__getattr__
动态返回一个属性,当调用不存在的属性时,Python会试图调用__getattr__(self,'key')来获取属性,并且返回key。
class Student(object):
def __getattr__(self, item):
return item
x = Student()
print(x.age) # age
print(x.name) # name
3、__getattribute__
当每次调用属性时,python会无条件进入__getattribute__中,不论属性存在与否,这就是与__getattr__的区别
必须特别小心 __getattribute__ 方法,因为 Python 在查找类的方法名称时也将对其进行调用
class Student(object):
def __getattr__(self, item):
return "__getattr__ run...", item
def __getattribute__(self, item):
return "__getattribute__ run...", item
x = Student()
print(x.age) # ('__getattribute__ run...', 'age')
print(x.name) # ('__getattribute__ run...', 'name')
__getattribute__与__getattr__区别:
每次通过实例访问属性,都会经过__getattribute__函数。而当属性不存在时,仍然需要访问__getattribute__,不过接着要访问__getattr__。这就好像是一个异常处理函数。
示例:
class Student(object):
age = 18
def __getattr__(self, item):
print("not exist", item)
return "__getattr__ run...", item
def __getattribute__(self, item):
# 此处为了让其找到属性后调用object的默认__getattribute__进行返回
# 否则会引发超过最大递归次数的异常
print("__getattribute__ run...")
return object.__getattribute__(self, item)
x = Student()
print(x.age)
print("-" * 40)
print(x.name)
结果如下:
__getattribute__ run...
18
----------------------------------------
__getattribute__ run...
not exist name
('__getattr__ run...', 'name')
4、__setattr__
__setattr__会拦截所有属性的赋值语句。如果定义了这个方法,self.arrt = value 就会变成self,__setattr__("attr", value)。需要注意,当在__setattr__方法内对属性进行赋值时,不可使用self.attr = value,因为他会再次调用self,__setattr__("attr", value),则会形成无穷递归循环,最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name'] = value.
class Demo(dict):
def __getattr__(self, key):
# 继承dict类
return self[key]
def __setattr__(self, key, value):
# 改变赋值行为
self[key] = value
x = Demo()
x.age = 100
print(x.age)
5、__dict__
返回对象具有的属性与方法。对于类,是返回其全部属性与方法,对于类实例,只返回定义好的属性
ps:__dict__是dir()函数的子集,dir函数会自动寻找该对象的属性与方法(包括从父类中继承的属性)
示例
class Demo():
a = 1
b = 2
def __init__(self):
self.name = 'cc'
self.__dict__['age'] = 18
def demo(self):
pass
print(Demo.__dict__) # 可以打印出全部属性与方法地址
d = Demo()
print(d.__dict__) # 只能打印self的属性
print(dir(d))
{'__module__': '__main__', 'a': 1, 'b': 2, '__init__': <function Demo.__init__ at 0x1038a1700>, 'demo': <function Demo.demo at 0x1038a18b0>, '__dict__': <attribute '__dict__' of 'Demo' objects>, '__weakref__': <attribute '__weakref__' of 'Demo' objects>, '__doc__': None}
{'name': 'cc', 'age': 18}
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'age', 'b', 'demo', 'name']
6、__SLOTS__
允许类可以获得的属性,不能动态的添加其他的属性
示例
class Demo():
__slots__ = ('age', 'name')
d = Demo()
d.age = 18
print(d.age)
d.name = "xx"
print(d.name)
d.id=1
print(d.id) # 异常
7、__setitem__
拦截所有字典类型的赋值,需要init方法配合使用,避免出现超出最大递归深度
class Demo():
def __init__(self):
self.dict = dict()
def __setitem__(self, key, value):
print(key+"...")
self.dict[key] = value
def __getitem__(self, key):
print('调用getitem')
return self.dict[key]
d = Demo()
d["name"] = "xx"
8、__contains__
判断操作的时候会自动调用这个函数。
class Demo():
def __init__(self, list):
self.list = list
def __contains__(self, item):
print("contains run...")
return item in self.list
d = Demo([1,2,3])
res = d.__contains__(1)
print(res) # 因为__contains__定义返回的是一个表达式,所以此处返回ture
if 2 in d:
pass
结果
contains run...
True
contains run...
9、__iter__和__next__
一个类,实现了__iter__
,那么就认为它有迭代能力,通常此函数必须返回一个实现了__next__
的对象,如果自己实现了,你可以返回self
,这个返回值不是必须的;
注意,如果只实现了__iter__,那么它是迭代对象,只有同时实现了__iter__
和__next__才是迭代器。
自定义可迭代对象示例
class Myiterator(object):
def __init__(self, mylist):
self.my_list = mylist
self.current_index = 0
def __iter__(self):
return self
def __next__(self):
if self.current_index < len(self.my_list):
self.current_index += 1
return self.my_list[self.current_index - 1]
else:
raise StopIteration
class MyList(object):
def __init__(self):
self.my_list = list()
def append_item(self, item):
self.my_list.append(item)
def __iter__(self):
my_iterator = Myiterator(self.my_list)
return my_iterator
m = MyList()
m.append_item(1)
m.append_item(2)
for item in m:
print(item)
结果为1,2
自定义迭代器示例
class Myiterator(object):
def __init__(self, mylist):
self.my_list = mylist
self.current_index = 0
def __iter__(self):
return self
def __next__(self):
if self.current_index < len(self.my_list):
self.current_index += 1
return self.my_list[self.current_index - 1]
else:
raise StopIteration
m = Myiterator([1,2,3])
print(next(m))
print(next(m))
结果也为1,2
tips:python可以在魔法方法中调用内置方法
举个简单的例子
class Demo(object):
def __init__(self):
self.a = [1,2,3]
def __len__(self):
return len(self.a)
d = Demo()
print(len(d)) # 3
如果对你有帮助,可否在文章右侧点个赞再走呢~~
本文为原创,转载请注明出处
python lambda函数