Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何判断python变量是字符串还是列表?_Python_List_Duck Typing - Fatal编程技术网

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

如何判断python变量是字符串还是列表?,python,list,duck-typing,Python,List,Duck Typing,我有一个将字符串列表作为参数的例程,但我希望支持传入单个字符串并将其转换为一个字符串列表。例如: def func( files ): for f in files: doSomethingWithFile( f ) func( ['file1','file2','file3'] ) func( 'file1' ) # should be treated like ['file1'] def func(files): if isinstance(files,

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

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

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

func( 'file1' ) # should be treated like ['file1']
def func(files):
    if isinstance(files, basestring):
        doSomethingWithASingleFile(files)
    else:
        for f in files:
            doSomethingWithFile(f)

我的函数如何判断传入的是字符串还是列表?我知道有一个
类型
函数,但是有没有一种“更具pythonic”的方法呢?

嗯,检查类型没有什么不和谐的。话虽如此,如果你愿意给打电话的人增加一点负担:

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

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

我认为这更像是一种“显式比隐式好”。在这里,当输入已经是列表形式时,调用方至少可以识别。

就我个人而言,我并不喜欢这种行为——它会干扰duck键入。有人可能会说,它没有遵守“显式优于隐式”的口号。为什么不使用varargs语法:

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

func( 'file1', 'file2', 'file3' )
func( 'file1' )
func( *listOfFiles )

我想说的是,Python最常用的方法是让用户始终传递一个列表,即使其中只有一项。很明显,
func()
可以获取文件列表

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

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

如果您确实希望将参数设置为字符串的特殊情况,请使用,并与
basestring
(str()和
unicode()
都是从中派生的)进行比较,例如:

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

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

func( 'file1' ) # should be treated like ['file1']
def func(files):
    if isinstance(files, basestring):
        doSomethingWithASingleFile(files)
    else:
        for f in files:
            doSomethingWithFile(f)

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

Varargs让我感到困惑,所以我用Python对它进行了测试,以便自己清理它

首先,瓦拉格斯的政治公众人物是

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

希望这对其他人有帮助。

如果你能更好地控制打电话的人,那么另一个答案会更好。在我的情况下,我没有这种奢侈,因此我决定采用以下解决方案(附带警告):

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

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

func('file1')

这种方法适用于处理满足上述条件的已知列表类型集的情况。但是,某些序列类型将丢失。

更“明确”的方法肯定是要求用户在列表中传递单个文件?像func(['file1'])一样,我同意这是显式的,但我不认为它更显式。两种技术使用相同的逻辑;一个是另一个的反面。我恰好认为上面的内容更直观一些,因为它强调列表中的文件而不是列表本身与func相关。“我个人并不喜欢这种行为”,你具体指的是什么?@nemo我想他指的是最初的问题,这可以解释为请求一个函数,该函数的参数是字符串或字符串列表,其中函数调用不提供传入的参数类型。我同意这一点。FWIW,varargs只有在没有其他args的情况下才有效:
func(file,someflag)
,如果不将
someflag
转换为关键字,则无法将其转换为
func(*files,someflag)
,argPOP 8似乎更喜欢isinstance(u'abc',basestring)而不是使用类型模块。@mdorseif:我编辑了答案,使用
basestring
而不是
types
模块。问题是,如果您在这里只依赖duck键入,字符串将被视为duck键入的列表,并且没有做正确的事情。python将字符串视为字符列表,而不是将其视为单个项。注意,Python3没有
基串。使用
str
除非你指的是一个字节对象(在这个用例中你肯定不应该这样做)。这是一个非常简单的解决方案,对我来说非常有效。谢谢直到有人向您传递一个带有
lower
方法的集合:-/^例如数学对象,或者与真实世界函数交互的集合,例如升高或降低机械控制的窗口为止
casefold
方法可能更像字符串这可能不像其他人指出的那样是最健壮的,但它确实非常适合duck类型。这个解决方案需要一些解释和上下文。OP的帖子中既没有你的变量也没有基串。这在Python3中不起作用。使用
isinstance(你的变量,str)
。其他的注释也不起作用。导入six并检查它是否是一个字符串,使用它来实现python2和3的兼容性以及python2中的utf字符串支持
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