2011-08-12 126 views
7

很長時間以來,我一直在試圖找出將標誌傳遞給python函數的最佳方式。最直接的方法是一樣的東西:Python:將標誌傳遞給函數

def func(data, flag1, flag2, flag3): 
    ... 

func(my_data, True, False, True) 

這是非常好的,簡潔,但令人難以置信的難以辨認,因爲這個詞「真」或「假」不能告訴你正在設置什麼標誌,和你必須仔細計算從左邊開始的論點。你可以讓它們成爲關鍵字參數:

def func(data, flag1=False, flag2=False, flag3=False): 
    ... 

func(my_data, flag1=True, flag3=True) 

但是這是多餘的,因爲「真」根本沒有任何意義。我可以把它作爲一個清單:

func(mydata, ['flag1', 'flag3']) 

func(mydata, [func.flag1, func.flag3]) 

但第一感覺比較髒,使用字符串作爲標誌,第二個還是有點重複。理想情況下,我想說的是:

func(my_data, flag1, flag3) 

將標誌傳遞給具有最小冗餘和冗餘的函數。有什麼辦法在Python中做這樣的事情?

編輯: 我結束了去:

func(mydata, flagA=1, flagB=1) 

主要用於上述原因:編譯時檢查(對傳入的字符串),沒有命名空間污染(相對於使用全局「ENUM」 S )和最小的樣板(= 1或= 0僅爲2個字符,對於= True或= False則爲5或6)。這也使得該標誌很容易設置的默認值:

def func(data, flagA=1, flagB=0, flagC=1): 
    ... 

這是更爲清晰,遠遠高於鐵圈跳提取並分配默認爲** kwarg風格的標誌更容易。這些標誌基本上是靜態檢查的,並且非常清晰/可以寫入。現在,如果我能刮掉的最後兩個字符...

+1

你爲什麼想/需要傳遞的標誌擺在首位?也許你應該重新考慮你的接口...... –

+0

這些標誌將被用來設置數據結構中的布爾值,然後這些布爾值將控制對數據結構進行操作的函數的未來行爲。這完全不是面向對象的方法,但我選擇它不是簡單的;不管怎樣,即使我做到了OO風格,行爲變化也很微妙,可能不值得創建一個完整的類來處理。 –

+0

也許你可以傳遞一個包含值的(簡單的)數據結構呢?一個'集'的標誌,或'Dict'映射標誌名稱bools ... –

回答

3

一些Python標準庫使用:

re.match(pattern, str, re.MULTILINE | re.IGNORECASE) 

您可以通過使用* ARGS調整這種方法:

my.func(a, b, c, my.MULTLINE, my.IGNORECASE) 

我真的建議用標誌1 =真打算:

  • 它可讀
  • 在編譯時檢查標誌名稱時間(除非** kwargs使用)
  • 可以使用,而不是真和假標誌= 1和標誌= 0,以減少噪聲
  • 可以暫時改變LONG_FLAG_NAME_YOU_DONT_REMEMBER =真爲False無需重新鍵入長名稱時將需要改回
3

帶*號ARGS:

def some_func(data, *args): 
    # do something 
    return args # this is just to show how it works 


>>> print some_func(12, 'test', 'test2', 'test3') 
('test', 'test2', 'test3') 

這是一個很好的問題,瞭解kwargs指定參數和如何* **工作:*args and **kwargs?

5

您可以定義flag1 ... flagN爲全局變量,並與func(*args)

FLAG1 = 1 
FLAG2 = 2 

def func(*args): 
    pass 

func(FLAG1, FLAG2) 

通過defini定義功能ng標誌,而不是使用字符串,可以避免在標誌名稱中出現拼寫錯誤,並且在調試時會出現一些頭痛的問題。

-1

我更喜歡沒有標誌的函數。相反,這樣做:

def func_flag1(arg): 
    pass # something useful 

def func_flag2(arg): 
    pass # something for flag 2. 

但是「flagX」實際上是像「do_X_with_option」這樣有意義的東西。我更喜歡這個,因爲它使得它更清晰,讓函數更簡單(更少的bug),並且你不必將一些常量帶入其他模塊(在標誌實際上是某種枚舉的情況下)。

+0

問題是我的標誌相當獨立;因此需要O(n)個標誌會花費O(2^n)個函數來模擬。我現在有2個標誌,這將需要4個功能,並且即使是3個或4個標誌也會很快失控 –

3

翻轉它怎麼樣?

flag1, flag2, flag3, flag4, flag5, flag6 = range(6) 

def func(enable=[], disable=[], 
     enabled_by_default=[flag5, flag6]): 
    enabled = set(enabled_by_default + enabled) - set(disabled) 
    if flag1 in enabled: 
     ... 
    if flag2 in enabled: 
     ... 

func(enable = [flag1, flag2, flag3], 
    disable = [flag6]) 
3

我失蹤好老bitwise標誌:

a = 1 
b = 2 
c = 4 
d = 8 

def func(data, flags): 
    print((flags & a) == a) 
    print((flags & b) == b) 
    print((flags & c) == c) 
    print((flags & d) == d) 

>>>> func("bla", a|c|d) 
>>>> True 
>>>> False 
>>>> True 
>>>> True 
+0

感謝您提供此信息。我在谷歌上搜索了半小時的「python bit flags」。 – Arne