2011-06-27 20 views
14

Cách tiếp cận tốt nhất để thực hiện nếu bạn muốn tạo động và tham chiếu thuộc tính lồng nhau là gì?Ghi đè __getattr__ để hỗ trợ thuộc tính lồng nhau động

Tôi đã viết một ứng dụng khách Flickr đơn giản và muốn khớp với API được ghi tài liệu càng chặt chẽ càng tốt, mà không thực sự xác định mọi phương thức. Ví dụ, để thực hiện một yêu cầu lên Flickr của flickr.people.getInfo API method:

flickr = Client() 
data = flickr.people.getInfo(user_id='xxx') 

Trong trường hợp này flickr.people.getInfo bản đồ trực tiếp với phương pháp tương ứng trong tài liệu API của họ. Khi được gọi, peoplegetInfo được tạo khi chúng được tra cứu, sau đó yêu cầu thực hiện thích hợp được xác định theo đường dẫn đến getInfo, là people.getInfo. Đây là phương pháp tôi đã sử dụng:

class Attr(object): 
    def __init__(self, client, name, parent): 
     self._client = client 
     self._name = name 
     self._parent = parent 

    def __getattr__(self, name): 
     attr = Attr(self._client, name, self) 
     setattr(self, name, attr) 
     return attr 

    def _get_path(self, path=None): 
     if path: 
      path = '.'.join((self._name, path)) 
     else: 
      path = self._name 
     if isinstance(self._parent, Attr): 
      return self._parent._get_path(path) 
     return path 

    def __call__(self, *args, **kwargs): 
     return self._client.execute_method(self._get_path(), *args, **kwargs) 

class Client(object): 
    def __getattr__(self, name): 
     attr = Attr(self, name, None) 
     setattr(self, name, attr) 
     return attr 

    def execute_method(self, method, *args, **kwargs): 
     print method, args, kwargs 

này hoạt động, nhưng tôi tò mò nếu cách tiếp cận của tôi để đối phó với nhiệm vụ thuộc tính lồng nhau/tra cứu có thể được cải thiện, hoặc nếu có bất kỳ lỗi đang ẩn nấp trong chờ đợi, unbeknownst với tôi . Đặc biệt, tôi tò mò nếu có một cách tốt hơn để tìm ra "đường dẫn" đến một thuộc tính nhất định. Ví dụ: nếu tôi gọi Client().x.y.z(), x, y, z không tồn tại và sẽ được tạo từng cái một (như __getattr__ tra cứu một thuộc tính duy nhất tại một thời điểm). Vào thời điểm z được gọi, tôi cần phải biết rằng đường dẫn đến zx.y.z.

+0

"lồng" thuộc tính được gần như luôn luôn xử lý với các đối tượng lồng nhau. Tại sao bạn phân tích cú pháp tên, khi Python có thể xử lý việc phân tích cú pháp này cho bạn? –

+0

Tôi đang tạo các đối tượng lồng nhau. Có cách nào đơn giản hơn để tìm ra đường dẫn đến thuộc tính lồng nhau không? – zeekay

+0

Khi bạn làm 'a.b.c', Python đưa' "b" 'thành' a '' __getattr__'. Bạn không cần phải lý luận ra một "con đường" hoặc bất cứ điều gì giống như nó. Bạn chỉ cần cung cấp trường hợp thích hợp của 'b' tại' a.b' và trường hợp thích hợp của 'c' và' b.c'. –

Trả lời

7

Nhờ Thomas K để chỉ ra rằng flipy đã thực hiện việc này (và có vẻ như một thư viện thú vị để tương tác với Flickr). Một cách tiếp cận sạch:

class Method(object): 
    def __init__(self, client, method_name): 
     self.client = client 
     self.method_name = method_name 

    def __getattr__(self, key): 
     return Method(self.client, '.'.join((self.method_name, key))) 

    def __call__(self, **kwargs): 
     print self.method_name, kwargs 

class Client(object): 
    def __getattr__(self, key): 
     return Method(self, key) 

Et thì đấy:

>>> c = Client() 
>>> c.some.method(x=1, y=2) 
some.method {'y': 2, 'x': 1}