如何判断python变量是字符串还是列表?

Gra*_*row 61 python duck-typing list

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

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

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

func( 'file1' ) # should be treated like ['file1']
Run Code Online (Sandbox Code Playgroud)

我的函数如何判断字符串或​​列表是否已传入?我知道有一个type功能,但是有更"pythonic"的方式吗?

Aym*_*ieh 43

isinstance(your_var, basestring)
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案需要一些解释,一些上下文 OP的帖子中都没有your_var和basestring. (4认同)
  • 这在Python 3中不起作用.使用`isinstance(your_var,str)`. (4认同)

Dav*_*ger 37

好吧,关于检查类型没什么特别的.话虽如此,如果你愿意给呼叫者带来一点小负担:

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

func( *['file1','file2','file3'] ) #Is treated like func('file1','file2','file3')
func( 'file1' )
Run Code Online (Sandbox Code Playgroud)

我认为这更像是pythonic,因为"明确比隐含更好".当输入已经是列表形式时,至少对呼叫者的部分进行识别.

  • 当然,更"明确"的方法是要求用户传递列表中的单个文件?像func(['file1']) (10认同)
  • 我同意这是明确的,但我不明白它是如何更明确的.两种技术都使用相同的逻辑; 一个是另一个的反面.我碰巧认为上面的内容稍微直观一些,因为它强调列表中的文件而不是列表本身与func相关. (2认同)

Dav*_*ave 32

就个人而言,我并不喜欢这种行为 - 它会干扰鸭子打字.有人可能会说它不遵守"明确比隐含更好"的口头禅.为什么不使用varargs语法:

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

func( 'file1', 'file2', 'file3' )
func( 'file1' )
func( *listOfFiles )
Run Code Online (Sandbox Code Playgroud)


dbr*_*dbr 16

我会说Python最常用的方法是让用户总是传递一个列表,即使其中只有一个项目.这使得显而易见的是func()可以获取文件列表

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

func(['file1'])
Run Code Online (Sandbox Code Playgroud)

正如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)
Run Code Online (Sandbox Code Playgroud)

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

  • 问题是,如果你只依赖于鸭子打字,那么字符串*被视为带有鸭子打字的列表,并且做不正确.python不会将其视为单个项目,而是将字符串视为字符列表.Whups. (12认同)

lim*_*der 11

if hasattr(f, 'lower'): print "I'm string like"
Run Code Online (Sandbox Code Playgroud)

  • 这是有效的,直到有人通过一个带有`lower`方法的集合: - / (3认同)

jfs*_*jfs 11

def func(files):
    for f in files if not isinstance(files, basestring) else [files]:
        doSomethingWithFile(f)

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

func('file1')
Run Code Online (Sandbox Code Playgroud)


Dan*_*ane 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
Run Code Online (Sandbox Code Playgroud)

这种方法适用于您处理符合上述条件的已知类似列表类型的情况.但是会遗漏一些序列类型.