唯一常量引用



让我们以以下代码为例:

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返回一个具有给定键的dict,如果参数是可迭代的,则返回一个或多个键;如果参数为None,则返回空字典;如果参数是常量ALL,则返回整个字典。

当您想要返回一个名为"everything"的密钥时,就会出现此问题。Python可能对ALL和参数使用相同的引用(因为它们都是不可变的),这将使keys is ALL表达式成为True。因此,函数将返回整个dict,而不是预期的行为。

可以将ALL分配给专门为此目的定义的类的实例对象,或者使用type方法生成内联对象,这将使ALL成为唯一引用。不过,这两种解决方案似乎都有些过头了。

我也可以在函数声明中使用一个标志(即:def get_values(keys, all=False)),但我总是可以从另一个参数中导出一个参数的值(如果是all is True,那么是keys is None,如果是keys is not None,然后是All is not False),所以它看起来过于冗长。

你对前面提到的技术有什么看法,你认为还有其他可能的解决方法吗?

不要使用一个可能(不需要付出极大努力)是有效键的值作为sentinel。

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上的迭代器对其键进行迭代。

最新更新