2012-11-28 67 views
3

爲什麼以下有效?在Python中,爲什麼裸函數對象有效的代碼?

#!/usr/bin/python 
def spam(): 
    pass 

spam 

我明白函數是對象,但我認爲上面的代碼永遠不會有用,而且總是出錯的結果。爲什麼它不會在引用垃圾郵件功能對象的行上導致錯誤?

+0

它爲什麼會導致錯誤?這是一個絕對有效的Python語法。 –

+0

設計時很有用。 – asheeshr

+3

語言應該如何知道什麼是「有用的」,什麼不是? – YXD

回答

7

每個表達式都是一個有效的語句。使用局部變量(不管它指的是什麼)是一個有效的表達式。由於後期的綁定和動態性,你不能在編譯時檢測它是否指向一個函數或其他東西(儘管在這種情況下你不需要知道,因爲只引用一個本地從不做任何事情)。運行時檢查將會非常昂貴而沒有收益。

這會導致禁止聲明<local variable>;。具體禁止這種情況是不一致的,需要額外的工作,並沒有幫助很多恕我直言。我沒有看到無法完成的技術原因,所以可能歸結爲BDFL不希望爲此特殊情況。

2

首先,spamspam()當然是根本不同的陳述。如果你看看a = spama = spam()之間的差異,這變得清楚。第一個存儲函數在變量a中,第二個存儲當時發生的函數的一個調用的返回值。兩者都是有用但不同的操作。

只是提到spam這樣的功能沒有做一些有用的事情,沒有。但是在python中只聲明值並不是被禁止的。在您的論證之後,單一聲明4也應該是非法的,就像任何有價值的。這實際上會在任何地方使用pydoc字符串,因爲它們只是提到了一個無用的值(從執行的角度來看)。

所以我認爲它可能被禁止使用這樣的價值觀,但它不是,現在它甚至有用法。

+0

你說過我想說得好多了。我刪除了我的和你的+1! – 2012-11-28 17:41:01

+2

您可以爲docstrings特殊情況。我相信OP所掌握的是,讓Python捕獲「忘記調用函數」錯誤的附加價值是值得處理裸表達式的(非常輕微的)成本。 –

+0

@RussellBorogove是的,你可以,我猜,它可以幫助你檢測代碼中的許多錯誤。儘管如此,它不知道爲什麼,對我來說不會感到非常焦慮。並且它不太適合交互式Python提示符,在那裏向你顯示每個「提到的」值(我經常在那裏輸入類似「垃圾郵件」的東西,找出它們來自哪裏,不知道, – kratenko

2

在一般情況下,引用裸表達式會產生副作用。代碼:

class Nugget(object): 
    @property 
    def spam(self): 
     print "does merely referencing a property invoke it?" 

n = Nugget() 
n.spam   # no explicit invocation 

實際上是否打印消息。在你的例子中給你一個錯誤會打破這種情況的普遍性。

+0

獲取一個屬性,如果這是解釋/編譯語言中的一個很好的理由。並且僅僅引用一個裸名就是完全不同的東西,前者可以(如你所示)執行任意代碼,而後者則不能(至少對於當地人來說,我相信你需要深入的,特定於實現的全局變魔術) – delnan

+0

Hm ,我認爲你是對的,雖然我的思維模型在這裏很糟糕,但是在模塊範圍內而不是在類內的屬性什麼也不做,我不知道我的感受如何。 –

+0

我認爲你的例子是不是真的提到一個功能,而是(對外)提及一個變量。因此,它很清楚地表明,改變這種基本行爲的影響有什麼影響,因爲內部有些事情不像他們看起來那樣。 – kratenko

相關問題