能够既是一种事物,又可以是一个迭代器或多个事物的参数是一种代码异味。当这个事物是一个字符串时,情况就更糟了,因为字符串 是 可迭代的,甚至是一个序列(所以您对于isinstance(names,Iterable)
的测试会做错事情)。
Python标准库确实有一些这样的情况 - 最恶名昭彰的是str.__mod__
- 但它们大多数都在另一个方向上出现错误,明确要求元组而不是任何可迭代对象,并且它们中的大多数被认为是错误,或者至少不会再添加到今天的语言中。有时候仍然是最好的答案,但是这种异味应该使您在执行操作之前三思。
我不知道您的具体用例是什么,但我认为以下方法会更加优雅:
def spam(*names):
namestr = ','.join(names)
dostuff(namestr)
现在用户可以像这样调用它:
现在用户可以像这样调用它:
spam('eggs')
spam('eggs', 'cheese', 'beans')
或者,如果他们碰巧有一个列表,也很容易:
spam(*ingredients)
如果那不合适,另一个选择是关键字参数,甚至只有关键字参数:
def spam(*, name=None, names=None):
if name and names:
raise TypeError('Not both!')
if not names: names = [name]
但如果最佳设计确实是一个字符串或一个(非字符串的)字符串可迭代对象,或者是一个字符串或一个字符串元组,那么标准的方法就是类型转换。它看起来可能有点丑陋,但它提醒您正在做什么,并以最惯用的方式完成它。
def spam(names):
if isinstance(names, str):
names = [names]
dostuff(names)
name
的变量。 - Antoine Viscardi*names
怎么样?这样用户就可以发送一个名称或五个名称,而不需要括号 - 或者,如果他有一个列表方便,他可以直接将*lst
发送给你。 - abarnert