2011-05-31 55 views
7

我在另需函数或方法作为自变量的函数使用argspec,并返回这样的元组:定制占位符等没有在python

(("arg1", obj1), ("arg2", obj2), ...) 

这意味着第一个参数传递函数是arg1,它有一个默认值obj1,依此类推。

这里是擦:如果它没有默认值,我需要一个占位符值来表示这一点。我无法使用无,因为那时我无法区分没有默认值默认值是无。对于False,0,-1等也是如此。我可以用一个元素使它成为一个元组,但是用于检查它的代码将会很难看,我不能轻易将它变成字典。所以,我想我会创造一个无状物体不是没有了,这是我想出来的:

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'>

有什么理由不这样做吗?有更好的解决方案吗?

+0

是否有任何理由为什么你不能有没有默认值只有一个元素的元组?类似于:((“arg1”,),(“arg2”,obj2),...)“其中”arg1“没有默认值。你可以这样做,如果'len(the_tuple)== 1'等 – Fenikso 2011-05-31 10:05:42

+2

@FMc:为了避免错误来自默认参数的意外修改,最好不要使用可变默认值。 – lunaryorn 2011-05-31 10:07:08

+0

@Fenikso我在我的问题中涵盖了这种可能性。总之,尽管它很直观,但我觉得它不够雅致。 – 2011-05-31 10:21:07

回答

5

我最喜欢的哨兵是Ellipsis,如果我可以quote自己:

它的存在,它是一个对象,这是一个单身,和它的名字的意思是“缺乏”,这是不是过度使用无(可以作为正常数据流的一部分放入队列中)。因人而异。

+1

但是,它正在Python 3中消失:-o – Keith 2011-05-31 11:36:00

+3

@Keith:请引用。在Python 3中的AFAIK,你甚至可以说'a = ...'(即'''语法可以用在片段之外),所以我觉得它并没有消失。 – tzot 2011-05-31 12:26:54

+0

看来我可以引用[甚至更早](http://mail.python.org/pipermail/python-list/2004-August/273139.html):) – tzot 2011-05-31 14:30:39

3

没有任何理由不为此目的使用此类哨兵对象。作为替代,以一个类的对象,你也可以创建一个动态创建类型的单一实例:

NoDefault = type('NoDefault', (object,), { 
    '__str__': lambda s: 'NoDefault', '__repr__': lambda s: 'NoDefault'})() 
4

我前一段时间也有类似的情况。这是我想出来的。

# 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, name, bases, dct) 
    def __init__(cls, name, bases, dct): 
     super(NULLType, cls).__init__(name, bases, 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可调用和序列。