Python:高级主题之(属性取值和赋值过程、属性描述符、装饰器)

背景

学习了Javascript才知道原来属性的取值和赋值操作访问的“位置”可能不同、还有词法作用域这个东西,这也是我学习任何一门语言会注意的两个知识点,Python的作用域和Javascript几乎一致,这里就不做解释,本文重点介绍一下三个概念:

  1. 属性取值和赋值过程
  2. 属性描述符
  3. 装饰器

本文最好会利用这些知识介绍:如何实现自定义的@staticmethod和@classmethod。

属性取值和赋值过程


  • 一切皆是对象,类型也是对象。
  • 对象包含一个__class__属性指向其所属类型。
  • 对象包含一个__dict__属性指向其所包含的成员(属性和方法)。

取值过程(下面是伪代码)

__getattribute__(property) logic:

descripter = find first descripter in class and bases's dict(property)
if descripter:
    return descripter.__get__(instance, instance.__class__)
else:
    if value in instance.__dict__
        return value

    value = find first value in class and bases's dict(property)
    if value is a function:
        return bounded function(value)
    else:
        return value

raise AttributeNotFundedException

赋值过程(下面是伪代码)

__setattr__(property, value)logic:

descripter = find first descripter in class and bases's dict(property)
if descripter:
    descripter.__set__(instance, value)
else:
    instance.__dict__[property] = value

根据取值和赋值过程的逻辑可以得出以下结论

  1. 赋值和取值的位置可能不同。
  2. 取值过程的伪代码第11行会返回绑定方法(我们在Javascript经常会让某个函数绑定到指定的作用域,和这个概念是一样的)。
  3. 取值和赋值过程都会先查找属性描述符,也就是说:属性描述的优先级最高,下文会介绍属性描述符。

属性描述符

什么是属性描述符?属性描述符就是一个类型,实现了三个魔法方法而已:__set__、__get__和__del__,属性描述符一般不会独立使用,必须存储在类型的__dict__中才有意义,这样才会参与到属性的取值和赋值过程,具体参见上文。

属性描述符

#属性描述符
class Descripter:
    def __get__(self, instance, owner):
        print(self, instance, owner)

    def __set__(self, instance, value):
        print(self, instance, value)
测试代码

class TestClass:
    Des = Descripter()


    def __getattribute__(self, name):
        print("before __getattribute__")
        return    super(TestClass, self).__getattribute__(name)
        print("after __getattribute__")

    def __setattr__(self, name, value):
        print("before __setattr__")
        super(TestClass, self).__setattr__(name, value)
        print("after __setattr__")

test1 = TestClass()
test2 = TestClass()

test1.Des = None
test2.Des

输出结果

1 before __setattr__
2 <__main__.Descripter object at 0x01D9A030> <__main__.TestClass object at 0x01D9A090> None
3 after __setattr__
4 before __getattribute__
5 <__main__.Descripter object at 0x01D9A030> <__main__.TestClass object at 0x01D9A0B0> <class '__main__.TestClass'>

结论

类型的多个实例共享同一个属性描述符实例,属性描述符的优先级高于实例的__dict__,具体自己可以测试一下。


转载自: http://www.cnblogs.com/happyframework/p/3260233.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值