2015-08-27 1 views
2

Хотя существует множество способов обойти это, из-за индивидуальной ошибки я не могу допустить этого, пока не пойму природу отказа.Атрибут класса словаря, который относится к другим атрибутам класса в определении

Попытка:

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? Это потому, что это в понимании словаря?

ответ

4

Да, это потому, что в понимании словаря. Обратите внимание, что это не «поиск» UNKNOWN; он просто не ищет его, потому что UNKNOWN ссылается только на лямбда. Если вы замените свое понимание dict на что-то еще, чтобы определение класса было успешным, вы получите сообщение об ошибке позже, если попытаетесь получить доступ к несуществующему ключу (потому что тогда он попытается вызвать эту лямбда). Так что если вы измените его на

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) 

И лямбда и словарь понимание создания функциональных областей, вложенных в область видимости класса, так что они не имеют доступа к переменным класса напрямую. См. Также this related question.

+0

В том, что я хотел бы добавить, наиболее предпочтительный путь вокруг этого будет определять (некоторые или все) эти переменные в методе '__init __()' класса с 'self.FAVE = [...]'. – Sam

+0

Спасибо! Но это все еще так странно; почему этот случай? Я думал, что всегда было так, что вложенные области имели доступ к родительской области в Python. По крайней мере, так было в моем опыте. – eriophora

+0

@eriophora: Области классов разные. См. Вопрос, который я связал, для некоторого обсуждения этого. – BrenBarn