我希望一个函数能够将字符串列表或多个字符串作为参数作为 *args

I want a function to be able to take as an argument both a list of strings or several strings as *args

我有一个函数应该能够将许多字符串参数作为 *args,或者将字符串列表作为参数。例如:

def getStuff(*stuff):
  for thing in stuff:
    print(thing)
getStuff("cat", "mouse", "dog")
getStuff(animals)

我希望无论以哪种方式调用此函数都能够产生相同的结果。我目前正在使用以下非常简单的方法,但不是最干净的代码:

def getStuff(*stuff):
  if type(stuff[0]) != list:
    for thing in stuff:
        print(thing)
  else:
    for thing in stuff:
      for subthing in thing:
        print(subthing)

有没有简单的方法可以做到这一点?我正在寻找 python 最佳实践。

当您在 Python 中编写函数时,通常最佳做法是假设函数的参数已知且不变。

看看你的代码,如果你传递一个字符串数组,你的函数似乎可以完成同样的事情。将数组传递给它后,只需打印其中的每个项目。如果只有一项,它将与仅打印一项的函数一样工作。

我建议这样写:

def getStuff(stuff):
    for thing in stuff:
        print(thing)

我确实意识到这不是您要找的东西,但在谈论 Python 中的最佳实践时,就是这样。

如果 args 元组的第一个元素是一个列表,这将获取它,否则我们可以遍历 args (stuff) 元组本身:

def getStuff(*stuff):
    
    stuff = stuff[0] if isinstance(stuff[0], list) else stuff
    
    for thing in stuff:
        print(thing)

更优雅的解决方案,使用itertools:

import itertools

def getStuff(*stuff):
        
    for thing in itertools.chain.from_iterable(stuff):
        print(thing)

说明:itertools.chain.from_iterable 只是将嵌套的可迭代对象展平,以防 stuff 不仅仅是一个字符串元组。像这样, stuff 是元组还是元组中的列表,甚至是多个列表的元组都没有关系。

在 Python 中,许多人更喜欢遵循 ​​EAFP principle over type-checking (aka LBYL) — since exception handling is fairly cheap — see What is the EAFP principle in Python? specifically this answer

以下是将其应用到您的示例代码的方法:

def getStuff(*stuff):
    try:
        stuff[0].split()
    except AttributeError:  # List objects have no split() method.
        stuff = stuff[0]
    for thing in stuff:
        print(thing)

getStuff("cat", "mouse", "dog")
print()
animals = ['cow', 'horse', 'pig']
getStuff(animals)

输出:

cat
mouse
dog

cow
horse
pig