2012-03-12 59 views
6

有时我喜欢为对象编写getter属性,以便第一次调用它时,完成一次繁重的工作,然后保存该值并在未来调用时返回。在objective-c中,我会使用一个ivar或一个静态变量来保存这个值。例如:Python中用于实现懒惰getter的正确模式是什么?

- (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 

回答

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

+0

谢谢,@property不去那个类,但它呢? – 2012-03-13 04:13:29

+0

@darren事实上它不会,这就是我在午夜错误的一面张贴的内容。 :)我现在修复了它。 – lvc 2012-03-13 06:35:03

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 

现在您可以访问“富”阉它已经被计算或不使用:

object.foo 
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 

你可以离开了物业,并有__getattr__测试“A”直接,但你不会有知名度,“A”为属性在dir中进行内省或IDE自动填充等操作。

+0

谢谢,我起初在__getattr__和__getattribute__之间感到困惑。这是有道理的。 – 2012-03-13 04:12:59