Python function parameter: tuple / list

My function expects a list or tuple as a parameter. In fact, anyway, everything that it does passes it to another function that takes a list or tuple:

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

Now I need to change the function a bit to handle the extra element:

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

Unfortunately, this will not work: if arg is a tuple, I have to say x + ('a',) .

Obviously, I can make it work by forcing arg to list. But this is not neat.

Is there a better way to do this? I can't get callers to always transfer a tuple, of course, because it just switches to working with them.

+6
python list coding-style tuples
source share
9 answers

If another_func just wants an iterable, you can pass itertools.chain(x,'a') .

+7
source share

How to change another function to accept a list of parameters instead?

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

What about:

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

Edit: While re-reading the question, I think this is more than what you want (using arg and x was a bit confusing):

 tuple(arg) + ('a',) 

As others have said, this is probably not the most effective way, but it is very clear. If your tuples / lists are small, I can use this for less comprehensible solutions, as the performance hit will be negligible. If your lists are large, use more efficient solutions.

+3
source share
 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') 
+2
source share

If iterable is enough, you can use itertools.chain , but keep in mind that if function A (the first called) also iterates over iterable after calling B , then you may have problems, since iterables cannot be rewound. In this case, you must select a sequence or use iterable.tee to make a copy of the iteration:

 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 if itertools.tee is actually not that efficient, if B consumes all or most of the iteration, at this point it is easier to simply convert iterable to a tuple or list .

+2
source share

My suggestion:

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

This is not very effective, but it will be better for you to circumvent mutable things if you are going to, well, mutating them.

+1
source share

You can use the iterable type passed to the first function to build 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'] 
+1
source share

Ask your function to accept the iteration. Then use itertools.chain to add whatever sequence you want for iteration.

 from itertools import chain def func(iterable): another_func(chain(iterable, ('a',))) 
0
source share

I would say that Santiago Lesica answered the question

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

is the best because it is the simplest. (no need to import itertools material and use much less readable calls). But use it only if you expect it to be small. If t can be large, you should use one of the other solutions.

0
source share

All Articles