我正在寻找一种方法来检测是否明确传递了关键字arg,而不使用**kwargs
。
以下是一个例子:
def foo(first, second=None):
pass
如果在此函数中我发现second
包含None
,是否有办法知道None
是来自默认值,还是已明确传入?基本上,我有一个可选的参数,可以想象是任何值或类型。所以我要么需要某种“唯一”默认值,这样用户就不会故意传递那个默认值,或者我需要一种方法来检测参数是否实际上是明确传递的。
我希望我可以通过检查堆栈来发现它,但我觉得这太过分了。
我也知道我可以这样做:
def foo(first, **kwargs):
if 'second' in kwargs:
# Overridden!
pass
但我不想接受**kwargs
,因为它使我的函数签名不那么有用并且可以隐藏错误。
答案 0 :(得分:4)
您始终可以创建唯一对象并将其用作默认对象:
_default = object()
def foo(first, second=_default):
if second is not _default:
# Overridden!
pass
答案 1 :(得分:2)
NPE's answer完全正确:使用不是None
的{{3}}。任何旧的sentinel value对象都会在很长一段时间内完成。
_default = object()
有一个缺点:_default
不会在条件中共享None
在逻辑上等于False
的方便属性。也就是说,None
是“假的”,但_default
是“真实的”。更正式的是bool(None) == False
bool(_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
。如果您使用了更简单的_default = object()
哨兵,则无法执行此操作,因为bool(object()) == True
。
现在_default
是唯一的,在需要打印时打印得很好,并且始终等同于False
。这是你自己的私人None
。