2012-09-08 121 views
4

我想讓我的代碼不接受關鍵字參數就像一些bulitins也不接受關鍵字參數,但是,我無法這樣做。這裏,是根據我有限的瞭解我的想法: -python不接受關鍵字參數

def somefunc(a,b): 
    print a,b 

somefunc(10,20) 

輸出:

10 20 

現在,當我運行下面的(我知道這是不是有望成爲關鍵詞參數在函數定義中,但是,在看函數調用時,它看起來與調用接受關鍵字參數的函數時的語法相同):

somefunc(b=10,a=20) 

輸出:

20 10 

我有2個問題: -

  1. 望着函數調用somefunc(b=10,a=20)而不是函數定義,這可能似乎不是的對只接受普通參數或接受關鍵字參數的函數的函數的調用。口譯員如何區分兩者?
  2. 是否有可能將表單中的任何函數轉換爲不與許多內建函數一樣接受關鍵字參數?

爲什麼我想這樣做呢? 我只是檢查我是否可以做到這一點,這樣我就不會錯過深入瞭解python的任何內容。我知道python是否允許。

+0

你爲什麼要這樣做? –

+1

我只是檢查我是否可以這樣做,這樣我就不會錯過深入理解python的任何內容。 – GodMan

回答

4

ad 1)如果Python被調用如somefunct(name=value, ...),則Python會自動驗證正確的名稱。我不需要記住參數的確切標準順序,並且如果我記得具有很好的描述性參數名稱的功能,並且將會測試它們被接受,那麼通過在每次使用時每月查看文檔來驗證它是否「神經質」由Python。相反,使用參數的正確順序只能通過文檔來驗證。通過命名參數進行調用優於位置參數的很長列表。因此,所報道的行爲是有根據的。 (短的單個字母參數「a,b」當然不會幫助防止錯誤)

ad 2)一些衆所周知的內置快速函數用C語言編寫,固定數量的所需參數不支持使用命名參數。 (例如hasattr

這是因爲它們只使用簡單標頭...(... PyObject *args),因此所有命名參數都會自動被拒絕。 (Python永遠不會反省C源代碼中的參數名稱。:-)

許多其他C函數的標題爲...(... PyObject *args, PyObject *kwds),他們通過執行更復雜的驗證PyArg_ParseTupleAndKeywords並將名稱寫入文檔字符串來明確支持名稱的確切列表。

編輯:提高英語

3

Looking at the function call somefunc(b=10,a=20) and not the function definition, this can seem to be either of a call to a function which accepts just normal arguments or a function which accepts keyword arguments. How does the interpreter differentiate between the two?

不知道這是不是你所問的,但如果我理解你的話,答案是「它不」。無論參數在函數中如何定義,都可以用調用函數。如果您使用關鍵字語法傳遞任何參數(例如,f(a=...)),Python會將相應的值綁定到函數定義中具有相同名稱的參數。是否定義了默認值並不重要。這兩種函數定義不會創建不同的「種類」參數,只是某些參數可能具有默認值,其他參數可能不具有。所以無論你做def f(a)還是def f(a=2),你仍然可以做f(a=...)。唯一的限制是您必須首先傳遞/定義位置參數(例如,您不能執行def f(a=2, b)f(a=2, 3))。另見this answer

至於你的問題的第二部分,我不知道有什麼辦法阻止Python函數接受關鍵字傳遞的值作爲命名參數。如果僅定義*args,那麼它將不接受關鍵字參數,但位置參數不能具有單獨的名稱。

+0

@BrenBarn:'無論函數中參數的定義如何,都可以用關鍵字調用函數。我明白那個。但是,我只是通過查看函數調用'somefunc(b = 10,a = 20)'來說,判斷函數定義是否需要2個不同的名稱:'a'和'b ',或者函數期望關鍵字參數。不是嗎? – GodMan

+0

@GodMan:我想你正在以一種奇怪的方式使用「關鍵字參數」。你的意思是*變量*關鍵字參數(即'** kwargs')?如果是這樣,那麼是的,你不能說。但那不是「關鍵詞爭論」的意思;關鍵字參數只是由關鍵字定義和/或傳遞的參數(即使它們是明確定義的)。定義了def f(a,b)和def f(a = 2,b = 3)的函數都通過名稱'a'和'b'接受不同的參數,並且在這兩種情況下都可以傳遞這些值按位置或按關鍵字。 – BrenBarn

+0

@Marcin:我已經編輯澄清,你不能做的是命名位置參數,不接受通過關鍵字傳遞的值。 – BrenBarn

5

您可以使用任意參數列表來執行此操作。見http://docs.python.org/tutorial/controlflow.html#arbitrary-argument-lists

例如:

def somefunc(*args): 
    print args[0], args[1] 

調用不帶關鍵字:

somefunc(10,20) 

給出:

10 20 

調用帶有關鍵字:

somefunc(a=10,b=20) 

給出了一個錯誤:

TypeError: someFunc() got an unexpected keyword argument 'a' 

目前還不清楚爲什麼你會想這樣做雖然。

+1

+1 - _目前還不清楚你爲什麼要這麼做。 - - 只是因爲你能做到這一點_doesn't_這意味着它可以做到這一點。 – Kimvais

3

在關鍵字和位置參數之間,Python沒有如此強烈的區別。

位置參數在它們在函數調用 關鍵字參數可以以任意順序加入上市順序分析,但不能來位置參數:事實上,因爲它是那麼簡單。

所以,如果你有這樣的:

def foo(x): 
    pass 

你可以這樣做:

foo(1) # positional 
foo(x=1) # keyword 

但你不能做foo()因爲你沒有提供一個默認值。

同樣,如果你有這樣的:

def foo(x,y='hello'): 
    pass 

foo(1) # this works fine 
foo() # this is invalid, as an argument without a default isn't passed 
foo(y='hello',1) # error - positional arguments come before keyword arguments 

不要忘記在arbitrary argument lists閱讀起來。

0

我覺得這是一個非常不好的Python的功能,並可能導致非常難以維護和bug的代碼。假設你有一個函數:

def myurl(x, y): 
    url = "{}:{}".format(x, y) 
    return url 

雖然它看起來像一個好主意,以實現與關鍵字參數更換位置永遠無法做到這一點。我很驚訝,沒有Python的選項會阻止此功能使用關鍵字參數來調用:

>> print myurl(x="localhost", y=8080) 

如果有人數字出庫將更具可讀性,如果寫成:

def myurl(hostname, port): 
    url = "{}:{}".format(hostname, port) 
    return url 

那麼使用關鍵字調用作爲myurl(x="localhost", y=8080)代碼的其餘部分將失敗:

TypeError: myurl() got an unexpected keyword argument 'x' 

這意味着你的本地函數變量所有的突然變成了全局變量!我希望這個問題可以用Python 3解決。