虽然有很多方法可以解决这个问题,但由于性格上的缺陷,我不能放过它,直到我理解失败的本质。
尝试:
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
?是因为它在字典理解中吗?
答案 0 :(得分:4)
是的,这是因为它符合词典理解。请注意,它不是“找到”UNKNOWN
;它只是没有找到它,因为UNKNOWN
仅在lambda中引用。如果你用其他东西替换你的dict理解以允许类定义成功,如果你试图访问一个不存在的键,你将会在以后遇到错误(因为它会尝试调用该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 Foo(object):
something = "Hello"
def meth(self):
print(something)
lambda和字典理解都创建嵌套在类范围内的函数作用域,因此它们无法直接访问类变量。另请参阅this related question。