Skip to main content
 首页 » 编程设计

python之在 python 中更快的属性访问

2025年05月04日12myhome

考虑以下类:

class MyObject(object): 
 
    __slots__ = ('_att1', '_att2') 
 
    def __init__(self): 
        self._att1 = None 
        self._att2 = None 
 
    @property 
    def att1(self): 
        """READ-ONLY property. """ 
        return self._att1 
 
    @property 
    def att2(self): 
        """att2 property description. """ 
        return self._att2 
 
    @att2.setter 
    def att2(self, val): 
        self._att2 = val 

使用属性装饰器的一个优点是我们可以添加一些文档

a = MyObject() 
help(a) 
Help on MyObject in module __main__ object: 
 
class MyObject(__builtin__.object) 
 |  Methods defined here: 
 |   
 |  __init__(self) 
 |   
 |  ---------------------------------------------------------------------- 
 |  Data descriptors defined here: 
 |   
 |  att1 
 |      READ-ONLY property. 
 |   
 |  att2 
 |      att2 property description. 

如果该类打算由最终用户使用,那么访问属性就可以了 通过使用属性。

a.att2 = "new value" 

但是,如果我要从 MyObject 派生一个类,在派生类中使用“ protected ”变量是否可以接受?也就是说,

 class Derived(MyObject): 
 
     __slots__ = () 
 
     def __init__(self): 
         self._att1 = 1 
         self._att2 = 0 
 
     @property 
     def att2(self): 
         """att2 adds 1 to itself in every call. """ 
         self._att2 += 1 
         return self._att2 
 
     @att2.setter 
     def att2(self, val): 
         self._att2 = val 

我知道如果 MyObject 是来自第三方的对象,那么带下划线的属性可能会发生变化,因此如果它们发生变化,我的代码就会中断。但是,由于我使用 MyObject 作为基类,我认为将它与我自己的派生类一起使用是很好的。

我最近开始使用 pylint,它让我意识到我在派生类中使用“ protected ”变量这一事实。我决定在这里发布问题的原因是想知道这样做是否可以接受,这样我就可以在 pylint 中抑制这些警告。如果不是,那么处理这个问题的标准是什么?

我想说的另一点是关于属性访问。什么会更快

a.att1 

或

a._att1 

我的印象是,通过执行 a.att1 python 会首先查看对象字典,或者像我正在使用的示例中的插槽。如果它在查找函数时不在此处(如 __getattr__ 的情况)。在我的类定义中进行大量计算时,我宁愿访问位于字典或插槽中的内容,而不是我用装饰器定义的内容。这在 python 社区中被认为是不好的做法吗?我之所以问这个问题,是因为 pylint 的默认配置告诉我并非如此,我想继续工作时牢记良好的标准。

编辑:

让我们尽量不要讨论 __slots__ 和过早的优化。如果可能的话 假设在我原来的帖子中我没有使用 __slots__ 并且所有内容都在对象的字典中。

请您参考如下方法:

带下划线的属性不是“ protected ”,而是“私有(private)的”——它们可能会发生变化。即使你的类是从它派生的。您应该使用父属性来访问此数据。

谈到性能。当然,属性访问比属性访问慢一点,只是因为它涉及函数调用,但您不应该关心它。顺便说一句,它与 __getattr__ 和所有这些东西无关。属性也作为普通属性在字典中查找,它们只是实现了 descriptor protocol。 .