博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python对象的创建和销毁
阅读量:6112 次
发布时间:2019-06-21

本文共 6171 字,大约阅读时间需要 20 分钟。

对象的创建

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

 

转载地址:http://dycka.baihongyu.com/

你可能感兴趣的文章
企业级负载平衡简介(转)
查看>>
ICCV2017 论文浏览记录
查看>>
科技巨头的交通争夺战
查看>>
当中兴安卓手机遇上农行音频通用K宝 -- 卡在“正在通讯”,一直加载中
查看>>
Shell基础之-正则表达式
查看>>
JavaScript异步之Generator、async、await
查看>>
讲讲吸顶效果与react-sticky
查看>>
c++面向对象的一些问题1 0
查看>>
直播视频流技术名词
查看>>
网易跟贴这么火,背后的某个力量不可忽视
查看>>
企业级java springboot b2bc商城系统开源源码二次开发-hystrix参数详解(八)
查看>>
java B2B2C 多租户电子商城系统- 整合企业架构的技术点
查看>>
IOC —— AOP
查看>>
比特币现金将出新招,推动比特币现金使用
查看>>
数据库的这些性能优化,你做了吗?
查看>>
某大型网站迁移总结(完结)
查看>>
mysql的innodb中事务日志(redo log)ib_logfile
查看>>
部署SSL证书后,网页内容造成页面错误提示的处理办法
查看>>
MS SQLSERVER通用存储过程分页
查看>>
60.使用Azure AI 自定义视觉服务实现物品识别Demo
查看>>