Python中用于实现惰性getter的正确模式是什么?

时间:2012-03-12 05:31:37

标签: python design-patterns getter

有时候我喜欢为一个对象编写getter属性,这样第一次调用它们时,繁重的工作就会完成一次,并且该值会被保存并在将来的调用中返回。在objective-c中,我将使用ivar或静态变量来保存此值。类似的东西:

- (id)foo
{
    if ( _foo == nil )
    {
        _foo = // hard work to figure out foo
    }
    return _foo
}

这种相同的模式在Python中是否能够很好地运行,或者有更多可接受的方法吗?到目前为止我基本上都是一样的。我不喜欢我的解决方案是我的对象变得混乱了这些值的值和getter:

def foo(self):
    if not hasattr(self, "mFoo":
        self.mFoo = # heavy lifting to compute foo
    return self.mFoo

4 个答案:

答案 0 :(得分:7)

请改用lazy property。吸毒者是so 1990's

答案 1 :(得分:3)

不是每次都进行明确的“hasattr”测试,而是让Python运行时为你做。在类中定义__getattr__,仅在引用未定义属性时调用。

class Sth(object):
    @property
    def a(self):
        print "property a"
        return self._a

    def _a_compute(self):
        # put expensive computation code here
        print "_a_compute"
        return 1000

    def __getattr__(self, attr):
        print "__getattr__"
        if attr == '_a':
            self._a = self._a_compute()
            return self._a


ss = Sth()
print "first time"
print ss.a
print
print "second time"
print ss.a

打印以下内容:

first time
property a
__getattr__
_a_compute
1000

second time
property a
1000

您可以省略该属性并直接对{a}进行__getattr__测试,但是对于像内省或内省这样的内容,您无法将{a'作为dir中的属性的可见性IDE自动完成。

答案 2 :(得分:1)

您可以在Python中使用完全相同的模式。你好像担心是否必须一直做my_object.get_foo()是Pythonic。值得庆幸的是,Python为您提供了一个很好的工具,可以使用properties

的形式
class my_class(object):

     @property
     def foo(self):
       # calculate if needed
       return self._foo

这使得您可以使用使用作为属性,即使它是作为函数实现的。即,用户将执行my_object.foo,而不关心它在幕后运行功能。

要注意的另一件事是Python惯例说私有属性拼写_foo而不是mFoo

答案 3 :(得分:1)

我会做这样的事情:

@property
def foo(self):
    return self._foo_value if hasattr(self, '_foo_value') else calculate_foo()

def calculate_foo(self):
    self._foo_value = # heavy foo calculation
    return self._foo_value

现在你可以使用以下方式访问已经计算过的“foo”:

object.foo