2014-02-11 52 views
1

走樣我有有我要揭露爲X,Y的各種內部變量Python類,一個簡單的例子是:屬性使用__setattr__在Python

class Vec2: 
    def __init__(self): 
     self.data = [0.0, 0.0] 
     self.mapping = {'x':0, 'y':1} 

    def __getitem__(self, index): 
     return self.data[index] 

    def __setitem__(self, index, value): 
     self.data[index] = value 

    def __getattr__(self, key): 
     if key in self.mapping: 
      return self.data[self.mapping[key]] 
     else: 
      raise AttributeError 

    def _setattr__(self, key, value): 
     # ????? 
     pass 

我還以爲這是行不通的因爲__getattr__訪問自己的成員。然而,只要我不試圖定義一個__setattr__ - 即使我只是將其等於pass,我也會得到遞歸。我應該如何執行__setattr__?特別是,如果他們的鑰匙不是x或y,我應該怎麼稱呼?

此外,通常我的問題是,這是否實施所期望的行爲,如以正確的方式:

v = Vec2() 
# this 
v.x = 1.0 
v.y = 0.0 
# or this 
v[0] = 1.0 
v[1] = 0.0 

,或者是否有更好的選擇。我正在使用Python 2.7.5。謝謝!

回答

3

不要使用此__getattr____setattr__Properties是你的任務更適合:

# Inherit from object. This is important. 
class Vec2(object): 
    def __init__(self): 
     self.data = [0.0, 0.0] 

    def __getitem__(self, index): 
     return self.data[index] 

    def __setitem__(self, index, val): 
     self.data[index] = val 

    @property 
    def x(self): 
     return self.data[0] 
    @x.setter 
    def x(self, val): 
     self.data[0] = val 

    @property 
    def y(self): 
     return self.data[1] 
    @y.setter 
    def y(self, val): 
     self.data[1] = val 

的問題與您__setattr__嘗試是__setattr__被要求的所有屬性的任務,包括self.dataself.mapping,你在__setattr__嘗試本身的任何任務。您可以通過向object.__setattr__委託xy以外的屬性來解決該問題,但屬性更容易。屬性還可以讓您不必在__getattr__中使用object.__getattribute__進行屬性訪問,這是導致無限遞歸問題的因素之一。

__setattr__不同,只有當您嘗試訪問它們控制的屬性時纔會觸發屬性。 x屬性不必處理對x以外的屬性的訪問,並且在編寫屬性時不必使用替代屬性訪問機制。

+0

當我嘗試添加這些內容時,它什麼也不做。也就是說,如果我嘗試使用'v.x = 1.0',它只會向類中添加一個名爲'x'的屬性,並且不會調用您的屬性。如果我在這些方法中放置打印語句,則不會打印任何內容。我需要做別的事情嗎?根據您鏈接到的頁面應該工作,但到目前爲止,我仍然有問題。 – Robotbugs

+0

好吧,我發現這個問題,我需要從對象中派生出這個類來工作。 – Robotbugs

+0

@Robotbugs:是的。大多數花哨的東西不起作用,除非一個階級在其祖先的某個地方有「對象」。 – user2357112

3

您可以撥打object.__setattr__明確,以避免遞歸:

def __setattr__(self, key, value): 
    object.__setattr__(self, key, value)