我有一个调用REST API的函数。参数之一是逗号分隔的名称列表。要生成它,我这样做:
','.join(names)
但是,我还想允许用户提供一个名称。问题是,例如,如果names = ERII
会导致['E', 'R', 'I', 'I']
,但我需要改为['ERII']
。
现在,我可以强制用户输入仅包含一个值(names=['ERRI']
或names=('ERII',)
的列表。我希望允许用户提供单个String。不用if else
语句检查提供的值是否为Iterable
的语句吗?
阿洛斯,我不确定这是什么最佳实践,是强制提供列表还是允许单个字符串?
答案 0 :(得分:2)
可以是事物或可迭代的事物或事物是代码气味的参数。如果事情是字符串,情况就更糟了,因为字符串是是可迭代的,甚至是序列(因此,对isinstance(names, Iterable)
的测试将做错事情)。
Python stdlib确实有一些这样的情况-最臭名昭著的是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)
答案 1 :(得分:1)
我允许列表和单个字符串作为参数。另外,我认为if / else解决方案没有任何问题,除了您可以直接检查参数是否为invisible(lapply(pkg, function(x) {
if (!nzchar(system.file(package=x)))
install.packages(x)
library(x, character.only=TRUE)
}))
类的实例(而不是检查参数是否可迭代)之外:>
str
如果检查参数是否可迭代,请小心-字符串和列表都可迭代。
答案 2 :(得分:0)
使用isinstance()识别输入的类型可能提供解决方案:
def generate_names(input_term):
output_list = []
if isinstance(input_term,str):
output_list.append(','.join(input_term.split()))
elif isinstance(input_term,list):
output_list.append(','.join(input_term))
else:
print('Please provide a string or a list.')
return(output_list)
这将允许您输入列表,单个名称的字符串以及包含多个名称(由空格分隔)的字符串:
name = 'Eric'
name1 = 'Alice John'
namelist = ['Alice', 'Elsa', 'George']
应用此功能:
print(generate_names(name))
print(generate_names(name1))
print(generate_names(namelist))
获取:
['Eric']
['爱丽丝,约翰']
['Alice,Elsa,George']