什么叫魔术方法:
在python中定义以双下划线开头,有一些python自定义的函数,并且以双下划线为结尾的函数叫做魔法函数
class Company(object): def __init__(self, employee_list): self.employee = employee_list def __getitem__(self, item): return self.employee[item] def __len__(self): return len(self.employee) company = Company(["tom", "bob", "jane"]) company1 = company[:2] print(len(company)) for em in company1: print(em)
当中间定义了__getitem__方法,就将Company变成了一个可迭代对象,调用for循环时,python会一个一个尝试,直到报错。所以打印print(len(company1))不会报错
__subclasshook__:
这个魔术方法有什么用呢?
使用__subclasshook__后只要具体类定义了与抽象类相同的方法就认为是他的子类
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def say(self): return 'say yeah' @classmethod def __subclasshook__(cls, C): if cls is A: if any("say" in B.__dict__ for B in C.__mro__): return True return NotTmplementd class B(object): def say(self): return 'hello' print issubclass(B, A) # True print isinstance(B(), A) # True print B.__dict__ # {'say': <function say at 0x7f...>, ...} print A.__subclasshook__(B) # True
3,__getattr__ 和__getattribute__区别
# __getattr__, __getattribute__ # __getattr__ 就是在查找不到属性的时候调用 from datetime import date class User: def __init__(self, info={}): self.in fo = info def __getattr__(self, item): return self.info[item] # def __getattribute__(self, item): # return "bobby" 这个是任何时候都会 进入的,不管是否报错 if __name__ == "__main__": user = User(info={"company_name": "imooc", "name": "bobby"}) print(user.test)
首先调用__getattribute__。如果类定义了__getattr__方法, 那么在__getattribute__抛出 AttributeError 的时候就会调用到__getattr__,
4,property_test
from datetime import date, datetime class User: def __init__(self, name, birthday): self.name = name self.birthday = birthday self._age = 0 # 声明不想被修改的属性 # def get_age(self): # return datetime.now().year - self.birthday.year @property def age(self): return datetime.now().year - self.birthday.year @age.setter def age(self, value): self._age = value if __name__ == "__main__": user = User("bobby", date(year=1987, month=1, day=1)) user.age = 30 print(user._age) print(user.age)
其实property主要的作用就是将方法的调用伪装为一个属性的查找方式
5,__new__和__init__区别
class User: def __new__(cls, *args, **kwargs): print(" in new ") return super().__new__(cls) def __init__(self, name): print(" in init") pass a = int() # new 是用来控制对象的生成过程, 在对象生成之前 # init是用来完善对象的 # 如果new方法不返回对象, 则不会调用init函数 if __name__ == "__main__": user = User(name="bobby")
运行结果如下:
in new in init
__new__在python3新式类才有的,python2.2之前中是没有的,这个方法允许我们在生成对象之前加逻辑,
所以他传入的参数是cls类。和__init__的根本区别在于,__new__可以自定义类的生成过程的,在__init__之前,不管是传参也好,不传参也好,都需要经过__new__方法
new 是用来控制对象的生成过程, 在对象生成之前
init是用来完善对象的
一般在框架中见得多。(用于元类编程)