簡體   English   中英

解壓多個列表作為函數的參數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM