【问题标题】:Pythonic way to make a function which can take an iterable or any number of arguments?Pythonic 方法来制作一个可以接受可迭代或任意数量参数的函数?
【发布时间】:2019-04-03 16:26:11
【问题描述】:

这真的是最 Pythonic 的方式来制作一个可以接受一个可迭代或任意数量的参数并对每个参数执行某些操作的函数吗?

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,但由于我实际上是在寻找一种更清洁的方法来做到这一点,所以我提出了这个新问题。

这可行,但在我看来,检查非常难看,我希望有更简单、更清洁的方法来实现这一点输出应该保持不变。

【问题讨论】:

    标签: python python-3.x function arguments


    【解决方案1】:

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

    # 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"]),在这种情况下,为什么无缘无故地使您的函数实现复杂化。

    【讨论】:

    • 是的,我非常清楚大多数时候最好只强制函数用户以特定格式传递参数。问题一般不是关于最佳实践,而是关于实现此类功能的最佳方式
    • 没有什么好办法,因为你天生就在试图猜测调用者的意图。您必须计算参数的数量,然后您必须担心像 str 这样的类型看起来像可迭代但不是,或者它们应该是。
    • 所以你是说我原来的例子是完美的,没有什么可以改进的吗?我明白没有好方法,但一定有比别人更好的方法。
    • 不,我是说您的原件已经达到了最好的水平,但仍然存在缺陷。假设用户想要将字符串视为可迭代的;你的方法仍然要求他们写for_each(["foo"]),在这种情况下,为什么要无缘无故地使你的函数实现复杂化?
    • 在理想的世界中,str 实例根本不能迭代,或者会有一个独特的 char 类型迭代 str 会产生。尽管如此,这并不一定会阻止某人编写他们的 own 类型,该类型实现了这种 iterator-of-its-own-type 废话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多