2010-11-17 54 views
6

我的函數需要一個列表或元組作爲參數。它並不真正關心它是,它所做的只是把它傳遞給可以接受一個列表或元組的另一個功能:Python函數參數:元組/列表

def func(arg): # arg is tuple or list 
    another_func(x) 
    # do other stuff here 

現在我需要稍微修改的功能,來處理額外的元素:

def func(arg): #arg is tuple or list 
    another_func(x + ['a']) 
    # etc 

不幸的是,這是行不通的:如果arg是元組,我必須說x + ('a',)

很明顯,我可以通過強制arg列表工作。但它並不整齊。

有沒有更好的方法呢?當然,我不能強迫呼叫者總是通過一個元組,因爲它只是轉移到他們工作。

+0

如果其他函數接受或者我會發送它一個元組,因爲它會更快地處理。那麼'tuple(x)+('a',)''不完整? – aaronasterling 2010-11-17 20:08:38

+0

元組實現速度更快嗎? – max 2010-11-17 20:40:27

+2

從字符串和數字文字構造一個元組比構建一個列表要快。更重要的是,如果tuple(x)已經是一個元組,那麼'tuple(x)'只返回'x',而'list(x)'拷貝'x'即使它已經是一個列表。因此,通過使用元組,可以將大部分工作切分爲一半的輸入案例。 – aaronasterling 2010-11-17 20:49:43

回答

7

如果another_func只是想要一個迭代你可以通過itertools.chain(x,'a')它。

+0

+1我喜歡這樣,但速度快嗎? – max 2010-11-17 20:45:28

+0

@max沒有複製,因此速度非常快。這可能是最有效的Python解決方案。 – 2010-11-17 21:14:33

3

怎麼樣:

l = ['a'] 
l.extend(x) 

編輯: 重讀的問題,我覺得這是更你想要什麼(使用argx是有點混亂):

tuple(arg) + ('a',) 

正如其他人所說,這可能不是最有效的方式,但它非常清楚。如果你的元組/列表很小,我可能會使用這個不太清晰的解決方案,因爲性能影響可以忽略不計。如果您的清單很大,請使用更高效的解決方案。

+0

'extend'返回'None',因爲它會改變列表。 – delnan 2010-11-17 20:05:08

+0

+1,簡單又幹淨 – slezica 2010-11-17 20:06:38

+0

@delnan:你是什麼意思? – max 2010-11-17 21:42:45

4

如何將其他函數改爲接受params列表呢?

def func(arg): # arg is tuple or list 
    another_func('a', *x) 
+1

那麼another_func需要幾個列表參數時受到同一問題的影響,或者它已經有一個(不相關的)* x參數? – max 2010-11-17 21:41:58

+0

+0:很好,但不確定是否可以更改其他功能 – Claudiu 2010-11-17 21:43:29

+0

@max:答案是一樣的。修復其他功能。 – 2010-11-17 21:57:44

2
def f(*args): 
    print args 

def a(*args): 
    k = list(args) 
    k.append('a') 
    f(*k) 

a(1, 2, 3) 

輸出:

(1, 2, 3, 'a') 
+0

hmm'f(*(tuple(args)+('a',))'是更好的 – Claudiu 2010-11-17 21:44:08

1

我的建議:

def foo(t): 
    bar(list(t) + [other]) 

這是不是很有效,但是,你會更好繞過可變的東西,如果你要成爲,好吧,改變它們。

+0

請問您能澄清一下嗎?爲什麼這樣做效率不高? – max 2010-11-17 20:44:08

+0

@max它效率不高,因爲它複製整個列表只是爲了添加一個單一的項目 – 2010-11-17 21:16:39

0

讓你的函數接受任何迭代。然後使用itertools.chain將您想要的任何序列添加到迭代器中。

from itertools import chain 

def func(iterable): 
    another_func(chain(iterable, ('a',))) 
1

可以使用迭代傳遞給第一個函數的類型來構建你傳遞給第二個內容:

from itertools import chain 

def func(iterable): 
    it = iter(iterable) 
    another_func(type(iterable)(chain(it, ('a',)))) 

def another_func(arg): 
    print arg 

func((1,2)) 
# (1, 2, 'a') 
func([1,2]) 
# [1, 2, 'a'] 
2

如果一個迭代是的話,你可以使用itertools.chain,但要知道,如果函數A(第一個被調用)在調用B後迭代遍歷該迭代,那麼您可能會遇到問題,因爲無法重新迭代迭代。在這種情況下,你應該選擇一個序列或使用iterable.tee使可迭代的副本:

import itertools as it 

def A(iterable): 
    iterable, backup = it.tee(iterable) 
    res = B(it.chain(iterable, 'a')) 
    #do something with res 
    for elem in backup: 
     #do something with elem 

def B(iterable): 
    for elem in iterable: 
     #do something with elem 

即使itertools.tee是不是真的那麼有效的,如果B消耗所有可迭代的,那麼只需將iterable轉換爲tuplelist即可。

+0

+ 1用於說明迭代器的重繞在我的例子中,iterable已經足夠了;我猜測序列的情況下,我只會根據@aaronasterling的建議強迫元組 – max 2010-11-17 21:43:37

0

我會說這樣做

def foo(t): 
    bar(list(t) + [other]) 

聖地亞哥Lezica的回答是最好的,因爲它是最簡單的。 (不需要導入itertools的東西,並使用更少的可讀鏈式調用)。但只有在你希望t很小的時候才能使用它。如果t可能很大,您應該使用其他解決方案之一。