对象的创建
pyhton用__new__来创建对象(__new__相当于Java中的构建函数),对象创建好之后会立即调用__init__方法,__init__方法有个参数self就是刚才__new__创建好的那个对象。通过我们有__init__方法中给对象的属性进行赋值,或者动态线对象添加属性并赋值。
class Student(object): cnt = 0 # 用于记录该类的实例创建了多少个 def __new__(cls, *args, **kwargs): print '__new__' cls.cnt += 1 return super(Student, cls).__new__(cls, *args, **kwargs) def __init__(self): print '__init__' self.name = 'ELE' + str(self.cnt)if __name__ == '__main__': inst1 = Student() print inst2 = Student() print inst2.name print Student.cnt
输出
__new____init____new____init__ELE22
对象被当作函数来使用时,会调用对象的__call__方法,相当于是__call__重载了小括号运算符。
class Student(object): def __init__(self): self.name='orisun' def __call__(self): print '__call__' self.name = 'SOS'if __name__ == '__main__': inst = Student() print inst.name print inst() print inst.name
输出
orisun__call__SOS
用__new__实现单例模式
# coding:utf-8class Singleton1(object): name = '' def __new__(cls, *args, **kwargs): if not '_instance' in vars(cls): print 'creating instance of Singleton1' cls._instance = super(Singleton1, cls).__new__(cls) if len(args) > 0: cls.name = args[0] elif 'name' in kwargs: cls.name = kwargs[name] return cls._instanceclass Singleton2(object): name = '' def __new__(cls, *args, **kwargs): if not '_instance' in vars(cls): print 'creating instance of Singleton2' cls._instance = super(Singleton2, cls).__new__(cls) if len(args) > 0: cls.name = args[0] elif 'name' in kwargs: cls.name = kwargs['name'] return cls._instanceif __name__ == '__main__': inst1 = Singleton1('a') inst2 = Singleton1(name='b') print inst1 is inst2 print inst1.name print inst2.name print '*' * 10 inst3 = Singleton2(name='b') inst4 = Singleton2('a') print inst3 is inst4 print inst3.name print inst4.name
输出:
creating instance of Singleton1Trueaa**********creating instance of Singleton2Truebb
判断2个对象是否为同一个对象我们用了关键字is。
上例中我们充分利用了__new__()函数的两个参数:*args和**kwargs。
用__new__实现对实例的缓存
# coding:utf-8import weakrefclass Cached(object): _cache = weakref.WeakValueDictionary() def __new__(cls, *args, **kwargs): name = None if len(args) > 0: name = args[0] elif 'name' in kwargs: name = kwargs['name'] else: name = '' if not name in cls._cache: _instance = super(Cached, cls).__new__(cls) cls._cache[name] = _instance return cls._cache[name] def __init__(self, *args, **kwargs): if len(args) > 0: self.name = args[0] elif 'name' in kwargs: self.name = kwargs['name']if __name__ == '__main__': inst1 = Cached('a') inst2 = Cached(name='b') inst3 = Cached(name='a') print 'inst1 is inst2' if (inst1 is inst2) else 'inst1 is not inst2' print 'inst1 is inst3' if (inst1 is inst3) else 'inst1 is not inst3' print 'inst1.name =', inst1.name print 'inst2.name =', inst2.name print 'inst3.name =', inst3.name
输出:
inst1 is not inst2inst1 is inst3inst1.name = ainst2.name = binst3.name = a
对象的销毁
python和Java一样都是垃圾自动回收,不需要我们显示地销毁对象。执行del obj时会调用对象的__del__方法,这样对象的引用计数会减1,当对象的引用计数为0时,对象就会被销毁,内存就会被回收。
import gcclass A(object): def __init__(self): self.large_list=[i for i in xrange(10000000)] def __del__(self): print "__del__"@profiledef foo(): a=A() b=a del b del a gc.collect() printif __name__ == '__main__': foo()
我们使用memory_profiler模块监控每行代码内存的变化。
$ python -m memory_profiler a.py__del__ Filename: a.py Line # Mem usage Increment Line Contents================================================ 13 9.066 MiB 0.000 MiB @profile 14 def foo(): 15 251.051 MiB 241.984 MiB a=A() 16 251.051 MiB 0.000 MiB b=a 17 251.051 MiB 0.000 MiB del b 18 243.863 MiB -7.188 MiB del a 19 20.863 MiB -223.000 MiB gc.collect() 20 20.863 MiB 0.000 MiB print
可见del b时,对象的引用计数还没有变为0,故内存占用没有丝毫减少。当del a时,对象的引用计数变为0,内存有所减少,但是对象占用的内存并没有立即完全回收,直到显式调用gc.collect()。
通过MetaClass创建类
class MetaClass(type): def __new__(cls,class_name,base_classes,attr_dict): print '__new__ in MetaClass' return super(MetaClass,cls).__new__(cls,class_name,base_classes,attr_dict) def __init__(cls,class_name,base_classes,attr_dict): print '__init__ in MetaClass' super(MetaClass, cls).__init__(class_name,base_classes,attr_dict) def __call__(cls,*args): print '__call__ in MetaClass' print 'AAAAAAAAAAAAAAA' super(MetaClass, cls).__call__(*args) print 'BBBBBBBBBBBBBBB' class A(object): __metaclass__=MetaClass name='orisun' def __new__(cls, *args, **kwargs): print '__new__ in A' return super(A, cls).__new__(cls, *args, **kwargs) def __init__(self): print '__init__ in A'if __name__ == '__main__': print '='*40 a=A() print '='*40
输出
__new__ in MetaClass__init__ in MetaClass========================================__call__ in MetaClassAAAAAAAAAAAAAAA__new__ in A__init__ in ABBBBBBBBBBBBBBB========================================
我们看到,不需要执行类A之外的任何代码,单纯是在定义完类A之后,MetaClass中的__new__和__init__就被执行了。
当创建类实例时,MetaClass中的__call__会被执行,__call__中调用super.__call__时,类A的__new__和__init__才被调到。
用MetaClass实现单例模式
# coding:utf-8class Singleton(type): def __init__(cls, class_name, base_classes, attr_dict): cls.__instance = None super(Singleton, cls).__init__(class_name, base_classes, attr_dict) def __call__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = super(Singleton, cls).__call__(*args, **kwargs) return cls.__instance else: return cls.__instanceclass Segger(object): __metaclass__ = Singleton def __init__(self, name): self.name = nameif __name__ == '__main__': inst1 = Segger('a') inst2 = Segger('b') print inst1 is inst2 print inst1.name print inst2.name
输出:
Trueaa