开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜