Python function parameter: tuple/list

只愿长相守 提交于 2019-12-10 13:08:00

问题


My function 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.


回答1:


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




回答2:


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)



回答3:


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.




回答4:


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')



回答5:


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.




回答6:


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.




回答7:


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']



回答8:


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',)))



回答9:


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.



来源:https://stackoverflow.com/questions/4208619/python-function-parameter-tuple-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!