2016年06月09日 作者:SRJOGLEKAR246 提到属性访问,大多数人仅仅知道一件事,即点运算符’.’(就像x.some_attribute)。简单来说,属性访问是从一个你已有的对象中获得另一个对象的方法。对于那些使用Python而不愿深入探索的人来说,上一句话可能非常简单。然而,这个看起来非常容易的东西其实深藏着许多秘密。 让我们一个个地来看每个部分吧。 __dict__属性 Python中的每个对象都有一个__dict__属性。这个字典,或者说类字典的(我将在后面解释)对象包含了这个对象本身的所有属性。它存储着这些属性的名称与值的键值对。 这里是一个例子:
对象的__dict__属性非常容易理解。它以Python字典的方式工作,事实上,它就是一个字典。
有一个原因可以解释这一奇怪的实现。如果你不想深入细节,仅仅需要知道这样做是为了保证Python解释器能够正常工作,并且能够提升某些优化性能。如果想知道更详细的解释,请到StackOverflow中看一看 Scott H的回答。 描述符 描述符是一个在其属性中至少包含下列魔法方法其中之一的对象,即__get__, __set__或者__delete__(记住,Python中方法本质上也是对象)。注意,我们要讨论的是对象,而类可能实现了它们,也可能没有实现。 描述符可以帮助你在Python中定义一个对象的属性的行为。通过上面所提到的魔法方法,你可以分别实现获取、设置及删除对象中的属性(由描述符所描述的)。Python中存在两种描述符——数据描述符和非数据描述符。 非数据描述符仅仅定义了__get__属性。所有其他类型的都属于数据描述符。你自然会想到,为什么这两类描述符会这样命令。答案很直观。通常,一个对象的数据相关的属性我们才会趋向于“设置”或者“删除”它。其他属性,例如方法本身,我们不会这样做。所以这些描述符被称作非数据描述符。 如同Python中其他许多东西一样,这不是一个必须遵守的规则,而是一个惯例。你也可以用数据描述符来描述一个方法。但是这样的话,你的__get__应当返回一个函数。 这里有一个例子。两个类分别定义了数据描述符对象和非数据描述符对象:
让我们在一些代码中使用这些类:
现在让我们看一下Python中管理属性访问的高层的规则 规则 这里一字不差地引用了Shalabh Chatuvedi的书中的内容,流程如下: 1. 如果attrname是一个objectname的特殊(例如,Python提供的)属性,返回它; 2. 检查objectname.__class__.__dict__中的attrname。如果它存在并且是一个数据描述符,返回这个描述符本身。搜索所有objectname.__class__的基类并做相同的操作; 3. 检查objectname.__dict__中的attrname,如果找到即返回。如果objectname是一个类,同时搜索它的基类。如果它是类并且一个描述符存在其中或是基类中,返回这个描述符的结果; 4. 检查objectname.__class__.__dict__中的attrname。如果存在并且是一个非数据描述符,返回这个描述符的结果。如果存在并且不是一个描述符,直接返回。如果是存在并且是一个数据描述符,我们不应当来这里因为我们应当已经在第二步时返回了。搜索所有的objectname.__class__的基类并做同样的操作。 5. 抛出AttributeError异常。 为了更好的说明,这里有一些使用我们在描述符一节所写的代码(请再看一遍以便有个更清醒的认识)所做的测试: data_attr_child是some_object类中的一个描述符。所以你可以重写它。同样,ChildClass(‘desc3’)中的version已经使用了,不是ParentClass中的那一个。
data_attr_parent的属性行为和data_attr_child的类似。
设置属性的规则 这里要比获得属性的规则简单许多。在此引用Shalabh的书:
就是这些! __slots__ 简单得说,__slots__是Python中阻止对象拥有它自己的__dict__属性的方式。这意味着,如果你在类里定义了__slots__,你就不可以给它的对象设置任意属性(除了在’slots’中定义的)。 这里有一个这样的类的例子:
正如Guido van Rossum他自己在他的博客中所提到的,Python的__slots__实现是为了带来效率的提升,而不是严格限制属性设置。直观地说:假设你有一个类,你想要构造大规模的它的对象。你不希望对象本身拥有灵活的动态的属性,而是想要更高的效率。由于slots本质上去掉了每个对象的__dict__属性,这样你会节省大量的内存。 有趣的是,Python中slots是由描述符实现的。 |
|
来自: River_LaLaLa > 《Python》