你也许经常会听到「描述符」这个概念,但是由于大多数的程序员很少会使用到他,所以可能你并不太清楚了解它的原理,python视频教程栏目将详细介绍
推荐(免费):python视频教程
但是如果你想自己的事业来说更上一层的话,对于python的使用更加熟练的话,我认为你还是应该对描述符
的这个概念有一个清晰的了解,这对于你以后的发展有着巨大的帮助,也有利于你将来更深层次的python设计的理解。
尽管在开发的过程中,我们没有直接的使用过描述符,但是它在底层的运用却是十分频繁的存在。例如下面的这些:
function
、bound method
、unbound method
- 装是器
property
、staticmethod
、classmethod
这些是不是都很熟悉?
其实这些都与描述符有着千丝万缕的联系,这样吧,我们通过下面的文章来探讨一下描述符背后的工作原理吧。
什么是描述符?
在我们了解什么是描述符前,我们可以先找一个例子来看一下
class A: x = 10print(A.x) # 10
这个例子很简单,我们先在类A
中定义一个类属性x
,然后得出它的值。
除了本文来源gao@daima#com搞(%代@#码网@这种直接定义类属性的方法外,我们还可以这样去定义一个类属性:
class Ten: def __get__(self, obj, objtype=None): return 10class A: x = Ten() # 属性换成了一个类print(A.x) # 10
我们可以发现,这回的类属性x
不是一个具体的值了,而是一个类Ten
,通过这个Ten
定义了一个__get__
方法,返回具体的值。
因此可得出:在python中,我们可以把一个类的属性,托管给一个类,而这样的属性就是一个描述符
简而言之,描述符
是一个绑定行为
属性
而这又有着什么意思呢?
回想,我们在开发时,一般情况下,会将行为
叫做什么?行为
即一个方法。
所以我们也可以将描述符
理解为:对象的属性并非一个具体的值,而是交给了一个方法去定义。
可以想像一下,如果我们用一个方法去定义一个属性,这么做有什么好处?
有了方法,我们就可以在方法内实现自己的逻辑,最简单的,我们可以根据不同的条件,在方法内给属性赋予不同的值,就像下面这样:
class Age: def __get__(self, obj, objtype=None): if obj.name == 'zhangsan': return 20 elif obj.name == 'lisi': return 25 else: return ValueError("unknow")class Person: age = Age() def __init__(self, name): self.name = name p1 = Person('zhangsan')print(p1.age) # 20p2 = Person('lisi')print(p2.age) # 25p3 = Person('wangwu')print(p3.age) # unknow
这个例子中,age
类属性被另一个类托管了,在这个类的 __get__
中,它会根据 Person
类的属性 name
,决定 age
是什么值。
通过这样一个例子,我们可以看到,通过描述符的使用,我们可以轻易地改变一个类属性的定义方式。
描述符协议
了解了描述符的定义,现在我们把重点放到托管属性的类上。