程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(1)

python基础第十七课--OOP 让属性具有惰性求值的能力(小白piao分享)

发布于2020-03-10 20:51     阅读(1292)     评论(0)     点赞(16)     收藏(0)


什么是惰性求值?

        在某些场景中,我们可能更希望系统执行的高效性,在某些属性不被访问时,其不存在,当被访问时才会生成空间,另外生成后会将结果保存在缓存中,下次调用该属性会直接去取缓存中的值,而不是冗余地再去执行很多代码得到新的值。此过程,称之为惰性求值。

        实例代码进行解释:

class lazyproperty:
    def __init__(self,func):
        self.func = func
        print(self.func.__name__)
    def __get__(self, instance, owner):
        print(self,instance,owner)
        if instance is None:
            return self
        else:
            value = self.func(instance)
            setattr(instance,self.func.__name__,value)#为对象设置属性值,当属性不存在时创建该属性
            #或者:#instance.__dict__[self.func.__name__] = value
            return value
    #注意:此处并没有定义__set__()方法

import math
class Circle:
    def __init__(self,radius):
        self.radius = radius
    @lazyproperty
    def area(self):
        print('computing area ...')
        return self.radius ** 2 * math.pi
    @lazyproperty
    def perimetter(self):
        print('compiting perimeter ...')
        return 2*math.pi*self.radius

c = Circle(2.0)
print('1:',vars(c))#1: {'radius': 2.0} 底层字典中并没有area的属性

print(c.area)#当访问的数据不在底层的实例字典(instance.__dict__)中时,才会调用__get__();
            # 此时实例c的底层字典通过上一行得知并没有area这个属性
            #与c.area = 4.0 直接的区别是该赋值会直接将属性加入字典中。
            #而惰性求值只有在访问该属性时才会将属性插入底层字典,不访问面积时会节约空间

print('2:',vars(c))#2: {'radius': 2.0, 'area': 12.566370614359172} 底层字典中才有area的属性

print(c.area)#该次打印由于已经由上次的c.area的调用导致将area的属性插入了字典中,
            # 所以本次打印会直接在底层字典中寻找这个属性值,而不会再去调用area().
c.area = 25
print(c.area)#此时这种属性是可变的属性area: 4.0 -> 25


#通过如下方法可以是属性变为不可被修改的属性:
def lazyProperty(func):
    name = '_lazy_'+func.__name__
    print(name)
    @property #相当于:lazy.getter
    def lazy(self):
        if hasattr(self,name):
            getattr(self,name)
        else:
            value = func(self)
            setattr(self,name,value)
            print(name)
            return value  #相当于上述的__get__()

    #注意:此处并未设置@lazy.setter,所以并不能对属性值进行设置!!!如果设置了,如下:
    # 情景二:
    @lazy.setter
    def lazy(self,value):
        setattr(self,name,value)
        print(value)
    return lazy

import math
class Circle:
    def __init__(self,radius):
        self.radius = radius
    @lazyProperty
    def area(self):
        print('computing area ...')
        return self.radius ** 2 * math.pi
    @lazyProperty
    def perimetter(self):
        print('compiting perimeter ...')
        return 2*math.pi*self.radius

c = Circle(2.0)
print(c.area)
'''
computing area ...
_lazy_area
12.566370614359172
'''
c.area = 28
'''
#如果不释放上述情景二的代码:
#则属性值不可被修改:
Traceback (most recent call last):
  File "F:/PycharmProjects/class_obj/class_one.py", line 249, in <module>
    c.area = 28
AttributeError: can't set attribute

Process finished with exit code 1
'''
'''
#如果释放掉上述情景二的注释:
#则会得到:
28
'''

        代码来源于书籍,但是代码中的注释为自己的理解,望重点看下注释内容。



所属网站分类: 技术文章 > 博客

作者:我Lovepython

链接:https://www.pythonheidong.com/blog/article/251634/d024d7521f2fc97256b3/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

16 0
收藏该文
已收藏

评论内容:(最多支持255个字符)