61

我有一个将字符串列表作为参数的例程,但我想支持传入单个字符串并将其转换为一个字符串列表。例如:

def func( files ):
    for f in files:
        doSomethingWithFile( f )

func( ['file1','file2','file3'] )

func( 'file1' ) # should be treated like ['file1']

我的函数如何判断传入的是字符串还是列表?我知道有一个type功能,但有没有“更pythonic”的方式?

4

8 回答 8

40
isinstance(your_var, basestring)
于 2009-05-07T18:57:40.530 回答
37

好吧,检查类型没有什么不合时宜的。话虽如此,如果您愿意给调用者增加一点负担:

def func( *files ):
    for f in files:
         doSomethingWithFile( f )

func( *['file1','file2','file3'] ) #Is treated like func('file1','file2','file3')
func( 'file1' )

我认为这更像是pythonic,因为“显式优于隐式”。当输入已经是列表形式时,调用者至少可以识别。

于 2009-05-07T18:58:29.903 回答
32

就个人而言,我不太喜欢这种行为——它会干扰鸭子打字。有人可能会争辩说,它不遵守“显式胜于隐式”的口头禅。为什么不使用可变参数语法:

def func( *files ):
    for f in files:
        doSomethingWithFile( f )

func( 'file1', 'file2', 'file3' )
func( 'file1' )
func( *listOfFiles )
于 2009-05-07T18:58:58.810 回答
16

我会说最 Python 的方式是让用户总是传递一个列表,即使它只有一个项目。这很明显func()可以获取文件列表

def func(files):
    for cur_file in files:
        blah(cur_file)

func(['file1'])

正如 Dave 所建议的,您可以使用该func(*files)语法,但我从不喜欢这个功能,而且它似乎更明确(“显式优于隐式”)只需要一个列表。它还将您的特殊情况(func使用单个文件调用)转换为默认情况,因为现在您必须使用额外的语法来func使用列表调用..

如果您确实想为作为字符串的参数创建特殊情况,请使用isinstance()内置函数,并与basestring(两者都派生自)进行比较,例如:str()unicode()

def func(files):
    if isinstance(files, basestring):
        doSomethingWithASingleFile(files)
    else:
        for f in files:
            doSomethingWithFile(f)

真的,我建议只需要一个列表,即使只有一个文件(毕竟,它只需要两个额外的字符!)

于 2009-05-07T19:24:29.747 回答
13
if hasattr(f, 'lower'): print "I'm string like"
于 2009-05-07T23:42:28.300 回答
11
def func(files):
    for f in files if not isinstance(files, basestring) else [files]:
        doSomethingWithFile(f)

func(['file1', 'file2', 'file3'])

func('file1')
于 2009-05-08T02:25:58.503 回答
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

这种方法适用于您正在处理一组已知的满足上述标准的类似列表的类型的情况。不过,一些序列类型会被遗漏。

于 2012-06-19T17:46:39.093 回答
3

Varargs 让我感到困惑,所以我在 Python 中对其进行了测试,以便自己解决。

首先,可变参数的 PEP 在这里

这是示例程序,基于 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']

希望这对其他人有帮助。

于 2009-05-08T01:24:14.203 回答