2012-03-17 36 views
2

以下Python代碼正常執行而不引發異常:爲什麼Python不會在命名空間碰撞時產生錯誤?

class Foo: 
    pass 

class Foo: 
    pass 

def bar(): 
    pass 

def bar(): 
    pass 

print(Foo.__module__ + Foo.__name__) 

但顯然,也有__main__.Foo__main__.bar多個實例。爲什麼Python遇到這種名稱空間衝突時不會引發錯誤?既然它沒有提出錯誤,它究竟做了什麼?第一類__main__.Foo被第二類__main__.Foo所取代?

+0

要分配一個變量兩次是錯誤的? – JBernardo 2012-03-17 14:59:32

+0

但是,它不僅僅是分配一個變量嗎?它使用每個新的類定義創建新類型。 – Channel72 2012-03-17 15:00:20

+0

那又如何?它創建了第二個類對象,然後它分配名稱/「變量」Foo來引用該類對象,而不是之前引用的對象。模塊是一系列語句(大部分類似於函數),'class' /'def'只是語句。 – delnan 2012-03-17 15:02:51

回答

6

在Python中,一切都是某種類型的對象 - 實例。例如。 1int類型的一個實例,def foo(): pass創建對象foofunction類型的一個實例(用於相同的類 - 對象,通過class語句創建的類型是type的實例)。 (是,存在鍵入type和內置鑑於這一點,有沒有

class Foo: 
    string = "foo1" 

class Foo: 
    string = "foo2" 

a = 1 
a = 2 

BTW之間差(在名稱結合機構的水平),可以使用type函數來執行類定義-in功能type):

Foo = type('Foo',(), {string: 'foo1'}) 

因此類和函數是不是一些不同種類的數據,雖然SPECI al語法可用於創建它們的實例。

另請參閱相關Data Model部分。

1

第二個定義替換第一個,預期,如果你認爲在班作爲當前命名空間的「類型辭典」元素:

>>> class Foo: 
...  def test1(self): 
...    print "test1" 
... 
>>> Foo 
<class __main__.Foo at 0x7fe8c6943650> 
>>> class Foo: 
...  def test2(self): 
...    print "test2" 
... 
>>> Foo 
<class __main__.Foo at 0x7fe8c6943590> 
>>> a = Foo() 
>>> a.test1() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: Foo instance has no attribute 'test1' 
>>> a.test2() 
test2 
>>> 

在這裏,你可以清楚地看到的「定義」 Foo更改(Foo指向內存中的不同類別),並且它是最後一個流行的。

1

Foo類被有效地重新定義在腳本之後(腳本被解釋器從上到下讀取)。

class Foo: 
    string = "foo1" 

class Foo: 
    string = "foo2" 

f = Foo() 
print f.string 

打印 「foo2的」

1

概念這只是重新綁定一個名字。這是沒有什麼不同:

x = 1 
x = 2 

我敢肯定,你不會希望這是一個錯誤。

1

在編譯和某些解釋語言中,在定義,聲明和執行之間存在明確的分離。但在Python中它更簡單。只是聲明!

Python EXECUTES只要它被調用,你的腳本/程序/模塊。看到defclass爲「語法糖」可能會有所幫助。例如。類是圍繞Foo = type("class-name", (bases), {attributes})的便利包裝。

所以Python執行:

class Foo #equivalent to: Foo = type("class-name", (bases), {attributes}) 
class Foo 
def bar 
def bar 

print(Foo.__module__ + Foo.__name__) 

其歸結爲覆蓋名Foobar了最新的 「宣言」。所以這只是按照python-pov的意圖工作 - 但可能並非如你所願! ;-)

所以這也是一個典型的錯誤與不同背景的開發人員產生誤解:

def some_method(default_list = []): 
    ... 

default_list這裏是一個單身。每次調用some_method時都使用相同的default_list,因爲列表對象是在第一次執行時創建的。

Python不會進入函數體,但只會在開始解析時執行簽名/頭。

相關問題