16. super用法
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。总之前人留下的经验就是:保持一致性。要不全部用类名调用父类,要不就全部用 super,不要一半一半。
17. 单例模式
1.
使用__new__
方法
如果想使得某个类从始至终最多只有一个实例,使用__new__方法会很简单。Python中类是通过__new__来创建实例的:
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton,cls).__new__(cls, *args, **kwargs)
return cls._instance
if __name__ == '__main__':
class A(Singleton):
def __init__(self, s):
self.s = s
a = A('apple')
b = A('banana')
print id(a), a.s
print id(b), b.s
结果:
29922256 banana
29922256 banana
通过__new__方法,将类的实例在创建的时候绑定到类属性_inst上。如果cls._inst为None,说明类还未实例化,实例化并将实例绑定到cls._inst,以后每次实例化的时候都返回第一次实例化创建的实例。注意从Singleton派生子类的时候,不要重载__new__。
2.共享属性
有时候我们并不关心生成的实例是否具有同一id,而只关心其状态和行为方式。我们可以允许许多个实例被创建,但所有的实例都共享状态和行为方式:
class Brog(object):
_shared_state = {}
def __new__(cls, *args, **kwargs):
obj = super(Brog, cls).__new__(cls, *args, **kwargs)
obj.__dict__ = cls._shared_state
return obj
if __name__ == '__main__':
class Example(Brog):
pass
a = Example()
b = Example()
c = Example()
adict = {}
j = 0
for i in a,b,c:
adict[i] = j
j += 1
for i in a,b,c:
print adict[i]
结果:
0
1
2
将所有实例的__dict__指向同一个字典,这样实例就共享相同的方法和属性。对任何实例的名字属性的设置,无论是在__init__中修改还是直接修改,所有的实例都会受到影响。不过实例的id是不同的。要保证类实例能共享属性,但不和子类共享,注意使用cls._shared_state,而不是Borg._shared_state。因为实例是不同的id,所以每个实例都可以做字典的key.
3. import方法
python模块是天然的单例模式
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
my_singleton.foo()
18. 协程
简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.
Python里最常见的yield就是协程的思想!
19. 引用和copy(),deepcopy()的区别
import copy
a = [1,2,3,4,['a', 'b']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
a.append(5)
a[4].append('c')
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
20. read,readline和readlines
- read 读取整个文件
- readline 读取下一行,使用生成器方法
- readlines 读取整个文件到一个迭代器以供我们遍历