如何检查是否设置了可选功能参数 [英] How to check whether optional function parameter is set

查看:94
本文介绍了如何检查是否设置了可选功能参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python中是否有一种简便的方法来检查可选参数的值是否来自其默认值,或者是因为用户已在函数调用中明确设置了可选参数?

Is there an easy way in Python to check whether the value of an optional parameter comes from its default value, or because the user has set it explicitly at the function call?

推荐答案

很多答案都没有完整的信息,因此,我想将它们与我最喜欢的模式结合在一起.

Lot of answers have little pieces of the full info, so I'd like to bring it all together with my favourite pattern(s).

如果默认值是可变对象,那么您很幸运:您可以利用以下事实:在定义函数时,Python的默认参数将被评估一次(在上一节的答案末尾对此有更多了解)

If the default value is a mutable object, you are lucky: you can exploit the fact that Python’s default arguments are evaluated once when the function is defined (some more about this at the end of the answer in the last section)

这意味着您可以使用is轻松比较默认的可变值,以查看它是作为参数传递还是默认保留,如以下示例中作为函数或方法所示:

This means you can easily compare a default mutable value using is to see if it was passed as an argument or left by default, as in the following examples as function or method:

def f(value={}):
    if value is f.__defaults__[0]:
        print('default')
    else:
        print('passed in the call')

class A:
    def f(self, value={}):
        if value is self.f.__defaults__[0]:
            print('default')
        else:
            print('passed in the call')

不可变的默认参数

现在,如果您的默认值预期为immutable值(请记住,即使字符串是不可变的!),这也就不太优雅了,因为您无法按原样利用该技巧,但是仍然有一些需要注意的地方可以做,仍然在使用可变类型;基本上,您将 mutable 假"默认值放在函数签名中,并将所需的真实"默认值放在函数主体中.

Immutable default arguments

Now, it's a bit less elegant if your default is expected to be an immutable value (and remember that even strings are immutable!) because you can't exploit the trick as it is, but there is still something you can do, still exploiting mutable type; basically you put a mutable "fake" default in the function signature, and the desired "real" default value in the function body.

def f(value={}):
    """
    my function
    :param value: value for my function; default is 1
    """
    if value is f.__defaults__[0]:
        print('default')
        value = 1
    else:
        print('passed in the call')
    # whatever I want to do with the value
    print(value)

如果您真正的默认值是None,这会特别有趣,但是None是不可变的,因此...您仍然需要显式地使用mutable作为函数的默认参数,并在代码中切换为None.

It feels particularly funny if you real default is None, but None is immutable so... you still need to explicitly use a mutable as the function default parameter, and switch to None in the code.

或类似于@ c-z的建议,如果python文档不够用:-),则可以在两者之间添加一个对象以使API更加明确(无需阅读文档); used_proxy_默认类实例是可变的,并且将包含您要使用的实际默认值.

or, similar to @c-z suggestion, if python docs are not enough :-) , you can add an object in between to make the API more explicit (without reading the docs); the used_proxy_ Default class instance is mutable, and will contain the real default value you want to use.

class Default:
    def __repr__(self):
        return "Default Value: {} ({})".format(self.value, type(self.value))

    def __init__(self, value):
        self.value = value

def f(default=Default(1)):
    if default is f.__defaults__[0]:
        print('default')
        print(default)
        default = default.value
    else:
        print('passed in the call')
    print("argument is: {}".format(default))

现在:

>>> f()
default
Default Value: 1 (<class 'int'>)
argument is: 1

>>> f(2)
passed in the call
argument is: 2

以上对于Default(None)也很好.

显然,由于所有print都仅用于显示它们的工作方式,因此上述模式看起来比应有的丑陋.否则,我会觉得它们很简洁且可重复.

Obviously the above patterns looks uglier than they should because of all the print which are there only for showing how they work. Otherwise I find them terse and repeatable enough.

您可以编写一个装饰器,以更简化的方式添加@dmg建议的__call__模式,但这仍然必须在函数定义本身中使用怪异的技巧-您需要将valuevalue_default如果您的代码需要区分它们,那么我看不出太多优势,因此我不会编写示例:-)

You could write a decorator to add the __call__ pattern suggested by @dmg in a more streamlined way, but this will still oblige to use weird tricks in the function definition itself - you would need to split out value and value_default if your code need to distinguish them, so I don't see much advantage and I won't write the example :-)

有关#1 python陷阱的更多信息! ,出于您自己的喜好而被滥用. 您可以通过执行以下操作来查看由于定义评估而发生的事情:

A bit more about #1 python gotcha!, abused for your own pleasure above. You can see what happens due to the evaluation at definition by doing:

def testme(default=[]):
    print(id(default))

您可以根据需要多次运行testme(),您将始终看到对同一默认实例的引用(因此,您的默认实例基本上是不可变的:-)).

You can run testme() as many time as you want, you will always see a reference to the same default instance (so basically your default is immutable :-) ).

请记住,在Python中只有3种可变的内置类型: setlistdict;其他一切-甚至弦乐! -是一成不变的.

Remember that in Python there are only 3 mutable built-in types: set, list, dict; everything else - even strings! - is immutable.

这篇关于如何检查是否设置了可选功能参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆