2012-03-12 15 views
6

Bazen, bir nesne için getter niteliklerini, ilk defa çağrılacakları, ağır kaldırma işleminin bir kez yapıldığı ve bu değerin gelecekteki aramalarda kaydedilip geri gönderildiği gibi yazmak isterim. Amaç-c'de bu değeri tutmak için bir ivar veya statik bir değişken kullanacağım. gibi bir şey:Tembel alıcıları uygulamak için Python'da uygun desen nedir?

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

bu aynı desen Python iyi tutmak mı, yoksa bunu yapmanın daha kabul yolu var mı? Temelde şu ana kadar aynı şey var. Ne benim çözümü hakkında sevmiyorum benim nesne bu değerler için değerleri ve alıcılar ile darmadağın olur olmasıdır:

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

cevap

1

Tam olarak aynı modeli Python'da kullanabilirsiniz. Her zaman Pythonic my_object.get_foo() yapmak zorunda olup olmadığı konusunda endişeli görünüyorsun. Neyse ki, Python size properties şeklinde burada çalışmak için güzel bir araç verir: Bu bir fonksiyonu olarak uygulansa dahi, bir niteliği olarak kullanılan bir şey var sağlar

class my_class(object): 

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

. Yani, kullanıcılar my_object.foo'u yapacak ve onun perde arkasında bir işlev yürütmesine dikkat etmeyecektir.

Dikkat edilmesi gereken diğer bir nokta, Python sözleşmesinin, özel özelliklerin mFoo yerine _foo yazıldığını söylemesidir.

+0

Teşekkürler, @property bu sınıfa devam etmez, öyle değil mi? –

+0

@darren gerçekten de, bu gece yarısı yanlış tarafta yayınlamak için aldığım değil. :) Şimdi tamir ettim. – lvc

1

Böyle bir şey yapacağını: Zaten hesaplanmış veya değildi Hava

@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 

Artık kullanarak, "foo" erişebilir:

object.foo 
3

yerine açık bir "hasattr yapıyor "Her zaman test edin, Python çalışma zamanını sizin için yapalım. Tanımlanmamış bir öznitelik başvurulduğunda yalnızca sizin adınıza __getattr__ tanımlayın.

first time 
property a 
__getattr__ 
_a_compute 
1000 

second time 
property a 
1000 

Sen mülkü dışarıda bırakın ve 'a' doğrudan, ama o zaman, siz 'bir' bir nitelik olarak görünürlüğünü olmazdı için __getattr__ testi olabilir:

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 

aşağıdaki yazdırır Introspection veya IDE otomatik tamamlama gibi şeyler için dir'da.

+0

teşekkürler, ilk başta __getattr__ ve __getattribute__ arasında karıştırıldım. Bu olsa mantıklı. –

İlgili konular