您的位置:首页 > 编程语言 > Python开发

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

2015-05-14 11:17 411 查看


背景

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

属性取值和赋值过程
属性描述符
装饰器

本文最好会利用这些知识介绍:如何实现自定义的@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


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

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


属性描述符

什么是属性描述符?属性描述符就是一个类型,实现了三个魔法方法而已:__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__,具体自己可以测试一下。

转载自:/article/4736932.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: