2011-05-31 46 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可調用和序列。