检测Python中的kwarg覆盖

检测Python中的kwarg覆盖,python,Python,我正在寻找一种方法来检测关键字arg是否被显式传入,而不使用**kwargs 以下是一个例子: def foo(first, second=None): pass 如果在此函数中,我发现second包含None,是否有办法知道该None是默认值还是显式传入的?基本上,我有一个可选参数,可以是任何值或类型。因此,我要么需要某种“唯一”的默认值,这样用户就不会有意地传入该默认值,要么需要一种方法来检测参数是否确实显式传入 我希望我可以通过检查堆栈来发现它,但我觉得这太过分了 我也知道我可以

我正在寻找一种方法来检测关键字arg是否被显式传入,而不使用
**kwargs

以下是一个例子:

def foo(first, second=None):
    pass
如果在此函数中,我发现
second
包含
None
,是否有办法知道该
None
是默认值还是显式传入的?基本上,我有一个可选参数,可以是任何值或类型。因此,我要么需要某种“唯一”的默认值,这样用户就不会有意地传入该默认值,要么需要一种方法来检测参数是否确实显式传入

我希望我可以通过检查堆栈来发现它,但我觉得这太过分了

我也知道我可以这样做:

def foo(first, **kwargs):
    if 'second' in kwargs:
        # Overridden!
        pass

但我不愿意接受
**kwargs
,因为它会降低我的函数签名的实用性并隐藏错误。

您可以始终创建一个唯一的对象并将其用作默认值:

_default = object()

def foo(first, second=_default):
    if second is not _default:
        # Overridden!
        pass
完全正确:使用不是
None
的。很多时候,任何旧物体都可以

\u default=object()
有一个缺点:
\u default
不共享
None
的便利属性,即在条件语句中逻辑上等于
False
。也就是说,
None
是“假的”,但是
\u default
是“真的”。更正式地说,
bool(None)==False
但是
bool(\u default)==True

如果您可以创建新的
NoneType
实例,使其类似于
None
,但不完全是
None
,那就太好了。但是不能进一步实例化
NoneType
。不过,您可以创建一个类似的类。因此:

import sys

_PY3 = sys.version_info[0] == 3

class NullType(object):

    """
    A 'null' type different from, but parallel to, None. Core function
    is representing emptyness in a way that doesn't overload None.
    This helps create designated identifiers with specific meanings
    such as Passthrough, Prohibited, and Undefined.

    Instantiate to create desired null singletons. While they are
    singletons, depends on usage convention rather than strict
    enforcement to maintain their singleton-ness. This is a problem
    roughly 0% of the time.
    """

    def __init__(self, name=None):
        self.name = name

    def __repr__(self):
        if self.name is not None:
            return self.name
        else:
            return 'NullType(id: {0})'.format(id(self))

    if _PY3:
        def __bool__(self):
            """I am always False."""
            return False
    else:  # PY2
        def __nonzero__(self):
            """I am always False."""
            return False
将该代码放入
nulltype.py
中,然后:

from nulltype import NullType
_default = NullType('_default')

def foo(first, second=_default):
    if second is not _default:
        # Overridden!
        pass
但你也可以做到:

    if second:
        ...
(在某些上下文中)因为
second
的真值等于
None
。如果您使用了更简单的
\u default=object()
sentinel,则无法执行此操作,因为
bool(object())==True


现在,
\u默认值
是唯一的,在需要打印时可以很好地打印,并且总是等同于
False
。这是你自己的私人
None

除了使用不可怕的
**kwargs
之外,然后使用哨兵值。。。例如
sentinel=object()
然后检查
如果second不是sentinel
…谢谢,这太完美了。我喜欢它!我将把NPE的答案标记为真实答案,但这非常有用,谢谢!他的作品绝对具有简洁和内在的美。