这真的是最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)
输出:
done 1 done 2 done foo done bar done 3 done 4 done 5 done string done 6
我得到了这个有效的答案from here,但是由于我实际上正在寻找一种更清洁的方法来完成此操作,所以我提出了这个新问题。
这可行,但是我认为检查非常难看,并且我希望可以有更简单,更干净的方法来实现这一目标。 输出应保持不变。
答案 0 :(得分: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)
没有一种如您所愿的好方法,因为您本质上是在试图猜测呼叫者的意图。您必须计算参数的数量,然后必须担心像str这样的类型看起来像可迭代但不是,或者应该是这样。
如果必须按照自己的方式进行操作,则原始示例虽然可以尽力而为,但是仍然存在缺陷。假设用户希望将字符串视为可迭代字符串;您的方法仍然需要他们编写for_each([“ foo”]),在这种情况下,为什么无缘无故使函数的实现复杂化。