Python @property 与方法性能 - 使用哪一个?

Posted

技术标签:

【中文标题】Python @property 与方法性能 - 使用哪一个?【英文标题】:Python @property versus method performance - which one to use? 【发布时间】:2010-11-11 15:28:06 【问题描述】:

我已经编写了一些使用对象属性的代码:

class Foo:
    def __init__(self):
        self.bar = "baz"
myFoo = Foo()
print (myFoo.bar)

现在我想做一些花哨的计算来返回bar。我可以使用@property 使方法充当bar 的属性,或者我可以重构我的代码以使用myFoo.bar()

我应该返回并为我的所有bar 访问添加括号还是使用@property?假设我的代码库现在很小,但由于熵,它会增加。

【问题讨论】:

【参考方案1】:

如果它在逻辑上是对象的属性/属性,我会说将其保留为属性。如果它可能被参数化,我的意思是你可能想要调用 myFoo.bar(someArgs) 然后现在咬紧牙关,让它成为一个方法。

在大多数情况下,性能不太可能成为问题。

【讨论】:

【参考方案2】:

当性能如此容易衡量时,不必担心性能:

$ python -mtimeit -s'class X(object):
>   @property
>   def y(self): return 23
> x=X()' 'x.y'
1000000 loops, best of 3: 0.685 usec per loop
$ python -mtimeit -s'class X(object):

  def y(self): return 23
x=X()' 'x.y()'
1000000 loops, best of 3: 0.447 usec per loop
$ 

(在我的慢速笔记本电脑上——如果你想知道为什么第二种情况没有辅助 shell 提示,那是因为我从第一种情况下用 bash 中的向上箭头构建它,并且重复了换行结构但不是提示!-)。

因此,除非您知道 200+ 纳秒左右会很重要(您试图最大限度地优化一个紧密的内部循环),否则您可以使用属性方法;如果您进行一些计算来获取该值,那么 200 纳秒以上的时间当然会占总时间的一小部分。

我确实同意其他答案,即如果计算变得过于繁重,或者您可能需要参数等,则最好使用一种方法 - 同样,如果您需要将可调用对象存储在某处但仅稍后调用它,以及其他花哨的函数式编程技巧;但我想定量地说明性能点,因为timeit 使这样的测量变得如此简单!-)

【讨论】:

如果不计算 x 实例创建,结果会更接近(百分比),(我在 iPython 中使用了 %timeit 魔术函数):x = X(); %timeit x.y -> 1000000 次循环,3 次中的最佳:每个循环 211 ns; x = X(); %timeit x.y() -> 10000000 次循环,3 次中的最佳:每个循环 169 ns【参考方案3】:

在这种情况下,我发现选择最有意义的选项会更好。像这样的微小差异不会导致任何明显的性能损失。更重要的是您的代码易于使用和维护。

至于在使用方法和@property 之间进行选择,这是一个口味问题,但由于属性将自己伪装成简单的属性,因此无需进行任何详细说明。一个方法表明它可能是一项昂贵的操作,使用您的代码的开发人员会考虑缓存该值,而不是一次又一次地获取它。

再说一次,不要只考虑性能,始终考虑可维护性与性能。随着时间的推移,计算机变得越来越快。同样不代表代码的可读性。

总之,如果你想得到一个简单的计算值,@property是一个很好的选择;如果你想计算一个精确的值,一个方法会更好。

【讨论】:

【参考方案4】:

我会进行重构,但只是为了风格问题 - 我似乎更清楚的是,“花式计算”可能会通过方法调用进行,而我希望属性几乎是无操作的,但这是一个品味问题。

不要担心装饰器的性能...如果您认为这可能是一个问题,请测量两种情况下的性能并查看它增加了多少(我的猜测是,如果与你花哨的计算)。

【讨论】:

【参考方案5】:

我同意这里大多数人的说法,几年前我在 Python 中构建水文模型时做了很多测量,发现使用 @property 所带来的速度完全被计算所掩盖。

例如,创建方法局部变量(在我的计算中删除“点因子”比删除@property 提高了几乎一个数量级的性能(这些结果是中等规模应用程序的平均值)。

如果有必要,我会寻找其他地方进行优化,并首先专注于编写好的、可维护的代码。此时,如果 @property 在您的情况下很直观,请使用它。如果没有,请制定一个方法。

【讨论】:

【参考方案6】:

这正是@property 的意义所在。

【讨论】:

以上是关于Python @property 与方法性能 - 使用哪一个?的主要内容,如果未能解决你的问题,请参考以下文章

python学习8_1 面向对象(继承多态封装)以及零散概念(组合,property,绑定方法与非绑定方法,反射,内置函数)

17有关python面向对象编程的提高多继承多态类属性动态添加与限制添加属性与方法@property

python 3全栈开发-面向对象之绑定方法(classmethod与staticmethod的区别)多态封装的特性property

Python装饰器之 property()

Python装饰器之 property()

python中@property的作用和getter setter的解释