Python function parameter: tuple/list
My func开发者_运维百科tion expects a list or a tuple as a parameter. It doesn't really care which it is, all it does is pass it to another function that accepts either a list or tuple:
def func(arg): # arg is tuple or list
another_func(x)
# do other stuff here
Now I need to modify the function slightly, to process an additional element:
def func(arg): #arg is tuple or list
another_func(x + ['a'])
# etc
Unfortunately this is not going to work: if arg is tuple, I must say x + ('a',)
.
Obviously, I can make it work by coercing arg to list. But it isn't neat.
Is there a better way of doing that? I can't force callers to always pass a tuple, of course, since it simply shifts to work to them.
If another_func
just wants a iterable you can pass itertools.chain(x,'a')
to it.
What about changing the other function to accept a list of params instead ?
def func(arg): # arg is tuple or list
another_func('a', *x)
how about:
l = ['a']
l.extend(x)
Edit:
Re-reading question, I think this is more what you want (the use of arg
and x
was a little confusing):
tuple(arg) + ('a',)
As others have said, this is probably not the most efficient way, but it is very clear. If your tuples/lists are small, I might use this over less clear solutions as the performance hit will be negligible. If your lists are large, use the more efficient solutions.
def f(*args):
print args
def a(*args):
k = list(args)
k.append('a')
f(*k)
a(1, 2, 3)
Output:
(1, 2, 3, 'a')
If an iterable is enough you can use itertools.chain
, but be aware that if function A
(the first one called), also iterates over the iterable after calling B
, then you might have problems since iterables cannot be rewinded. In this case you should opt for a sequence or use iterable.tee
to make a copy of the iterable:
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
Even though itertools.tee
isn't really that efficient if B
consumes all or most of the iterable, at that point it's simpler to just convert iterable
to a tuple
or a list
.
My suggestion:
def foo(t):
bar(list(t) + [other])
This is not very efficient though, you'd be better off passing around mutable things if you're going to be, well, mutating them.
You can use the type of the iterable passed to the first function to construct what you pass to the second:
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']
Have your function accept any iterable. Then use itertools.chain
to add whatever sequence you want to the iterable.
from itertools import chain
def func(iterable):
another_func(chain(iterable, ('a',)))
I'd say Santiago Lezica's answer of doing
def foo(t):
bar(list(t) + [other])
is the best because it is the simplest. (no need to import itertools stuff and use much less readable chain calls). But only use it if you expect t to be small. If t can be large you should use one of the other solutions.
精彩评论