2012-03-12 26 views
6

Đôi khi tôi muốn viết các thuộc tính getter cho một đối tượng sao cho lần đầu tiên chúng được gọi, việc nâng hạng nặng được thực hiện một lần, và giá trị đó được lưu và trả về trong các cuộc gọi trong tương lai. Trong mục tiêu-c tôi sẽ sử dụng một ivar hoặc một biến tĩnh để giữ giá trị này. Một cái gì đó như:Mô hình thích hợp trong Python để thực hiện getters lười biếng là gì?

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

Mẫu này có tương tự được giữ vững trong Python hoặc có cách nào được chấp nhận hơn không? Về cơ bản tôi cũng vậy. Những gì tôi không thích về giải pháp của tôi là đối tượng của tôi bị lộn xộn với các giá trị và getters cho các giá trị đó:

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

Trả lời

1

Bạn có thể sử dụng chính xác cùng một mẫu trong Python. Bạn dường như lo lắng về việc phải làm my_object.get_foo() tất cả thời gian là Pythonic. Rất may, Python cung cấp cho bạn một công cụ phong phú cho việc ở đây theo hình thức properties:

class my_class(object): 

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

này cho phép bạn có cái gì đó là sử dụng như một thuộc tính, ngay cả khi nó được thực hiện như một hàm. tức là, người dùng sẽ làm my_object.foo và không quan tâm đến việc chạy một chức năng đằng sau hậu trường.

Điều khác cần lưu ý là quy ước Python nói rằng các thuộc tính riêng tư được đánh vần _foo thay vì mFoo.

+0

cảm ơn, @property không tham gia lớp học mặc dù vậy? –

+0

@ darren thực sự nó không, đó là những gì tôi nhận được để đăng bài ở phía bên trái của nửa đêm. :) Tôi đã sửa nó ngay bây giờ. – lvc

1

Tôi muốn làm điều gì đó như thế này:

@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 

Bây giờ bạn có thể truy cập vào "foo" thời tiết nó đã được tính toán hay không, sử dụng:

object.foo 
3

Thay vì làm một "hasattr rõ ràng "kiểm tra mọi lúc, hãy để thời gian chạy Python làm điều đó cho bạn. Xác định __getattr__ trong lớp của bạn, chỉ được gọi khi một thuộc tính không xác định được tham chiếu.

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 

In như sau:

first time 
property a 
__getattr__ 
_a_compute 
1000 

second time 
property a 
1000 

Bạn có thể bỏ qua bất động sản và có __getattr__ thử nghiệm cho 'a' trực tiếp, nhưng sau đó bạn sẽ không có khả năng hiển thị là một thuộc tính 'a' trong dir cho những thứ như nội tâm hoặc IDE tự động hoàn thành.

+0

cảm ơn, tôi đã nhầm lẫn lúc đầu tiên giữa __getattr__ và __getattribute__. Điều này có ý nghĩa mặc dù. –

Các vấn đề liên quan