2012-09-04 211 views
8

我在尋找模仿內置函數(如getattr)允許用戶指定「默認」返回值的行爲。我最初的嘗試是要做到這一點python - 返回默認值

def myfunc(foo, default=None): 
    # do stuff 
    if (default is not None): 
     return default 
    raise SomeException() 

的問題是,如果用戶想要None成爲他們的返回值,這個功能反而會引發異常。第二次嘗試:

def myfunc(foo, **kwargs): 
    # do stuff 
    if ('default' in kwargs): 
     return kwargs['default'] 
    raise SomeException() 

這解決了上述問題,並允許用戶指定任意值,但引入了在一個煩惱,用戶必須始終指定default=bar在他們的函數調用;他們不能僅在末尾提供bar。同樣,可以使用*args,但如果用戶喜歡該語法,則可以防止用戶使用default=bar

結合*args**kwargs提供了一個可行的解決方案,但它感覺這需要付出很大的努力。它也可能掩蓋不當的函數調用(如bar = myfunc(foo, baz, default=qux)

def myfunc(foo, *args, **kwargs): 
    # do stuff 
    if (len(args) == 1): 
     return args[0] 
    if ('default' in kwargs): 
     return kwargs['default'] 
    raise SomeException() 

是否有一個簡單的解決方案? (蟒蛇3.2,如果該事項)

回答

14

您需要使用定點檢測到一個默認值未設置:

sentinel = object() 

def func(someparam, default=sentinel): 
    if default is not sentinel: 
     print("You passed in something else!") 

這工作,因爲object()一個實例總是有它自己的內存ID,因此is將只返回True,如果確切的值留在原地。 其他任何值都不會註冊爲同一個對象,包括None

您會在各種不同的python項目中看到上述技巧的不同變體。任何以下哨兵也將工作:

sentinel = [] 
sentinel = {} 
+0

這是很簡單,謝謝! – Steve

+0

無論如何阻止人們通過哨兵? –

+2

@hayden:當然不是,這是python。你通常將它命名爲'_sentinel'或類似的將它標記爲私有的,但是這並不能阻止有進取精神的人通過導入它而破壞一切。當然,這樣做沒有意義。 –