简体   繁体   English

Python函数参数:tuple / list

[英]Python function parameter: tuple/list

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',) . 不幸的是,这不起作用:如果arg是元组,我必须说x + ('a',)

Obviously, I can make it work by coercing arg to list. 显然,我可以通过强制arg列出来使其工作。 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. 当然,我不能强迫呼叫者总是传递一个元组,因为它只是转移到他们的工作。

如果another_func只想要一个iterable,你可以将itertools.chain(x,'a')传递给它。

What about changing the other function to accept a list of params instead ? 如何更改其他功能以接受params列表呢?

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): 编辑:重新阅读问题,我认为这更像你想要的(使用argx有点混乱):

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. 如果一个iterable足够你可以使用itertools.chain ,但要注意,如果函数A (第一个被调用),也在调用B后遍历iterable,那么你可能会遇到问题,因为iterables不能被重新调用。 In this case you should opt for a sequence or use iterable.tee to make a copy of the iterable: 在这种情况下,您应该选择序列或使用iterable.tee来制作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

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 . 尽管如果B消耗全部大部分可迭代的话, itertools.tee并不是那么高效,那么将iterable转换为tuplelist更简单。

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: 您可以使用传递给第一个函数的iterable类型来构造传递给第二个函数的内容:

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. 然后使用itertools.chain将所需的任何序列添加到iterable中。

from itertools import chain

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

I'd say Santiago Lezica's answer of doing 我会说Santiago Lezica的答案

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). (无需导入itertools并使用更少可读的链调用)。 But only use it if you expect t to be small. 但是只有在你希望小到时才使用它。 If t can be large you should use one of the other solutions. 如果t可能很大,则应使用其他解决方案之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM