用Python方式制作可以采用可迭代或任意数量参数的函数?

ruo*_*ola 2 python arguments function python-3.x

这真的是使函数可以采用可迭代或任意数量的参数并对每个参数执行某些操作的最Python化方法吗?

from collections.abc import Iterable


def for_each(*args):
    """Take any number of arguments or an iterable and do something with them.
    Shouldn't throw an error or print anything when no arguments are given.
    """
    if (len(args) == 1
            and isinstance(args[0], Iterable)
            and not isinstance(args[0], str)):
        # Is this really the most Pythonic way to do this?
        args = args[0]

    for arg in args:
        # heavily simplified
        print("done", arg)


for_each(1, 2)
for_each(['foo', 'bar'])
for_each((3, 4, 5))
for_each()  # does essentially nothing, like it should
for_each("string")  # don't loop over the characters
for_each(6)
Run Code Online (Sandbox Code Playgroud)

输出:

done 1
done 2
done foo
done bar
done 3
done 4
done 5
done string
done 6
Run Code Online (Sandbox Code Playgroud)

我从这里得到了这个有效的答案,但是由于我实际上正在寻找一种更清洁的方式来执行此操作,因此我提出了这个新问题。

这种方法有效,但是我认为检查非常丑陋,我希望可以有更简单,更干净的方法来实现这一目标。输出应保持不变。

che*_*ner 6

Python的方式不是。选择一个,然后让调用者提供正确的参数:

# Iterable only: caller wraps the arguments
def for_each(iterable=None):
    if iterable is None:
        iterable = ()
        # or just return now, if that's an option

    for arg in iterable:
        ...

foreach((1,2,3))

# separate args: caller unpacks the arguments
def for_each(*args):
    for arg in args:
        ...

x = [1,2,3]
for_each(*x)
Run Code Online (Sandbox Code Playgroud)

没有什么好方法可以像您想要的那样进行,因为您本质上是在试图猜测呼叫者的意图。您必须计算参数的数量,然后必须担心像str这样的类型看起来像可迭代但不是,或者应该是这样。

如果必须按照您希望的方式进行操作,那么您最初的示例就可以尽力而为,但是仍然存在缺陷。假设用户希望将字符串视为可迭代;您的方法仍然需要他们编写for_each([“ foo”]),在这种情况下,为什么无缘无故使函数的实现复杂化。

  • 没有好的方法,因为您本质上是在尝试猜测呼叫者的意图。您*必须*计算参数的数量,然后您必须担心像str这样的类型,它们看起来像是可迭代的,但不是,或者应该是。 (3认同)