Python – 仅在变量存在时传递参数

Python — Only pass arguments if the variable exists

我有以下变量,用户可以选择通过表单提交(它们不是必需的,但可以这样做以过滤搜索)。

1
2
color = request.GET.get ('color')
size = request.GET.get ('size')

现在我想将这些变量传递给一个函数,但前提是它们存在。 如果它们不存在,我想只运行没有参数的函数。

没有参数的函数是:

1
apicall = search ()

只有它的颜色

1
apicall = search (color)

它的颜色和大小

1
apicall = search (color, size)

如果定义了参数,我想将它传递给函数,但如果不是,我不想传递它。

最有效的方法是什么? python有内置的方法吗?


假设这是一个标准的get调用(就像字典一样),这应该很容易。使用None定义函数以获取参数的默认值,然后传递colorsize而无需检查它们!

1
2
3
4
5
6
def apicall(color=None, size=None):
    pass # Do stuff

color = request.GET.get('color')
size = request.GET.get('size')
apicall(color, size)

这样,您只在一个地方检查None参数(在函数调用内部,无论如何,如果可以多种方式调用该函数,则必须检查)。一切都保持干净整洁。当然这假设(就像我在顶部说的那样)你的get调用就像普通的Python字典的get方法,如果找不到值,它返回None

最后,我注意到你的函数名是apicall:你实际上可能无法访问函数代码本身。在这种情况下,由于您可能对函数签名的默认值一无所知并且None可能是错误的,我可能只是编写一个简单的包装器来为您进行参数检查。然后你可以像上面那样调用包装器!

1
2
3
4
5
6
7
8
9
10
11
12
def wrapped_apicall(color=None, size=None):
    if color is None and size is None:
        return apicall()
    # At least one argument is not None, so...
    if size is None:
        # color is not None
        return apicall(color)
    if color is None:
        # size is not None
        return apicall(size)
    # Neither argument is None
    return apicall(color, size)

注意:除非您看不到您正在调用的代码并且没有任何文档,否则不需要第二个版本!使用None作为默认参数非常常见,因此您可以使用第一种方式。我只会使用包装器方法,如果你不能修改你正在调用的函数,你不知道它的默认参数是什么(或者它的默认参数是模块常量或其他东西,但这很少见)。


尽管我喜欢@HenryKeiter的解决方案,Python提供了一种更简单的方法来检查参数。事实上,有几种不同的解决方案。

  • 例如,如果search()是独立函数并且您想要查看args,则可以使用此解决方案中所示的inspect模块。
  • 示例代码1

    1
    2
    3
    4
    >>> import inspect
    >>> print(inspect.getfullargspec(search))

    ArgSpec(args=['size', 'color'], varargs=None, keywords=None, defaults=(None, None))
  • 但是,如果search()是类的方法(我们将其称为Search),那么您可以使用内置的vars函数来查看所有类方法及其参数:
  • 示例代码2

    1
    2
    3
    4
    5
    >>> import Search
    >>> print(vars(Search))

    mappingproxy({'__init__': <function Search.__init__(self, size, color)>,
                      'search': <function Search.search(self, size, color)})

    第二种方法唯一需要注意的是,它作为视觉检测工具更有用,而不是程序化工具,尽管技术上可以说if 'size' in vars(Search)['search']: do something。它不会非常强大。说if 'size' in inspect.getfullargspec(Search.search).args: do somethingfor arg in inspect.getfullargsspec(Search.search).args: do something更容易,更耐用


    在python 3中,您可以将它们打包在列表中,对其进行过滤,然后使用* -operator将列表解压缩为Search的参数:

    1
    2
    3
    4
    color = request.GET.get ('color')
    size = request.GET.get ('size')
    args = [ arg for arg in [color, size] if arg ]
    search(*args)

    但请注意,如果color是假的并且size是真实的,那么你将调用Search,其中1个参数是size的值,这可能是错误的,但原始问题没有提到所需的在这种情况下的行为。

    (因为我正在寻找比我更好的解决方案,但发现了这个问题)


    meybe你可以使用这样的东西:

    1
    2
    3
    4
    try:
        apicall = search (color, size)
    else:
        apicall = search(color)


    在定义方法时,如果设置了默认参数,则可以指定参数。

    1
    2
    def search(color=None, size=None):
        pass

    然后,当您调用它时,您可以根据需要指定关键字参数。这两个都是有效的:

    1
    2
    apicall = search(color=color)
    apicall = search(size=size)