引用定义中其他 class 属性的字典 class 属性

Dictionary class attribute that refers to other class attributes in the definition

虽然解决这个问题的方法有很多,但由于性格缺陷,我不能放手,直到我了解失败的本质。

正在尝试:

class OurFavAnimals(object):
    FAVE = 'THATS ONE OF OUR FAVORITES'
    NOTFAVE = 'NAH WE DONT CARE FOR THAT ONE'
    UNKNOWN = 'WHAT?'
    FAVES = defaultdict(lambda: UNKNOWN, {x:FAVE for x in ['dog', 'cat']})
    FAVES['Crab'] = NOTFAVE 

失败:

      3     NOTFAVE = 'NAH WE DONT CARE FOR THAT ONE'
      4     UNKNOWN = 'WHAT?'
----> 5     FAVES = defaultdict(lambda: UNKNOWN, {x:FAVE for x in ['dog', 'cat']})
      6     FAVES['Crab'] = NOTFAVE

NameError: global name 'FAVE' is not defined

为什么?为什么能找到UNKNOWN却找不到FAVE?是不是因为在字典理解中?

是的,这是因为它在字典理解中。请注意,它也不是 "finding" UNKNOWN;它只是还没有在寻找它,因为 UNKNOWN 仅在 lambda 中被引用。如果你用其他东西替换你的字典理解以允许 class 定义成功,如果你稍后尝试访问一个不存在的键(因为它会尝试调用那个 lambda),你会得到一个错误。所以如果你把它改成

FAVES = defaultdict(lambda: UNKNOWN, {'a': 1})

您将获得:

>>> OurFavAnimals.FAVES['x']
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    OurFavAnimals.FAVES['x']
  File "<pyshell#2>", line 5, in <lambda>
    FAVES = defaultdict(lambda: UNKNOWN, {'a': 1})
NameError: global name 'UNKNOWN' is not defined

在这两种情况下,原因是 class 作用域中定义的变量在嵌套作用域中不可用。换句话说,这与失败的原因相同:

class Foo(object):
    something = "Hello"
    def meth(self):
        print(something)

lambda 和字典理解都会创建嵌套在 class 作用域中的函数作用域,因此它们无法直接访问 class 变量。另见 this related question