2016-03-08 21 views
2

我有一個函數帶有兩個可選參數,我想要求兩者都可以,或者兩者都沒有指定。在Python中執行此操作的首選方式是什麼?我目前的做法似乎有點尷尬:配對的可選參數

def myfunc(data, opt1=None, opt2=None): 
    if opt1 is None or opt2 is None: 
     if not (opt1 is None and opt2 is None): 
      raise ValueError("Must specify both opt1 and opt2 or neither.")  

這個問題:Python Optional Argument Pair是我的一樣,但在​​具體的上下文;我對通常在函數內執行此操作的默認方式感興趣。

+1

'如果(OPT1是無)=(OPT2是None):提高ValueError異常(...)' – khelwood

+1

我覺得你的做法是你能做的最好的。除了在函數中用if語句檢查它之外,Python中沒有真正的「技巧」來強制執行這兩個或兩個可選參數。 –

回答

1

你可以定義一個函數

def ensure_both_or_neither(opt1, opt2): 
    if opt1 is None or opt2 is None: 
     if not (opt1 is None and opt2 is None): 
      raise ValueError("Must specify both opt1 and opt2 or neither.") 

然後從你的函數調用它:

def myfunc(data, opt1=None, opt2=None): 
    ensure_both_or_neither(opt1, opt2) 

我不認爲這是任何比你一部開拓創新的方式更好,但它是稍微明確的/可讀?

1
def myfunc(data, *args): 
    if(len(args)==0 or len(args)==2): 
     #do something 

是我會怎麼做

這也使您可以爲您希望有儘可能多的參數,並且只有在使用沒有或2的代碼運行

+0

不夠公平,但我希望除此之外可能還有更多的可選參數,計數可能會變得複雜。但是,我沒有在問題中具體說明。 – AGML

3

簡化的條件你正在尋找的是:如果兩個參數不上的is None同一側擠在一起

if (opt1 is None) != (opt2 is None): 
    raise ... 

這種情況是真實的。

1

您可以使用這樣一個事實:set刪除重複:

def myfunc(data, opt1=None, opt2=None): 
    if len({opt1 is None, opt2 is None}) - 1: 
     raise ValueError("Must specify both opt1 and opt2 or neither.") 

你可以做任何數量的參數:

def myfunc(data, *args): 
    if len({arg is None for arg in args}) - 1: 
     raise ValueError("Must specify all parameters or none.") 
0

如果你既不需要或兩者兼而有之,不接受兩個獨立的論點;接受單個可選元組和文檔它。不要讓用戶有機會只提供一個。

def myfunc(data, opts=None): 
    """blah blah blah 

    opts, if given, should be a tuple with two values, neither None. 
    """ 
    opt1, opt2 = opts if opts is not None else (None, None) 

你可以把默認(None, None),這將簡化你的函數(x1, x2 = opts)裏面的拆包,但塞滿您的函數的簽名爲代價。

(在現實中,opts可以是一個迭代有兩個元素,但如果用戶打電話像myfunc(data, "hi"),預計opt1hiopt2None,那是他的錯,不是你的。)

+0

如果元組是「(3,None)」,該怎麼辦?還是有同樣的問題。 – zondo

+0

我會打電話給用戶錯誤;他們並沒有忘記提供第二個參數,他們明確地*選擇了*以提供「無」作爲文檔化要求的值。 (最終,這歸結爲類型檢查,它在運行時通常是Python中調用者的責任。) – chepner

+0

我想到了這一點,但似乎在(3,無)情況下,我們可能會有代碼生成靜默行爲不正確。我們當然可以在功能中使用明確的檢查來防止這種情況發生,但是我們現在和以前一樣。所以我不清楚這個元組是如何幫助的。換句話說,我們可以依靠外部文檔*而不用*元組。 – AGML