我有一个例程,它将一个字符串列表作为参数,但我想支持传入一个字符串并将其转换为一个字符串列表。例如:
def func( files ):
for f in files:
doSomethingWithFile( f )
func( ['file1','file2','file3'] )
func( 'file1' ) # should be treated like ['file1']
我的函数如何判断字符串或列表是否已传入?我知道有一个type
函数,但是有更“pythonic”的方法吗?
答案 0 :(得分:43)
isinstance(your_var, basestring)
答案 1 :(得分:37)
嗯,关于检查类型没什么特别的。话虽如此,如果你愿意给呼叫者带来一点小负担:
def func( *files ):
for f in files:
doSomethingWithFile( f )
func( *['file1','file2','file3'] ) #Is treated like func('file1','file2','file3')
func( 'file1' )
我认为这更像是pythonic,因为“明确比隐含更好”。当输入已经是列表形式时,至少在调用者方面有识别。
答案 2 :(得分:32)
就个人而言,我并不喜欢这种行为 - 它会干扰鸭子打字。有人可能会说它不遵守“明确比隐含更好”的口头禅。为什么不使用varargs语法:
def func( *files ):
for f in files:
doSomethingWithFile( f )
func( 'file1', 'file2', 'file3' )
func( 'file1' )
func( *listOfFiles )
答案 3 :(得分:16)
我想说Python最常用的方法是让用户总是传递一个列表,即使其中只有一个项目。很明显func()
可以获取文件列表
def func(files):
for cur_file in files:
blah(cur_file)
func(['file1'])
正如Dave建议的那样,你可以使用func(*files)
语法,但我从不喜欢这个功能,并且它似乎更明确(“显式比隐式更好”)只需要一个列表。它还将您的特殊情况(使用单个文件调用func
)转换为默认情况,因为现在您必须使用额外的语法来使用列表调用func
..
如果您确实想要将参数设为字符串的特殊情况,请使用isinstance()
builtin,并与basestring
(str()
和unicode()
进行比较来源于)例如:
def func(files):
if isinstance(files, basestring):
doSomethingWithASingleFile(files)
else:
for f in files:
doSomethingWithFile(f)
真的,我建议只需要一个列表,即使只有一个文件(毕竟,它只需要两个额外的字符!)
答案 4 :(得分:11)
if hasattr(f, 'lower'): print "I'm string like"
答案 5 :(得分:11)
def func(files):
for f in files if not isinstance(files, basestring) else [files]:
doSomethingWithFile(f)
func(['file1', 'file2', 'file3'])
func('file1')
答案 6 :(得分:6)
如果您对呼叫者有更多控制权,那么其他答案之一就更好了。在我的情况下,我没有那么奢侈,所以我决定采用以下解决方案(注意事项):
def islistlike(v):
"""Return True if v is a non-string sequence and is iterable. Note that
not all objects with getitem() have the iterable attribute"""
if hasattr(v, '__iter__') and not isinstance(v, basestring):
return True
else:
#This will happen for most atomic types like numbers and strings
return False
此方法适用于您处理符合上述条件的已知类似列表类型的情况。但是有些序列类型会被遗漏。
答案 7 :(得分:3)
Varargs对我来说很困惑,所以我在Python中测试它以便为自己清理它。
首先,varargs的PEP是here。
这是一个示例程序,基于Dave和David Berger的两个答案,然后是输出,只是为了澄清。
def func( *files ):
print files
for f in files:
print( f )
if __name__ == '__main__':
func( *['file1','file2','file3'] ) #Is treated like func('file1','file2','file3')
func( 'onestring' )
func( 'thing1','thing2','thing3' )
func( ['stuff1','stuff2','stuff3'] )
结果输出;
('file1', 'file2', 'file3')
file1
file2
file3
('onestring',)
onestring
('thing1', 'thing2', 'thing3')
thing1
thing2
thing3
(['stuff1', 'stuff2', 'stuff3'],)
['stuff1', 'stuff2', 'stuff3']
希望这对其他人有帮助。