2010-05-07 34 views
0

我有一個函數,它是一個類方法,我想測試一個類的屬性,它可能是也可能不是None,但會一直存在。測試@classmethod函數的現有屬性,得到AttributeError

class classA(): 
def __init__(self, var1, var2 = None): 
    self.attribute1 = var1 
    self.attribute2 = var2 

@classmethod 
def func(self,x): 
    if self.attribute2 is None: 
    do something 

我得到的錯誤

AttributeError: class classA has no attribute 'attributeB' 

當我訪問屬性像我表現,但如果在命令行中,我可以看到它的工作原理,

x = classA() 
x.attribute2 is None 
True 

所以測試工作。

如果我從func中刪除@classmethod修飾符,則問題消失。
如果我離開@classmethod裝飾器,它似乎隻影響在超類的構造函數中提供默認值的變量。

上面的代碼是怎麼回事?

+4

「attributB」!=「attributeB」 – 2010-05-07 21:23:45

+2

請提供一個更完整的代碼示例(這是你的代碼甚至無法有效)。 – ChristopheD 2010-05-07 21:25:58

回答

3

類屬性和實例屬性之間存在差異。一個快速演示將是這樣:

>>> class A(object): 
...  x=4 
...  def __init__(self): 
...   self.y=2 
>>> a=A() #a is now an instance of A 
>>> A.x #Works as x is an attribute of the class 
2: 4 
>>> a.x #Works as instances can access class variables 
3: 4 
>>> a.y #Works as y is an attribute of the instance 
4: 2 
>>> A.y #Fails as the class A has no attribute y 
Traceback (most recent call last): 
    File "<pyshell#9>", line 1, in <module> 
    A.y #Fails as the class A has no attribute y 
AttributeError: type object 'A' has no attribute 'y' 
>>> 

現在,當一個類的方法裝飾有類方法,這預示着它並不需要一個實例,但需要類本身作爲參數。因此,傳統上我們將第一個參數命名爲cls,而不是自我。在你的代碼中,classA沒有屬性,所以試圖訪問attribute2失敗。這種差異可以顯示與下面的代碼:

>>> class B(object): 
...  x=2 
...  def __init__(self): 
...   self.x=7 
...  def pr1(self): 
...   print self.x 
...  @classmethod 
...  def pr2(cls): 
...   print cls.x 
>>> b=B() 
>>> B.x 
2 
>>> b.x 
7 
>>> b.pr1() 
7 
>>> b.pr2() 
2 
>>> B.pr2() 
2 

我可能沒有足夠清楚的,所以如果你仍然感到困惑不僅僅是搜索類方法或新的樣式類,並在此讀了一下。

+0

謝謝。我知道了。 – alex 2010-05-11 14:07:51

2

你應該先測試一下,看看你是否有hasattr()或somesuch這個屬性。

class classA(superClass): 
def func(self,x): 
    if not hasattr(self, "attributeB") or self.attributeB is None: 
    do somthing 

您可能還想確保子類從父類調用構造方法。該屬性顯然是在您引用它後才分配的。所以請確保這個類是正確構建的

parentclassName.__init__(self, ...) 
+0

+1:這是做正確的方式。檢查屬性是否先存在,然後對其執行操作。 – jathanism 2010-05-07 21:53:03

+1

如果父具有屬性(無條件),因爲斷碼例如* *似乎暗示,沒有理由來測試它。 – 2010-05-07 22:31:35

+0

-1:雖然這會工作,它並沒有真正解決實際問題。一般情況下,我會盡量避免設計模式導致類屬性有時,而不是別人得到設定。 – 2010-05-08 01:21:57

0

這兩個屬性是實例屬性,而不是類屬性。類方法試圖引用類屬性。您的屬性1和屬性2都不存在於類中:它們存在於實例中。

我不知道如何修復這個,但這是問題的根源。

(通過改變attribute2在FUNC按鍵ATTRIBUTE1驗證。)

所以問題確實應該「如何引用實例類方法中的屬性?」

2

self在一個實例方法中是實例。 self(或更傳統上,cls)在類方法中是類。綁定在實例上的屬性在類中不可見。使這項工作的唯一方法是將實例傳遞給類方法,此時您可以將其作爲實例方法。

+0

不知道我完全明白這一點。爲什麼它對賦予默認值和參數的argurments反應不同? – alex 2010-05-09 15:54:25

相關問題