2016-06-13 61 views
1

#for例如:Python的__init __(self)方法是否在所有其他類/實例方法之前被解釋器定義?

class example(object): 

    def someFunction(): 
     print("I am some function") 

    def __init__(self,x,y): 
     self.x = x 
     self.y = y 
     someFunction() 

爲什麼這個代碼生成someFunction沒有定義的錯誤? 是不是因爲python的解釋器執行def init代碼塊才執行def some函數代碼?我認爲python的執行順序是一種自頂向下的方法。任何洞察力將不勝感激。

+4

我不清楚你在這裏問什麼。你是否故意忽略'someFunction()'的'self'參數,並想知道爲什麼'__init __()'不能從封閉範圍看到名字?或者你想知道調用方法的正確方法是什麼?下一個問題的答案是Andy Hayden的答案如下。前一個問題的答案有一點涉及。 –

+0

您能否解釋爲什麼__init __()無法從封閉範圍看到名稱,這正是我想要問的。 – 7alman

+1

相關:http://stackoverflow.com/questions/9505979/the-scope-of-names-defined-in-class-block-doesnt-extend-to-the-methods-blocks http://stackoverflow.com/問題/ 13937637/why-doesnt-class-start-a-new-scope-like-def-does –

回答

1

您需要self太前綴是:

def __init__(self,x,y): 
    self.x = x 
    self.y = y 
    self.someFunction() 
+2

以及方法中的'self'參數。 –

+0

那麼,你不能在實例方法中調用不使用自參數的函數? – 7alman

+0

@ 7alman這是python101 ...也許你應該從一些關於python類的教程開始......如果你正在爲此付出努力,那麼你以後會遇到更多問題(例如,將它修復爲self.someFunction()你可能會發現你會得到一個關於正在傳遞的參數的錯誤,但是這個方法除了參數 –

0

安迪·海登的答案給你必要的修復,但我想你可以欣賞專門針對你的問題多一點背景。請注意,這裏描述了所謂的「新」對象模型,儘管舊模型(從2.2天前開始,仍然是Python 2中的默認模式,運行幾乎相同)。

當解釋器編譯一類是讀取整個類體,並在字典中保存定義(在你的情況,someFunction__init__)。它建立了一個「基類」(它繼承的類)的列表,然後它調用類的元類(除非你採取特殊的行動,在Python中你的類的元類將是內置類型type)與類名稱,基類列表和表示類名字空間的字典作爲參數。

在Python 3中,新模型是默認模型,您可以使用class聲明的關鍵字參數設置類的元類。這可以讓你驗證我的斷言。考慮下面的程序:

class print_args(type): 
    def __new__(cls, name, bases, name_space): 
     print("class:", cls) 
     print("Declaring class", name) 
     print("Bases:", bases) 
     print("Namespace:", name_space) 
     return type.__new__(cls, name, bases, name_space) 

class A: pass 

class B: pass 

print("Defining C") 
class C(A, B, metaclass=print_args): 
    CVar = "class attribute" 
    def myMethod(self, a): 
     return self.N, self.CVar 
    def __init__(self, N): 
     self.N = N 
print("Creating c") 
c = C(42) 
print(c.CVar, C.CVar) 
print(C.__dict__) 
print(c.__dict__) 
c.CVar = "instance attribute" 
print(c.CVar, C.CVar) 
print(c.__dict__) 

print_args類是一個簡單元類,模仿的type從它繼承和一點印刷後實際的工作委託給type.__new__的動作。當C類被聲明,它輸出

Defining C 
class: <class '__main__.print_args'> 
Declaring class C 
Bases: (<class '__main__.A'>, <class '__main__.B'>) 
Namespace: {'__qualname__': 'C', '__module__': '__main__', '__init__': <function C.__init__ at 0x10778bbf8>, 'myMethod': <function C.myMethod at 0x10778bc80>, 'CVar': 'class attribute'} 

注意,這一切都發生當C類被聲明爲- 您可以通過輸出的下一行講這個。另請注意,打印的值會告訴您傳遞給type.__new__的內容。程序接下來會創建一個C實例,並演示類屬性也可以作爲實例屬性進行訪問 - 方法解析順序也應用於屬性查找 - 實際上,實例也可以訪問AB類中的屬性是任何。

Creating c 
class attribute class attribute 

此時C類的__dict__看起來是這樣的:

{'CVar': 'class attribute', 
'__module__': '__main__', 
'__doc__': None, 
'__init__': <function C.__init__ at 0x10778bbf8>, 
'myMethod': <function C.myMethod at 0x10778bc80>} 

及其實例的字典是這樣的:

{'N': 42} 

它僅包含實例屬性N 。但是在將值綁定到c.CVar之後,我們可以看到實例屬性現在不同於類屬性。

instance attribute class attribute 

這通過實例的__dict__的更新後的視圖進行確認。

{'CVar': 'instance attribute', 'N': 42} 

希望這會給你更多的洞察,當你聲明類如何實例和類相關的情況,以及。

+0

欣賞進一步的洞察。 – 7alman

相關問題