资讯专栏INFORMATION COLUMN

流畅的python:描述符

nanfeiyan / 364人阅读

摘要:这里设置的是实例属性实例属性会覆盖描述符的方法类的描述符依然存在删除实例属性再读取时就会出发描述符的方法

描述符:描述符类的实例是托管类的类属性

用于研究描述符行为的几个方法:

def cls_name(obj_or_cls):
    cls = type(obj_or_cls)
    if cls is type:
        cls = obj_or_cls
    return cls.__name__.split(".")[-1]

def display(obj):
    cls =type(obj)
    if cls is type:
        return "".format(obj.__name__)
    elif cls in [type(None), int]:
        return repr(obj)
    else:
        return "<{} object>".format(cls_name(obj))

def print_args(name, *args):
    persudo_args = ",".join(display(x) for x in args)
    print("-> {}.__{}__({}))".format(cls_name(args[0]), name, persudo_args))


class Overriding:
    """由get 和set 方法的数据描述符,也称覆盖型描述符"""

    def __get__(self, instance, owner):
        print_args("get", self, instance, owner)

    def __set__(self, instance, value):
        print_args("set", self, instance, value)


class OverridingNoGet:
    """没有get方法的数据描述符,也称覆盖型描述符"""

    def __set__(self, instance, value):
        print_args("set", self, instance, vvalue)


class NonOverriding:
    """没有set方法的非数据描述符,也称非覆盖型描述符"""

    def __get__(self, instance, owner):
        print_args("get", self, instance, owner)
class Managed:
    over = Overriding()
    over_no_get = OverridingNoGet()
    non_over = NonOverriding()

    def spam(self):
        print("-> Managed.spam({})".format(display(self)))

覆盖型描述符,也叫数据型描述符

>>> from demo import *
>>> m = Manged()
>>> m.over #get里的参数分别对应[self]Overriding实例, [instance]Managed实例,[owner]Managed类
-> Overriding.__get__(,,))
>>> Managed.over #类直接调用属性,instance的位置为None。
-> Overriding.__get__(,None,))
>>> m.over = 7 #[self]->Overriding的实例, [instance]->Managed类的实例,[value]->设置的值[7]
-> Overriding.__set__(,,7))
>>> m.over  #读取m.over, 还是出发__get__方法
-> Overriding.__get__(,,))
>>> m.__dict__["over"] = 8  #直接通过__dict__方法设置实例属性
>>> vars(m)  #__dict__属性中已经有了over属性
{"over": 8}
>>> m.over  #但是,实现了set方法的覆盖型描述符会跳过实例属性,直接读取描述符属性
-> Overriding.__get__(,,))

没有get方法的覆盖型描述符

>>> m.over_no_get #没有__get__方法,所以返回描述符实例

>>> Managed.over_no_get #直接从托管类Managed中读取描述符实例也是如此

>>> m.over_no_get = 7  #设置值时出发__set__方法
-> OverridingNoGet.__set__(,,7))
>>> m.__dict__["over_no_get"] = 7 #通过实例的__dict__属性设置名为over_no_get的实例属性
>>> m.over_no_get #现在,实例属性会覆盖描述符,因为没有定义__get__方法
7
>>> m.over_no_get = 7  #设置属性值时还是会触发描述符的__set__方法
-> OverridingNoGet.__set__(,,7))

非覆盖型描述符,也叫非数据描述符

>>> m.non_over  #出发描述符的__get__方法
-> NonOverriding.__get__(,,))
>>> m.non_over = 7 #没有__set__方法,所以没有干涉赋值操作。这里设置的是实例属性
>>> m.non_over #实例属性会覆盖描述符的__get__方法
7
>>> m.__dict__
{"non_over": 7}
>>> Managed.non_over  #类的描述符依然存在
-> NonOverriding.__get__(,None,))
>>> del m.non_over #删除实例属性
>>> m.__dict__
{}
>>> m.non_over #再读取m.non_over时就会出发描述符的__get__方法
-> NonOverriding.__get__(,,))


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

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

相关文章

  • Bottle框架中装饰器类和描述应用

    摘要:最近在阅读微型框架的源码,发现了中有一个既是装饰器类又是描述符的有趣实现。所以第三版的代码可以这样写第三版的代码没有使用装饰器,而是使用了描述符这个技巧。更大的问题来自如何将描述符与装饰器结合起来,因为是一个类而不是方法。 最近在阅读Python微型Web框架Bottle的源码,发现了Bottle中有一个既是装饰器类又是描述符的有趣实现。刚好这两个点是Python比较的难理解,又混合在...

    Panda 评论0 收藏0
  • Python属性描述

    摘要:下面我们用描述符来实现中的动态属性和特性中提及的订单结算代码第四版使用描述符实现订单结算功能描述符基于协议实现,无需创建子类。特性是覆盖型描述符。非覆盖型描述符没有实现方法的描述符属于非覆盖型描述符。类中定义的方法是非覆盖型描述符。 导语:本文章记录了本人在学习Python基础之元编程篇的重点知识及个人心得,打算入门Python的朋友们可以来一起学习并交流。 本文重点: 1、了解描述符...

    geekzhou 评论0 收藏0
  • python 描述解析

    摘要:之所以是这样是因为当访问一个实例描述符对象时,会将转换为。而类的字典中则有描述符对象。这主要就是因为描述符优先。此外,非数据描述符的优先级低于实例属性。参考以上就是本人对描述符的一些理解,有什么不正确的地方还请不吝指出,谢谢 什么是描述符 python描述符是一个绑定行为的对象属性,在描述符协议中,它可以通过方法重写属性的访问。这些方法有 __get__(), __set__(), 和...

    rozbo 评论0 收藏0
  • 90 % Python 开发者不知道描述应用

    摘要:由上面的注释,可以看出其实就相当于一个描述符类,而在此刻变成了一个描述符。调用这个方法可以知道,每调用一次,它都会经过描述符类的。基于描述符如何实现同样的也是一样。我想你应该对描述符在中的应用有了更深的理解。好吧,我承认我标题党了。但是这篇文章的知识点,你有极大的可能并不知道。 前段时间,我写了一篇描述符的入门级文章,从那些文章里你知道了如何定义描述符,且明白了描述符是如何工作的。 如果你还...

    番茄西红柿 评论0 收藏0

发表评论

0条评论

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