[英]How to pass more than one element of a list to argument in a custom function - Python
[英]Unpacking more than one list as argument for a function
如果我有類似的功能:
def f(a,b,c,d):
print a,b,c,d
那么為什么這樣做有效:
f(1,2,3,4)
f(*[1,2,3,4])
但這不是:
f(*[1,2] , *[3,4])
f(*[1,2] , *[3,4])
^
SyntaxError: invalid syntax
?
編輯 :信息,最初的問題是替換函數包裝中的參數之一。 我想替換輸入的* args的給定成員,並嘗試如下操作:
def vectorize_pos(f,n=0):
'''
Decorator, vectorize the processing of the nth argument
:param f: function that dont accept a list as nth argument
'''
def vectorizedFunction(*args,**kwargs):
if isinstance(args[n],list):
return map(lambda x : f( *(args[:n]) , x , *(args[n+1,:]), **kwargs),args[n])
else:
return f(*args,**kwargs)
return vectorizedFunction
這就是問題的出處。 而且我知道還有其他方法可以做同樣的事情,但只是想了解為什么解壓縮一個序列會起作用,但不能解決更多問題。
因為按照函數調用語法 ,這就是定義參數列表的方式
argument_list ::= positional_arguments ["," keyword_arguments]
["," "*" expression] ["," keyword_arguments]
["," "**" expression]
| keyword_arguments ["," "*" expression]
["," keyword_arguments] ["," "**" expression]
| "*" expression ["," keyword_arguments] ["," "**" expression]
| "**" expression
因此,每個函數調用只能傳遞一個* expression
。
在Python 3.5開始,這樣 沒有 問題 。
PEP 448在Python 3.5中實現。 從PEP引用,它允許:
任意定位的拆箱操作員:
>>> print(*[1], *[2], 3) 1 2 3 >>> dict(**{'x': 1}, y=2, **{'z': 3}) {'x': 1, 'y': 2, 'z': 3}
您可以串聯列表:
>>> f(*[1,2]+[3,4])
1 2 3 4
或使用itertools.chain
:
>>> from itertools import chain
>>> f(*chain([1,2], [3,4]))
1 2 3 4
這將代替。
>>>def f(a,b,c,d):
print('hello') #or whatever you wanna do.
>>>f(1,2,*[3,4])
hello
不起作用的原因是Python使用此實現
一個列表解壓縮,並且按照語義,此后的任何參數都必須是命名關鍵字參數( 或通過 ** 傳遞命名關鍵字參數的字典 )
相比之下,這將起作用。
>>>def f(a,b,c,k):
pass
>>>f(1,*[2,3],k=4)
它不起作用,因為它的語法無效-也就是說,盡管看起來像,但實際上不是Python。
Python 2函數簽名中只允許使用一個加星標的參數,並且該參數必須在任何位置參數之后並且在任何關鍵字參數之前。 同樣,只允許使用一個雙星參數,並且該參數必須跟隨簽名中的所有關鍵字參數。 如果您要提交多個參數列表,則確實必須先從它們創建一個列表。
在Python 3中,也可以單獨使用星號來表示以下任何參數都是所謂的僅關鍵字參數,但是我認為我們現在還不需要討論。
*
此處不充當運算符。 它更像是函數調用語法的一部分,並且只允許某些有限的可能性。 可以定義語言,以便您可以做自己想做的事情(我已經完成了!),但這不是做出的選擇。
這些可能會有所幫助。 請注意,類推就是其他語言中可變數量的參數。 這意味着一旦您說要使用可變數量的參數,所有以下所有參數都屬於該列表的一部分(類似於C或C ++對varargs的用法)。
例如f = [1,2,3,4,5]
def func(a, b, c, d)
print a, b, c, d
func(f) # Error 1 argument, 4 required
func(*f) # Error 5 arguments 4 required
http://www.python-course.eu/passing_arguments.php
參數長度可變
現在,我們將介紹可以接受任意數量參數的函數。 那些具有C或C ++編程背景的人從這些語言的varargs功能中知道這一點。 在Python中,星號“ *”用於定義可變數量的參數。 星號字符必須在參數列表中的變量標識符之前。>>> def varpafu(*x): print(x) ... >>> varpafu() () >>> varpafu(34,"Do you like Python?", "Of course") (34, 'Do you like Python?', 'Of course') >>>
我們從前面的示例中了解到,傳遞給varpafu()函數調用的參數存儲在一個元組中,可以在函數體內將其作為“普通”變量x進行訪問。 如果在不帶任何參數的情況下調用該函數,則x的值為空元組。
有時,在函數定義中必須使用位置參數,后跟任意數量的參數。 這是可能的,但是位置參數必須始終在任意參數之前。 在下面的示例中,我們有一個位置參數“ city”,-主要位置,-必須始終給出,后跟任意數量的其他位置:
>>> def locations(city, *other_cities): print(city, other_cities) ... >>> locations("Paris") ('Paris', ()) >>> locations("Paris", "Strasbourg", "Lyon", "Dijon", "Bordeaux", "Marseille") ('Paris', ('Strasbourg', 'Lyon', 'Dijon', 'Bordeaux', 'Marseille')) >>>
http://docs.python.org/2.7/reference/expressions.html
如果語法* expression出現在函數調用中,則表達式必須求值為可迭代。 可迭代對象的元素被視為附加的位置參數; 如果存在位置參數x1,...,xN,並且表達式的計算結果為序列y1,...,yM,則等效於使用M + N個位置參數x1,...,xN,y1,...的調用。 ..,yM。
這樣的結果是,盡管* expression語法可能會出現在某些關鍵字參數之后,但會在關鍵字參數之前(和** expression參數,如果有的話,請參見下文)進行處理。 所以:
>
>>> def f(a, b): ... print a, b ... >>> f(b=1, *(2,)) 2 1 >>> f(a=1, *(2,)) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: f() got multiple values for keyword argument 'a' >>> f(1, *(2,)) 1 2
在同一調用中同時使用關鍵字參數和* expression語法是很不尋常的,因此在實踐中不會出現這種混淆。
如果語法** expression出現在函數調用中,則表達式必須計算為一個映射,該映射的內容被視為其他關鍵字參數。 如果關鍵字同時出現在表達式中並作為顯式關鍵字參數出現,則會引發TypeError異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.