首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重写__setattr__ ()的成本太高

重写__setattr__ ()的成本太高
EN

Stack Overflow用户
提问于 2012-11-02 20:44:48
回答 3查看 631关注 0票数 2

我想保存时间并将对象标记为已修改,因此我编写了一个类并覆盖了它的__setattr__函数。

代码语言:javascript
复制
import time

class CacheObject(object):
    __slots__ = ('modified', 'lastAccess')
    def __init__(self):
        object.__setattr__(self,'modified',False)
        object.__setattr__(self,'lastAccess',time.time())

    def setModified(self):
        object.__setattr__(self,'modified',True)
        object.__setattr__(self,'lastAccess',time.time())

    def resetTime(self):
        object.__setattr__(self,'lastAccess',time.time())

    def __setattr__(self,name,value):
        if (not hasattr(self,name)) or object.__getattribute__(self,name)!=value: 
            object.__setattr__(self,name,value)
            self.setModified()

class example(CacheObject):
    __slots__ = ('abc',)
    def __init__(self,i):
        self.abc = i
        super(example,self).__init__()

t = time.time()
f = example(0)
for i in range(100000):
    f.abc = i

print(time.time()-t)

我测量了进程时间,它花了2秒。当我注释掉被覆盖的函数时,处理时间是0.1秒,我知道被覆盖的函数会更慢,但几乎20倍的差距太大了。我想我一定是搞错了。

采纳cfi的建议

1.消除if条件

代码语言:javascript
复制
    def __setattr__(self,name,value):
#        if (not hasattr(self,name)) or object.__getattribute__(self,name)!=value: 
            object.__setattr__(self,name,value)
            self.setModified()

运行时间降至1.9,稍有改进,但如果不更改对象,则将对象标记为已修改会在其他进程中花费更多成本,因此不是一个选项。

2.将self.func更改为classname.func(self)

代码语言:javascript
复制
def __setattr__(self,name,value):
    if (not hasattr(self,name)) or object.__getattribute__(self,name)!=value: 
        object.__setattr__(self,name,value)
        CacheObject.setModified(self)

运行时间是2.0 .so没有什么真正的改变

3)提取setmodified函数

代码语言:javascript
复制
def __setattr__(self,name,value):
    if (not hasattr(self,name)) or object.__getattribute__(self,name)!=value: 
        object.__setattr__(self,name,value)
        object.__setattr__(self,'modified',True)
        object.__setattr__(self,'lastAccess',time.time())

运行时间降到1.2!这太棒了,它确实节省了近50%的时间,尽管成本仍然很高。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-02 21:33:17

不是一个完整的答案,但有一些建议:

  1. ,你能消除价值比较吗?当然,这是对您的实现的一个功能更改。但是,如果在attributes.
  2. Every中存储比整数更复杂的对象,通过self调用方法需要经过完整的方法解析顺序检查,那么运行时的开销将会更大。我不知道Python本身是否可以做MRO缓存。可能不是因为类型-存在-动态原则。因此,您应该能够通过将任何self.method(args)更改为classname.method(self, args)来减少一些开销。这就消除了调用的MRO开销。这适用于settattr()实现中的self.setModified()。在大多数地方,您已经通过引用object.
  3. Every完成了这项工作,单个函数调用需要时间。您可以消除它们,例如将setModified的功能转移到__setattr__本身。

让我们知道每一个的时间是如何变化的。我会把实验分成两部分。

编辑:感谢你的计时数字。

开销可能看起来很大(看起来仍然是10倍)。然而,将其放在整体运行时的角度来看。换句话说:你的整个运行时中有多少时间会花在设置这些被跟踪的属性上,有多少时间会花在其他地方?

在单线程应用程序中使用Amdahl's Law is a simple rule来明确设置期望。举个例子:如果1/3的时间花在设置属性上,2/3的时间花在做其他事情上。那么,将属性设置减慢10倍只会减慢30%。花在属性上的时间百分比越小,我们需要关心的就越少。但如果你的百分比很高,这可能对你一点帮助都没有。

票数 1
EN

Stack Overflow用户

发布于 2012-11-02 23:22:03

在这里覆盖__setattr__似乎没有任何作用。您只有两个属性,modified和lastAccess。这意味着这是您唯一可以设置的属性,那么为什么要覆盖__setattr__呢?只需直接设置属性即可。

如果您希望在设置属性时发生某些事情,请将其设置为具有setter和getter的属性。它更简单,也不那么神奇。

代码语言:javascript
复制
class CacheObject(object):
    __slots__ = ('modified', 'lastAccess')

    def __init__(self):
        self.modified = False
        self.lastAccess = time.time()

    def setModified(self):
        self.modified = True
        self.lastAccess = time.time()

    def resetTime(self):
        self.lastAccess = time.time()

class example(CacheObject):
    __slots__ = ('_abc',)
    def __init__(self,i):
        self._abc = i
        super(example,self).__init__()

    @property
    def abc(self):
        self.resetTime()
        return self._abc


    @abc.setter
    def abc(self, value):
        self.setModified()
        self._abc = value
票数 0
EN

Stack Overflow用户

发布于 2017-06-08 05:39:00

这是一个老问题,但值得更新。

我在使用Python3.6的pydantic上遇到了同样的问题。

object.__setattr__(self, name, value)只是比通常在类上设置属性要慢一些。没有明显的办法绕过这一点。

如果性能很重要,那么惟一的选择就是在需要覆盖_setattr_的类中将对object.__setattr__(self, name, value)的调用保持在绝对最少。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13195510

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档