让我们以下面的代码为例:
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 函数返回一个带有给定键的字典,如果参数是可迭代对象则返回 keys,如果参数是 None 则返回空字典,如果参数是常量 ALL 则返回整个字典。
当您想要返回一个名为“everything”的键时,就会出现这个问题。 Python 可能对 ALL 和参数使用相同的引用(因为它们都是相同的不可变),这将使 keys is ALL 表达式为 True。因此,该函数将返回整个字典,而不是预期的行为。
可以将 ALL 分配给专门为此目的定义的类的实例对象,或者使用 type 方法生成内联对象,这将使 ALL 成为唯一引用。不过,这两种解决方案似乎都有些矫枉过正。
我也可以在函数声明中使用一个标志(即:def get_values(keys, all=False)),但是我总是可以从另一个参数中导出参数的值(如果all is True, then keys is None, 如果keys is not None, then All is not False),所以它看起来过于冗长。
您对前面提到的技术有何看法,您是否看到其他可能的解决方法?
请您参考如下方法:
不要使用可能(不费吹灰之力)成为有效 key 的值作为标记。
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 可以采用 any 可迭代的事实,并且 dict 上的迭代器迭代它的键。
