代码之家  ›  专栏  ›  技术社区  ›  Antoine Viscardi Ziyed

Python,允许将单个字符串和字符串列表传递给函数

  •  0
  • Antoine Viscardi Ziyed  · 技术社区  · 6 年前

    我有一个调用REST API的函数。其中一个参数是以逗号分隔的名称列表。为了生成它,我这样做:

    ','.join(names)
    

    但是,我也希望允许用户提供单个名称。问题是如果 names = ERII 例如,它会导致 ['E', 'R', 'I', 'I'] ,但我需要它 ['ERII'] 相反。

    现在,我可以强制用户输入只有一个值的列表( names=['ERRI'] names=('ERII',) . 我希望允许用户提供单个字符串。有没有聪明的方法不用 if else 语句检查提供的值是否为 Iterable ?

    阿洛斯,我不确定这里的最佳实践是什么,强制提供一个列表,还是允许一个字符串?

    3 回复  |  直到 6 年前
        1
  •  4
  •   abarnert    6 年前

    可以是thing或iterable或things的参数都是代码味道。更糟的是当它是一根弦,因为一根弦 一个iterable,甚至一个序列(所以你的测试 isinstance(names, Iterable) 会做错事)。

    Python stdlib确实有一些这样的案例是臭名昭著的, str.__mod__ 但是大多数错误都指向另一个方向,显式地要求一个元组而不是任何iterable,而且大多数都被认为是错误,或者至少是今天不会添加到语言中的东西。有时候这仍然是最好的答案,但是气味会让你在做之前思考。

    我不知道你的用例是什么,但我想这会更好:

    def spam(*names):
        namestr = ','.join(names)
        dostuff(namestr)
    

    现在用户可以这样调用它:

    spam('eggs')
    spam('eggs', 'cheese', 'beans')
    

    或者,如果他们碰巧有一个列表,它仍然很容易:

    spam(*ingredients)
    

    如果这不合适,另一个选项是keywords,甚至可能是keyword-only params:

    def spam(*, name=None, names=None):
        if name and names:
            raise TypeError('Not both!')
        if not names: names = [name]
    

    但是,如果最好的设计真的是一个字符串或一个(非字符串)字符串的iterable,或者一个字符串或一个字符串元组,那么标准的方法是类型切换。它可能看起来有点难看,但它提醒人们注意,你正在做的事情正是你在做的,而且它是以最习惯的方式做的。

    def spam(names):
        if isinstance(names, str):
            names = [names]
        dostuff(names)
    
        2
  •  1
  •   Moon_Raven    6 年前

    我允许使用列表和单个字符串作为参数。另外,我认为if/else解决方案没有任何问题,只是您可以直接检查参数是否是 str 类(而不是检查参数是否可iterable):

    def foo(arg1):
        if isinstance(arg1, str):
            print("It's a string!")
        else:
            print("It's not a string!")
    

    如果检查参数是否可iterable(字符串和列表都可iterable),请小心。

        3
  •  0
  •   Yicen Tian    6 年前

    使用isinstance()标识输入类型可以提供一个解决方案:

    def generate_names(input_term):
        output_list = []
        if isinstance(input_term,str):
            output_list.append(','.join(input_term.split()))
        elif isinstance(input_term,list):
            output_list.append(','.join(input_term))
        else:
            print('Please provide a string or a list.')
        return(output_list)
    

    这将允许您输入列表、单个名称的字符串以及包含多个名称(用空格分隔)的字符串:

    name = 'Eric'
    name1 = 'Alice John'
    namelist = ['Alice', 'Elsa', 'George']
    

    应用此函数:

    print(generate_names(name))
    print(generate_names(name1))
    print(generate_names(namelist))
    

    获取:

    ['Eric']

    [爱丽丝,约翰]

    [爱丽丝,艾尔莎,乔治]