目录
8. __getattr__和__setattr__和__delattr__
9. __getitem__和__setitem__和__delitem__
1. __init__
在类准备将自身实例化时调用
class Person(object):
"""Silly Person"""
def __new__(cls,*args,**kwargs):
print('__new__ called.')
return super(Person, cls).__new__(cls)
def __init__(self, name, age):
print('__init__ called.')
self.name = name
self.age = age
if __name__ == '__main__':
piglei = Person('piglei', 24)
print(piglei)
# 执行结果
__new__ called.
__init__ called.
<__main__.Person object at 0x7fe8524f0ac8>
2. __new__
在类准备将自身实例化时调用
用途:单例模式
class Person(object):
"""Silly Person"""
def __new__(cls,*args,**kwargs):
print('__new__ called.')
return super(Person, cls).__new__(cls)
def __init__(self, name, age):
print('__init__ called.')
self.name = name
self.age = age
if __name__ == '__main__':
piglei = Person('piglei', 24)
print(piglei)
# 执行结果
__new__ called.
__init__ called.
<__main__.Person object at 0x7fe8524f0ac8>
3. __call__
类对象当作函数直接调用
class test(object):
def __call__(self,num):
print(num)
obj = test()
obj(5) #重点,其实例对象可以像函数一样被调用
# 结果:5
4.类执行顺序
- 创建类 ==》先执行type的__init__方法
- 类实例化(创建对象),执行type的__call__方法,__call__方法的返回值就是实例化的对象
- __call__内部调用
- 类.__new__方法,创建一个对象
- 类.__init__方法,初始化对象
- __call__内部调用
class Person(object):
"""Silly Person"""
def __new__(cls,*args,**kwargs):
print('__new__ called.')
return super(Person, cls).__new__(cls)
def __init__(self, name, age):
print('__init__ called.')
self.name = name
self.age = age
if __name__ == '__main__':
piglei = Person('piglei', 24)
print(piglei)
# 执行结果
__new__ called.
__init__ called.
<__main__.Person object at 0x7fe8524f0ac8>
4. __iter__和__next__
python的可迭代对象实现
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
if self.a > 1000:
raise StopIteration()
return self.a
for n in Fib():
print(n)
5. __str__和 __repr__和__doc__
作用就是:注释
5.1 __str__
返回一个对象的描述信息
实际上str只是覆盖了repr以得到更友好的用户显示
服务对象:面向用户
class Cat:
def __init__(self, new_name, new_age):
self.name = new_name
self.age = new_age
def __str__(self):
"""返回一个对象的描述信息"""
return "名字是:%s , 年龄是:%d" % (self.name, self.age)
tom = Cat("汤姆", 30)
print(tom) # 名字是:汤姆 , 年龄是:30
5.2 __repr__
默认情况:返回对象的信息(类名+object at + 内存地址)
服务对象:面向程序
class Cat:
def __init__(self, new_name, new_age):
self.name = new_name
self.age = new_age
def __repr__(self):
"""返回一个对象的描述信息"""
return "名字是:%s , 年龄是:%d" % (self.name, self.age)
# 创建了一个对象
tom = Cat("汤姆", 30)
print(tom) # 名字是:汤姆 , 年龄是:30
5.3 __doc__
类中的注释内容
class test():
"""这是一段注释"""
a = ""
t = test()
print(t.__doc__) # 这是一段注释
6. __mro__
处理继承类中子类、父类中的方法/属性调用顺序
class A():pass
class B():pass
class C(A,B):pass
print(C.__mro__)
#结果: (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
7. __get__和__set__和__delete__
8. __getattr__和__setattr__和__delattr__
调用类属性的方法
# 在这例子中,参考了`flask源码中`的`线程间的数据隔离`
import threading
import time
try:
import greenlet
get_ident = greenlet.getcurrent
except Exception as e:
get_ident = threading.get_ident
class Local(object):
DIC = {}
def __getattr__(self, item):
ident = get_ident()
if ident in self.DIC:
return self.DIC[ident].get(item)
return None
def __setattr__(self, key, value):
ident = get_ident()
if ident in self.DIC:
self.DIC[ident][key] = value
else:
self.DIC[ident] = {key:value}
import threading
import time
obj = Local()
def task(i):
obj.xx = i
time.sleep(2)
print(obj.xx,i)
for i in range(3):
t = threading.Thread(target=task,args=(i,))
t.start()
# 结果
1 1
3 3
2 2
9. __getitem__和__setitem__和__delitem__
类的字典调用方法
class A(object):
def __init__(self):
self['B'] = "BB"
self['D'] = "DD"
del self['D']
def __setitem__(self, name, value):
'''''
@summary: 每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
'''
print("__setitem__:Set %s Value %s" % (name, value))
self.__dict__[name] = value
def __getitem__(self, name):
'''''
@summary: 当访问属性时会调用该方法
'''
print("__getitem__:No attribute named '%s'" % name)
return None
def __delitem__(self, name):
'''''
@summary: 当删除属性时调用该方法
'''
print("__delitem__:Delect attribute '%s'" % name)
del self.__dict__[name]
print(self.__dict__)
if __name__ == "__main__":
X = A()
b = X['bb']
# 结果
__setitem__:Set B Value BB
__setitem__:Set D Value DD
{'B': 'BB', 'D': 'DD'}
10. __getattribute__
-
对于类来说,type.__getattribute__()把B.x变成B.__dict__['x'].__get__(None,B)内部实现
-
def __getattribute__(self, key): "Emulate type_getattro() in Objects/typeobject.c" v = object.__getattribute__(self, key) if hasattr(v, '__get__'): return v.__get__(None, self) return v
-
描述符被__getattribute__()方法调用
-
重载__getattribute__()会阻止描述符自动调用
-
__getattribute__()只使用于新式类和对象
-
数据描述符会重载实例字典
-
非数据描述符可能会被实例字典重载
-
-
super()返回的对象会使用定制 __getattribute__()方法来调动描述符,调用super(B,obj).m()会紧邻着B的基类A搜索obj.__class__.__mro__
-
然后返回A.__dict__['m'].__get__(obj,B)
-
如果不是一个描述符,返回未改变的m
-
如果不在字典中,m会调用object.__getattribute__()查询
-
11. __dict__
存储对象的数据
class A():
def __init__(self):
self.a = 2
self.b = 3
def test(self):
print('a normal func.')
obj = A()
print(obj.__dict__) # {'a': 2, 'b': 3}
print(A.__dict__)
"""
{'__module__': '__main__',
'__init__': <function A.__init__ at 0x7f541b16a268>,
'test': <function A.test at 0x7f541b16a378>,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None
}
"""
12. __file__
执行py文件时,默认把当前目录增加到sys.path中
test.py #当前目录为 D:\user\flask\test.py
import os
print(__file__)
>>> python test.py
结果:test.py
带上文件的绝对路径
>>> python D:\user\flask\test.py
结果:D:\user\flask\test.py
13. __name__
标识执行文件的模块名
test.py
def run():
print(__name__)
if __name__ == __main__:
print(__name__) # __main__
test2.py
import test
test.run() # test