python中更快的属性访问

python中更快的属性访问,python,pylint,Python,Pylint,考虑以下类别: class MyObject(object): __slots__ = ('_att1', '_att2') def __init__(self): self._att1 = None self._att2 = None @property def att1(self): """READ-ONLY property. """

考虑以下类别:

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
派生一个类,那么在派生类中使用“受保护”变量是否可以接受?就是

 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
,这让我意识到我在派生类中使用的是“受保护”变量。我决定在这里发布一个问题的原因是想知道这样做是否可以接受,这样我就可以在
pylint
中抑制这些警告。如果不是,那么处理这个问题的标准是什么

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

a.att1

我的印象是,通过执行
a.att1
python将首先查看对象字典,或插槽,就像我正在使用的示例一样。如果它在查找函数时不在那里(与的情况相同)。当在我的类定义中进行大量计算时,我宁愿访问字典或插槽中的内容,而不是使用装饰器定义的内容。在python社区中,这被认为是不好的做法吗?我之所以问这个问题,是因为
pylint
的默认配置告诉我不是这样的,我希望在考虑好标准的情况下继续工作

编辑: 让我们尽量不要讨论
\uuuuu插槽\uuuuu
和过早优化。如果可能的话 假设在我的原始帖子中,我没有使用
\uuuuu slots\uuuu
,并且所有内容都在对象的字典中。

简短回答:“过早优化是万恶之源。”

相信派林。看看你是否真的有性能问题。如果是,则分析并查找瓶颈。更改循环或数据结构可能更有效。

简短回答:“过早优化是万恶之源。”


相信派林。看看你是否真的有性能问题。如果是,则分析并查找瓶颈。更改循环或数据结构可能更有效。

带有下划线的属性不是“受保护的”,而是“私有的”——它们可能会发生更改。即使您的类是从它派生的。您应该使用父属性访问此数据


说到表演。当然,属性访问比属性访问慢一点,这仅仅是因为它涉及函数调用,但您不应该关心它。顺便说一句,它与
\uuu getattr\uuu
和所有这些东西都没有关系。属性也作为普通属性在字典中查找,它们只是实现了。带有下划线的属性不是“受保护的”,而是“私有的”——它们可能会发生更改。即使您的类是从它派生的。您应该使用父属性访问此数据


说到表演。当然,属性访问比属性访问慢一点,这仅仅是因为它涉及函数调用,但您不应该关心它。顺便说一句,它与
\uuu getattr\uuu
和所有这些东西都没有关系。属性也作为普通属性在字典中查找,它们只是实现了。Python在私有和受保护的类成员之间没有正式的区别。甚至私有和公共之间的区别也很弱,因为只要用户足够努力,任何东西都可以访问。如果私有与受保护的区别对您的应用程序有意义,您可以简单地记录
\u foo
(或
foo
)不是公共用户界面的一部分,但子类可以依赖它始终具有特定语义。(这些语义是什么取决于您。)

现在,我不知道为一个简单的只读属性这样做是否真的值得文档编写(函数调用开销可能不会太大,所以子类可以像其他所有人一样使用该属性)。但是,如果您有一个做了大量工作的属性,比如数据库查询或HTTP请求,那么将内部公开一点,以便子类只获取它们需要的部分,这可能是有意义的

如果您确实认为公开“protected”值是可取的,那么唯一的问题是是否应该在变量名前面加下划线。下划线对
dir
以及文档生成工具有一些影响,但它不会改变代码的运行方式


所以这实际上是一个代码风格的问题,而且这两种方式都不重要。您可以不使用下划线并在文档中添加大的警告文本,这样用户就知道他们不应该弄乱内部结构,或者您可以使用下划线并使pylint警告静音(如果必要,强制为子类实现者提供一些额外的文档).Python在私有类成员和受保护类成员之间没有正式的区别。甚至私有和公共之间的区别也很弱,因为只要用户足够努力,任何东西都可以访问。如果私有与受保护的区别对您的应用程序有意义,您可以简单地记录
\u foo
(或
foo
)不是公共用户界面的一部分,但子类可以依赖它始终具有特定语义。(这些语义是什么取决于您。)

现在,我不知道这是否真的值得
a._att1