问题描述
|
我在一个函数中使用argspec,该函数采用另一个函数或方法作为参数,并返回一个如下的元组:
((\"arg1\",obj1),(\"arg2\",obj2),...)
这意味着传递的函数的第一个参数为arg1,其默认值为obj1,依此类推。
麻烦之处:如果没有默认值,则需要一个占位符值来表示。我不能使用None,因为那样我就无法区分没有默认值和默认值为None。对于False,0,-1等也是如此。我可以使它成为具有单个元素的元组,但是用于检查它的代码将很难看,而且我无法轻易地将其变成字典。所以我想我会创建一个类似None的对象,它不是None,这就是我想出的:
class MetaNoDefault(type):
def __repr__(cls):
return cls.__name__
__str__ = __repr__
class NoDefault(object):
__Metaclass__ = MetaNoDefault
现在,(\"arg1\",NoDefault)
表示arg1没有默认值,我可以执行if obj1 is NoDefault:
等操作。元类使它仅显示为NoDefault
而不是<class \'__main__.NoDefault\'>
。
有什么理由不这样做吗?有更好的解决方案吗?
解决方法
我最喜欢的哨兵是
Ellipsis
,如果我可以引述自己的话:
它在那里,是一个对象,它是一个单例,其名称表示“缺少”,并且不是过度使用的None(可以作为一个部分放入队列中正常数据流)。 YMMV。
, 我前段时间也有类似情况。这是我想出的。
# Works like None,but is also a no-op callable and empty iterable.
class NULLType(type):
def __new__(cls,name,bases,dct):
return type.__new__(cls,dct)
def __init__(cls,dct):
super(NULLType,cls).__init__(name,dct)
def __str__(self):
return \"\"
def __repr__(self):
return \"NULL\"
def __nonzero__(self):
return False
def __len__(self):
return 0
def __call__(self,*args,**kwargs):
return None
def __contains__(self,item):
return False
def __iter__(self):
return self
def next(*args):
raise StopIteration
NULL = NULLType(\"NULL\",(type,),{})
它也可以充当null可调用和序列。
, 没有任何理由不出于此类目的使用此类哨兵对象。作为类对象的替代方法,您还可以创建动态创建类型的单例实例:
NoDefault = type(\'NoDefault\',(object,{
\'__str__\': lambda s: \'NoDefault\',\'__repr__\': lambda s: \'NoDefault\'})()