资讯专栏INFORMATION COLUMN

python 属性搜索优先级和descriptor

NusterCache / 900人阅读

摘要:属性搜索优先级和定义数据描述符数据描述符非数据描述符一般情况数据型描述符非数据型描述符类调用描述符如果被重写上面代码介绍的东西会被覆盖掉除非函数内部调用否则别这么干例子

属性搜索优先级和descriptor
########################
# 定义
########################

# 数据描述符
class DataDesc(object):
    def __init__(self, *args, **kwargs):
        pass

    def __get__(self, instance, cls):
        print(instance is None)
        return "DataDesc"

    def __set__(self, instance, value):
        return None

    def __delete__(self, instance):
        return None


# 数据描述符
class DataDesc2(object):
    def __init__(self, *args, **kwargs):
        pass

    def __get__(self, instance, cls):
        return "DataDesc2"

    def __set__(self, instance, value):
        return None


# 非数据描述符
class NonDataDesc(object):
    def __init__(self, *args, **kwargs):
        pass

    def __get__(self, instance, cls):
        print(instance is None)
        return "NonDataDesc"


class Foo(object):
    test_attr = DataDesc()
    test_attr2 = DataDesc()
    test_attr3 = NonDataDesc()
    test_attr4 = "test_attr4"

    def __getattr__(self, item):
        return "hehe__getattr__"


########################
# 一般情况
########################
foo = Foo()
"""
1. foo.__dict__["test_attr4"]
2. for cls in Foo.__mro__:
       cls.__dict__["test_attr4"]
3. foo.__getattr__("test_attr4")
"""
print(foo.test_attr4)
foo.__dict__["test_attr4"] = 666
print(foo.test_attr4)
print(id(foo.test_attr4) == id(foo.__dict__["test_attr4"]))
foo.__dict__.pop("test_attr4")
print(foo.test_attr4)
print(foo.test_attr5)
print(foo.__getattr__("test_attr5"))

########################
# 数据型描述符
########################
foo = Foo()
"""
1. type(foo).__dict__["test_attr"].__get__(foo, type(foo))
2. foo.__dict__["test_attr4"]
3. for cls in Foo.__mro__:
       cls.__dict__["test_attr4"]
4. foo.__getattr__("test_attr4")
"""
print(foo.test_attr)
foo.__dict__["test_attr"] = 666
print(foo.test_attr)
print(id(foo.test_attr) == id(foo.__dict__["test_attr"]))
delattr(Foo, "test_attr")
print(foo.test_attr)
print(id(foo.test_attr) == id(foo.__dict__["test_attr"]))

########################
# 非数据型描述符
########################
foo = Foo()
"""
1. foo.__dict__["test_attr4"]
2. type(foo).__dict__["test_attr"].__get__(foo, type(foo))
3. for cls in Foo.__mro__:
       cls.__dict__["test_attr4"]
4. foo.__getattr__("test_attr4")
"""
print(foo.test_attr3)
foo.__dict__["test_attr3"] = 666
print(foo.test_attr3)
print(id(foo.test_attr3) == id(foo.__dict__["test_attr3"]))
del foo.test_attr3
print(foo.test_attr3)

########################
# 类调用描述符
########################
"""
FOO.__dict__["test_attr"].__get__(None, FOO)
"""
print(Foo.test_attr2)
print(Foo.test_attr3)

########################
# __getattribute__
########################
"""
如果被重写,上面代码介绍的东西会被覆盖掉
除非函数内部调用object.__getattribute__
否则别这么干
"""


class Foo2(object):
    test_attr = DataDesc()
    test_attr2 = DataDesc()
    test_attr3 = NonDataDesc()
    test_attr4 = "test_attr4"

    def __getattribute__(self, item):
        return "in __getattribute__"


foo = Foo2()
print(foo.test_attr3)

########################
# 例子
########################
import time


class LazyProperty(object):
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, cls):
        if instance is not None:
            val = self.func(instance)
            setattr(instance, self.func.__name__, val)
            return val


class Foo3(object):
    @LazyProperty
    def method(self):
        time.sleep(5)
        return 666


foo3 = Foo3()
time1 = time.time()
print(foo3.method)
time2 = time.time()
print(time2 - time1)
print(foo3.method)
print(time.time() - time2)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45184.html

相关文章

  • 如何正确地使用Python属性描述符

    摘要:描述符登场什么是描述符一般来说,描述符是一个具有绑定行为的对象属性,其属性的访问被描述符协议方法覆写。先看如何用描述符来解决上面逻辑重复的问题。 关于@property装饰器 在Python中我们使用@property装饰器来把对函数的调用伪装成对属性的访问。 那么为什么要这样做呢?因为@property让我们将自定义的代码同变量的访问/设定联系在了一起,同时为你的类保持一个简单的访问...

    huayeluoliuhen 评论0 收藏0
  • Python中类的属性具有惰性求值的能力

    摘要:更多描述可见文档这种惰性求值的方法在很多模块中都会使用,比如中的使用上与例子一致,如表单中的讨论在大部分情况下,让属性具有惰性求值能力的全部意义就在于提升程序性能。当不需要这个属性时就能避免进行无意义的计算,同时又能阻止该属性重复进行计算。 起步 我们希望将一个只读的属性定义为 property 属性方法,只有在访问它时才进行计算,但是,又希望把计算出的值缓存起来,不要每次访问它时都重...

    NervosNetwork 评论0 收藏0
  • Pythondescriptor(上)

    摘要:事实上实例的实现方式与上面的实例类似。其次,为了实现确实对属性的调用顺序做出了相应的调整,这些将会的下中介绍。参考资料如何理解的中基于的一些概念上中基于的一些概念下的官方文档描述符解密的官方文档 Python 在 2.2 版本中引入了descriptor(描述符)功能,也正是基于这个功能实现了新式类(new-styel class)的对象模型,同时解决了之前版本中经典类 (classi...

    yexiaobai 评论0 收藏0
  • opencv python 特征匹配

    摘要:匹配器匹配非常简单,首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行描述符距离测试,最后返回距离最近的关键点对于匹配器,首先我们必须使用创建对象。 Feature Matching Brute-Force匹配器 Brute-Force匹配非常简单,首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离最近的关键点. 对于...

    macg0406 评论0 收藏0
  • JS 装饰器,一篇就够

    摘要:的装饰器中的同样借鉴了这个语法糖,不过依赖于的方法。等同于也就是说,装饰器是一个对类进行处理的函数。别名或装饰器在控制台显示一条警告,表示该方法将废除。有了装饰器,就可以改写上面的代码。 更多文章,请在Github blog查看 在 ES6 中增加了对类对象的相关定义和操作(比如 class 和 extends ),这就使得我们在多个不同类之间共享或者扩展一些方法或者行为的时候,变得并...

    learning 评论0 收藏0

发表评论

0条评论

NusterCache

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<