2013-11-16 5 views
0

Update

Благодаря @ jwodder-х ответ ниже, это постепенно становится яснее мне.NameError: определения функции против/словарных определений классов в Python

Вот упрощенный пример, который до сих пор меня смущает:

Это - где упоминается впоследствии определена переменная в определении функции - работает отлично:

#module.py 
def function_scope(): 
    var = global_var 
    return var 

def print_global(): 
    var = function_scope() 
    print var 

global_var = "Here I am!" 

#shell: 
>>> from module import print_global 
>>> print_global() 
Here I am! 

Но это - где переменная упоминается в определении класса - не удается:

#module.py 
class ClassScope(): 
    var = global_var 

def print_global(): 
    var = ClassScope.var 
    print var 

global_var = "Here I am!" 

#shell 
>>> from module import print_global 
NameError: name 'global_var' is not defined 

Это означает, что class ClassScope() определение «выполняется» в момент им порт. Напротив, определение def function_scope() «выполняется» при вызове функции (т. Е. После импорта, и, следовательно, функция имеет доступ к полному глобальному охвату модуля).

  1. Я думаю об этом правильно в целом? Понятие «исполняющая» функция/класс определения кажется странным для меня.
  2. Почему это несоответствие между определениями функций и определениями классов?
  3. Есть ли способ отложить выполнение определения класса, т. Е. Заставить его вести себя как функция, тем самым предоставляя ему доступ ко всей области модуля, которая существовала бы после успешного импорта?

Еще раз спасибо.

Оригинал Вопрос

Первоначально я пытался реализовать функцию, которая принимает имя класса и возвращает объект этого класса. Но по пути я понял, что у меня нет хорошего понимания области действия .. (Или, может быть, вопрос переменная времени жизни?)

Почему следующая работа ...

#module.py 
def create_object(class_name): 
    classes = { 
     'ClassA':ClassA, 
    } 
    return classes[class_name]() 

class ClassA(object): 
    pass 

#script.py 
from module import create_object 
obj = create_object('ClassA') 

... но это не удается?

#module.py 
CLASSES = { 
    'ClassA':ClassA, 
} 

def create_object(class_name): 
    return CLASSES[class_name]() 

class ClassA(object): 
    pass 

#script.py 
from module import create_object 
obj = create_object('ClassA') 

Вот исключение:

Traceback (most recent call last): 
    File "script.py", line 2, in <module> 
    from module import create_object 
    File ".../module.py", line 3, in <module> 
    'ClassA':ClassA, 
NameError: name 'ClassA' is not defined 

Похоже ClassA не в объеме, как это время упоминается в CLASSES словаре во втором примере. Но, если это так, почему это видно изнутри create_object() в первом примере?

Любая помощь в понимании этого очень ценится. Большое спасибо!

ответ

0

Это связано с точкой, в которой происходит поиск имени, а не с областью. Python пытается связать идентификатор с объектом или классом, когда выполняется код с использованием этого идентификатора.В первом фрагменте кода имени ClassA в create_object присваивается значение только тогда, когда выполняется create_object(), после чего выполняется определение class ClassA, которое создает ClassA. Во втором фрагменте кода вы пытаетесь выполнить код, который ссылается на ClassA, до того, как ClassA был определен, что создает ошибку.

+0

О, интересно! Основываясь на вашем ответе, я переместил глобальное определение словаря 'CLASSES' в начало модуля.py в фрагменте # 2. И это работает. Но почему же определение класса Class A считается «уже выполненным», когда оно ссылается изнутри функции 'create_object()' в фрагменте # 1? – tino

+0

Я предполагаю, что меня смущает фраза *, «когда код с использованием этого идентификатора выполнен» * в вашем ответе. Если порядок объявлений имеет значение в фрагменте №2, почему это не имеет значения в фрагменте №1? Или, может быть, я хочу спросить: когда выполняется определение класса Class A? – tino

+0

@tino: Определение класса Class A выполняется, как только он встречается парсером (грубо говоря). Обратите внимание, что когда встречается определение 'create_object', оно« выполняется »в том смысле, что тело функции связано с именем' create_object', но фактический код внутри тела * не * выполняется до 'create_object() '. Это похоже на использование глобальной переменной внутри функции: функция будет использовать значение переменной * во время вызова функции *, а не во время определения функции. – jwodder

Смежные вопросы