1.__new__ 类的构造方法,实例化时调用该方法返回对象,再调用init 方法进行初始化。new 方法的返回值决定对象到底是什么。
1 2 3 4 5 6 7 8 9 10 11 12 class Bar(object): def __init__(self, cls): self.cls = cls class Foo(object): def __new__(cls, *args, **kwargs): # return super(Foo,cls).__new__(cls,*args, **kwargs) return Bar(cls) obj = Foo() print(obj)
单例模式: 1 2 3 4 5 6 7 8 9 10 11 12 class Foo(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, "_Foo__instance"): cls.__instance = object.__new__(cls) return cls.__instance o1 = Foo() o2 = Foo() print(id(o1), o1) print(id(o2), o2)
2.__iter__ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Foo(object): # def __iter__(self): # return iter([11,22,33]) def __iter__(self): yield 1 yield 2 yield 3 obj = Foo() for item in obj: print(item)
可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了iter 方法。iter 方法需要返回一个迭代器(生成器也是一种特殊的迭代器), 当一个对象内部实现了iter 方法,就变为可迭代对象,就可以for循环。 iter()函数是内置方法,用于生成一个可迭代对象, 用法:
- iter(object) object必须是集合对象,且支持迭代协议(iteration protocol)或者支持序列协议(sequence protocol)。 说白了,也就是实现了iter ()方法或者getitem ()方法。
1 2 3 l = [1, 2, 3] for i in iter(l): print(i)
- iter(object, sentinel) 如果传递了第二个参数,则object必须是一个可调用的对象(如,函数)。此时,iter创建了一个迭代器对象,每次调用这个迭代器对象的next ()方法时,都会调用object。如果next 的返回值等于sentinel,则抛出StopIteration异常,否则返回下一个值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class TestIter(object): def __init__(self): self.l=[1,2,3,4,5] self.i=iter(self.l) def __call__(self): #定义了__call__方法的类的实例是可调用的 item = next(self.i) print ("__call__ is called,which would return",item) return item def __iter__(self): #支持迭代协议(即定义有__iter__()函数) print ("__iter__ is called!!") return iter(self.l) t = TestIter() # t是可调用的 t1 = iter(t, 3) # t必须是callable的,否则无法返回callable_iterator print(callable(t)) for i in t1: print(i) # 它每次在调用的时候,都会调用__call__函数,并且最后输出3就停止了。 True __call__ is called,which would return 1 1 __call__ is called,which would return 2 2 __call__ is called,which would return 3
应用: wtforms中,模板中循环form对象,其内部就是实现了iter 方法。
3.__mro__ python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如
1 2 >>> F.mro() #等同于F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
补充(钻石继承问题) 新式类: 经典类:
==super的本质 :不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的==
4.__dict__ 类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类dict 里的
对象的dict 中存储了一些self.xxx的一些东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Foo(object): key = 1234 def __init__(self, name, age): self.name = name self.age = age def run(self): print("running...") obj = Foo("Jack", 23) print("obj", obj.__dict__) print("Foo", Foo.__dict__) ### 结果 obj {'name': 'Jack', 'age': 23} Foo {'__module__': '__main__', 'key': 1234, '__init__': <function Foo.__init__ at 0x00000139AD9E9D08>, 'run': <function Foo.run at 0x00000139AD9E9B70>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
5.__slot__ 为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的slots 变量,来限制该class能添加的属性:
1 2 class A(object): __slots__ = 'name', 'age'
执行如下:
1 2 3 obj = A() obj.name = "Jack" obj.score = 100
结果:
1 2 3 4 Traceback (most recent call last): File "D:/django_test/df/test.py", line 356, in <module> obj.score = 100 AttributeError: 'A' object has no attribute 'score'
由于’score’没有被放到slots 中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。
使用slots 要注意,slots 定义的属性仅对当前类起作用,对继承的子类是不起作用的:
1 2 3 4 5 6 class B(A): pass obj = B() obj.name = "Jack" obj.score = 100
除非在子类中也定义slots ,这样,子类允许定义的属性就是自身的slots 加上父类的slots 。
1 2 3 4 5 6 7 class B(A): __slots__ = 'score' pass obj = B() obj.name = "Jack" obj.score = 100