2015-11-03 45 views
1

讓我們作爲例子下面的代碼:獨特的恆定參考

ALL = "everything" 

my_dict = {"random":"values"} 

def get_values(keys): 
    if keys is None: 
     return {} 
    if keys is ALL: 
     return my_dict 
    if not hasattr(keys, '__iter__') 
     keys = [keys] 
    return {key: my_dict[key] for key in keys} 

如果參數是一個可迭代get_values返回與給定鍵的字典,或鍵功能,一個空的字典如果參數是無或者如果參數是常量ALL,則爲整個字典。

當你想要返回一個名爲「everything」的鍵時,會發生這個問題。 Python可能會對ALL和參數​​使用相同的引用(因爲它們都是相同的不可變的),這會使keys is ALL表達式True。該函數將因此返回整個字典,所以不是預期的行爲。

可以將ALL分配給專門爲此目的定義的類的實例對象,或者使用type方法生成內聯對象,這將使所有對象成爲唯一引用。這兩個解決方案似乎有點矯枉過正。

我還可以使用一個標誌函數聲明(即:def get_values(keys, all=False)),但後來我總是可以從另一個派生一個參數的值(如果all is True,然後keys is None,如果keys is not None,然後All is not False),所以它似乎過於冗長。

您對前面提到的技術有什麼看法,您是否看到其他可能的解決方法?

+5

你問的是一個合適的*哨兵值*會是什麼?爲什麼不'ALL = object()'?這與自己完全相同(也可能相等),但沒有其他內容(請參閱http://stackoverflow.com/a/23703899/3001761)。 – jonrsharpe

+0

PEP 0020哥們,做一個叫做get_all_values()的函數怎麼樣? – Brian

回答

5

不要使用可能(無需付出極大努力)有效密鑰作爲標記的值。

ALL = object() 

但是,定義函數以獲取(可能爲空)序列的鍵似乎更簡單。

def get_values(keys=None): 
    if keys is None: 
     keys = [] 
    rv = {} 
    for key in keys: 
     # Keep in mind, this is a reference to 
     # an object in my_dict, not a copy. Also, 
     # you may want to handle keys not found in my_dict: 
     # ignore them, or set rv[key] to None? 
     rv[key] = my_dict[key] 
    return rv 

d1 = get_all_values() # Empty dict 
d2 = get_all_values([]) # Explicitly empty dict 
d3 = get_all_values(["foo", "bar"]) # (Sub)set of values 
d4 = get_all_values(my_dict) # A copy of my_dict 

在最後一種情況下,我們採取的事實get_all_values可以採取任何迭代,並在dict遍歷其密鑰的迭代器的優勢。