加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python3-cookbook笔记:第八章 类与对象

发布时间:2020-12-20 10:07:36 所属栏目:Python 来源:网络整理
导读:python3-cookbook中每个小节以问题、解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构、函数、类等特性在某类问题上如何更好地使用。这本书对于加深Python3的理解和提升Python编程能力的都有显著帮助,特

python3-cookbook中每个小节以问题、解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构、函数、类等特性在某类问题上如何更好地使用。这本书对于加深Python3的理解和提升Python编程能力的都有显著帮助,特别是对怎么提高Python程序的性能会有很好的帮助,如果有时间的话强烈建议看一下。
本文为学习笔记,文中的内容只是根据自己的工作需要和平时使用写了书中的部分内容,并且文中的示例代码大多直接贴的原文代码,当然,代码多数都在Python3.6的环境上都验证过了的。不同领域的编程关注点也会有所不同,有兴趣的可以去看全文。
python3-cookbook:https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html

?

8.4 创建大量对象时节省内存方法

创建大量的对象非常的占内存,可能有上百万的数量,这时候可以考虑使用类的__slots__属性,它会将类的实例当成一个固定大小的数组来表示,而不是字典。

但需要注意的是,我们应该尽量少的使用这个属性,因为这种类在定义之后就不再支持添加新属性了,甚至一些类的普通特性也不支持了,比如继承等特性。

import sys


class Date:
    __slots__ = ['year',monthday']

    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day


d = Date(1,2,3)

try:
    # 不能直接通过打印sys.getsizeof(d)查看实例d的内存大小,可以通过打印它的__dict__属性来查看
     如果定义了__slots__属性后,实例就没有__dict__属性了,也就是不能动态添加新属性了
    print(sys.getsizeof(d.__dict__))
except Exception as e:
    print(e)

?

?

8.6 创建可管理的属性

当给某个对象的属性赋值时,你想给它进行一些额外的逻辑处理,比如类型检查或者合法性验证的时候,可以使用property装饰器来定义它。定义property属性时,需要注意它们的方法名(也就是属性名)需要都一样。

如果想要定义一个动态的属性时,相比于使用get/set方法的形式,使用property来定义会让Python代码更加优雅。

property基础用法示例:

 Person:
     这里的self.first_name不是重复定义,而是在property中就定义了
         这里是在对self.first_name属性赋值,会触发该属性的setter方法
        self.first_name = first_name

    @property
    def first_name(self):
        """getter方法:属性名称为方法名称,并且只有定义了getter方法,才能定义其他的setter等方法"""
        return self._first_name

     装饰器的前缀名称必须跟property装饰器修饰的方法名称一样,即属性名称
    @first_name.setter
     first_name(self,value):
        方法名称必须跟property装饰器修饰的方法名称一样,即属性名称if not isinstance(value,str):
            raise TypeError(Expected a string!!!)
        self._first_name = value

    @first_name.deleter
     first_name(self):
        raise AttributeError("Can't delete attribute!!!")


a = Person(Guido)
print(a.first_name)

:
    a.first_name = 42
 TypeError as e:
    (e)

del a.first_name
 AttributeError as e:
    print(e)
Guido
Expected a string!!!
Can't delete attribute!!!

定义动态属性:

 math


 Circle:
     radius

    @property
     area(self):
        return math.pi * self.radius ** 2

    @property
     diameter(self):
        return self.radius * 2 perimeter(self):
        return 2 * math.pi * self.radius

?

?

8.11 简化数据结构的初始化

当需要写大量的用作数据结构的类,又不想每个类都定义一个__init__方法时,可以参考以下例子。

 Structure1:
     属性名称列表,在子类中覆盖即可
    _fields = []

    __init__(self,*args):
        if len(args) != len(self._fields):
            Expected {} arguments.format(len(self._fields)))

         如果需要添加关键字参数,或者添加不在_fields中的关键字参数,也是用这个原理定义即可
        for name,value in zip(self._fields,args):
            setattr(self,name,value)


 实例化示例
 Stock(Structure1):
    _fields = [namesharesprice]


 Point(Structure1):
    _fields = [xy Circle(Structure1):
    _fields = [radiusreturn math.pi * self.radius ** 2

?

?

8.16 在类中定义多个构造器

类方法classmethod的一个主要用途就是定义多个构造器。

 time


 Date:
     day

    @classmethod
     today(cls):
        此方法就相当于第二个构造器了"""
        t = time.localtime()
         cls(t.tm_year,t.tm_mon,t.tm_mday)


 使用默认的__init__方法初始化
a = Date(2012,12,21 直接返回一个新的实例
b = Date.today()

?

?

8.25 创建缓存实例

类似单例模式,某个对象你只想创建一次,或者想要使用之前创建好的对象,就像logging模块,获取相同名称的logger永远只有一个,这个问题除了使用元类等方式,还可以借助weakref模块。但是需要保证weakref.WeakValueDictionary()缓存中的对象在其他地方还在被使用,没有被删除回收掉。

 weakref


 Spam:
     name


 这个变量也可以放在类定义中,用于保证每次类的实例化都返回的是同一个实例对象
# 但是需要保证缓存中的对象在其他地方还在被使用,没有被删除回收掉
_spam_cache = weakref.WeakValueDictionary()


 当程序中其他地方想要使用某个实例时,传入对应名称即可
 get_spam(name):
    if name not  _spam_cache:
        s = Spam(name)
        _spam_cache[name] = s
    else:
        s = _spam_cache[name]
     s


a = get_spam(foo)
b = get_spam(bar)
c = get_spam(print(a is b)   False
is c)   True

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读