2010-09-06 57 views
1
>>> class S(object): 
...  def __init__(self): 
...    self.x = 1 
...  def x(self): 
...    return self.x 
... 
>>> s = S() 
>>> s.x 
1 
>>> s.x() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'int' object is not callable 

爲什麼在這個例子中是s.x的一個方法,但也是一個整數?在我看來,self.x = 1應該在實例化過程中替換屬性xdef x(self):聲明。爲什麼我可以得到和調用,分別導致一個整數和一個方法,相同的屬性?我的猜測是,新風格類中的變量查找模式是duck typed,以便將最相關的結果返回給調用者。我很想聽聽整個故事。蟒蛇 - 奇怪的行爲問題

回答

2

看起來你對所看到的錯誤有誤解。當您的s對象被實例化時,其構造函數將用一個整數替換方法x,因此在s對象中,x是一個整數,而不是函數。試圖將其稱爲方法會導致拋出異常。

由於方法調用在運行時被解析,因此Python是duck-typed編譯器與s.x()沒有問題,因爲x可能已被動態創建爲方法。但是,當解釋器實際上調用x作爲方法時,它通知x是一個整數且不能被調用,因此TypeError

+0

啊,謝謝。我不知道爲什麼我在深夜嘗試哲學。它從來沒有完全正確。我處於@decorator的框架中,只看到了'self self.x'作爲最終被調用的東西。而且,我甚至不知道是什麼讓我覺得這樣做,而不是讓事情變得更糟:) – orokusaki 2010-09-06 03:55:35

1

我不確定你在想什麼,但沒有什麼棘手的事情發生。當您分配self.x = 1時,方法x不再可訪問。從這一點開始,s.x只是一個整數 - 嘗試將其作爲方法調用導致異常,如您所見。

0

似乎x屬性被定義爲類定義中的方法。然而,實際實例化一個對象用一個整數覆蓋該名稱 - 因此,觀察到的行爲。它實際上從來不是兩次。所以,這基本上是一些錯誤的代碼。

3

Python不會爲可調用對象和不可調用對象使用單獨的空格:名稱是名稱是名稱。 s.x,通過Python規則,必須參考完全是相同的對象,無論你是否打電話給它。把它的另一種方法:假設_aux是出了名不以其他方式使用,

_aux = self.x 
_aux() 

self.x() 

必須在Python中絕對相同的語義,但事實上,在前者的中間值self.x正在被綁定到一個名稱,儘管後來被調用。

擁有單一的「統一」名稱空間用於可調用和非可調用有很多優點 - 它使名稱查找規則(對於每個裸名稱和限定名稱)極其簡單,例如,通過將它們完全解耦從目的被查找的名稱將被放置(在查找的結果之後或之後立即),也可以從類型的(可調用或不可調用)的任何對象出現根據查找規則首先被引用。

特別考慮Python有多少種不同的可調用類型(函數,類,定義了__call__的類的實例,特殊類型如staticmethodclassmethod,...! - ),任何其他規則只會導致混亂。 (還要注意,例如,即使是C++,語言這絕對是不害怕的複雜性,但其允許類的實例可調用[如果類重載operator()],採用了類似的統一的命名空間規則 - 再次,區分可調對象和不可調對象將是一個完全沒有根據的噩夢,在這方面的規則是不同的!)。

+0

@亞歷山大 - 一如既往,很好的答案。我認爲@Eli最好回答了我的問題,因爲它不是基於實踐理論,而是缺乏對我的關注。 – orokusaki 2010-09-06 04:10:40

+0

@Alex:完全不相關,但我必須反問。什麼是「! - )」?我聽說'!'可以用作眨眼,但我習慣將';-)'看作眨眼。 ' - )'意味着tongue舌,也許你將它與感嘆號結合起來強調。我見過你多次使用它,而且我一直在想它是什麼。很抱歉把它放在這裏,但我很好奇:P – avacariu 2010-09-06 04:15:43

+0

@vlad,它是一個變種眨眼笑臉,就像''---'''我猜'' - ]'也很好,但也許我有更多的「全臉」眨眼微笑,所以我更喜歡錶情符號中更「廣泛」的標點符號。 – 2010-09-06 05:34:19

0

這是你的代碼是這樣做的:

  1. 創建一個具有2種方法,__init__x
  2. 名爲S類創建的S一個實例,並命名爲s
    1. 呼叫S.__init__s作爲參數
      1. 設置s.x與價值1
  3. 打印s.x
  4. 打印調用s.x

現在的結果是,如果你在看2.1.1,你會看到你的overrided方法x一個整數,這意味着你不能調用再次withing s(但它在S類劇照)

如果你這樣做,然而,需要調用x功能,試試吧:

>>> class S(object): 
...  def __init__(self): 
...   self.x = 1 
...  def x(self): 
...   return self.x 
... 
>>> s = S() 
>>> s.x 
1 
>>> S.x(s) 
1 
>>> 

我只是做了它,你明白爲什麼你失去了x作爲方法,做到以正確的方式並避免使用與類方法同名的實例變量

+0

謝謝。我明白。打印出來的時候我只是誤讀了這個例外(厭倦了,露營),並且得出了一個結論。 – orokusaki 2010-09-08 16:29:52