2015-06-04 4 views
6

у меня есть проблема понимания того, что происходит с результатом следующих фрагментов кода:класс Python и глобальные против локальных переменных

my_str = "outside func" 
def func(): 
    my_str = "inside func" 
    class C(): 
     print(my_str) 
     print((lambda:my_str)()) 
     my_str = "inside C" 
     print(my_str) 

Выход:

outside func 
inside func 
inside C 

Другой кусок кода является:

my_str = "not in class" 
class C: 
    my_str = "in the class" 
    print([my_str for i in (1,2)]) 
    print(list(my_str for i in (1,2))) 

выход:

[‘in the class’, 'in the class’] 
['not in class’, 'not in class’] 

Возникает вопрос:

  1. Что происходит здесь, в каждой печати() заявление?
  2. Может ли кто-нибудь объяснить почему оператор print() получает строку из разных пространств имен?

Edit 1:

Я думаю, что это отличается от this question, потому что я смиренно думаю ответы там не объясняют этот вариант:

my_str = "outside func" 
def func(): 
    my_str = "inside func" 
    class C(): 
     print(my_str) 
     print((lambda:my_str)()) 
     #my_str = "inside C" 
     print(my_str) 

Выход есть:

inside func 
inside func 
inside func 

Редактировать 2:

В самом деле, это дубликат из this question, потому что, как говорит Мартин Питерс:

Ответ там говорится: Если имя назначается в пределах тела класса, почти в самом начале. Вы назначили my_str, сделав тот же случай , как и там. Комментируя эту строку означает, что вы больше не назначаете my_str, что делает его тем же случаем, что и x.


+0

@MartijnPieters Прекрасный ответ Антти там охватывает первый случай. Второй случай доходит до этого, но все же это не точный обман. Возможно, я оставлю эту ссылку для будущих посетителей на этот вопрос. (Вы уже подготовили проект обряда;)) –

+2

@BhargavRao: извините, я предположил, что вы ссылались на [Краткое описание правил определения Python] (http://stackoverflow.com/q/291978)! Это действительно обман. –

ответ

5

Есть четыре телескопы здесь:

  1. глобальный масштаб
  2. функция сфера
  3. тело класса
  4. лямбда-сфера

При созданииclass, тело класса выполняется как функция, и в качестве атрибутов класса используется локальное пространство имен этой «функции».

Однако тело класса не область видимости, и как таковая ведет себя иначе, чем функции. В теле функции привязка определяет область; назначить имя в функции, и оно помечено как локальное.В классе присвоение имени делает его глобальным, пока вы фактически не выполняете задание.

Так что ваш первый print() вызов находит my_str как глобальные, так как позже в теле класса вы связываетесь с именем. Это является следствием того, что классовые органы не участвуют в областях.

Далее вы определяете лямбду и называете ее. my_str никогда не назначается в этой лямбде, поэтому ее нужно найти в родительской области. Здесь тело класса не является областью видимости, а следующая область действия - область действия. Вот почему эта строка печатает inside func.

Последнее, что вы назначили локальному имени my_str в классе класса и напечатаете это локальное.

В момент удаления задания имена в классе рассматриваются как нелокальные; первый и последний операторы print() теперь равны, и имя просто просматривается в соответствии с обычными правилами определения области видимости.

+0

Не могли бы вы расширить свой ответ, чтобы объяснить изменение Edit1? – Dargor

+3

@PabloGalindoSalgado: ваше редактирование только * подтверждает *, что сообщение является обманом. –

+0

Мне так жаль, тогда. Я дважды читал ответы и не понимаю этого различия ... но прямо, как вы сказали. Время для кофе. :( – Dargor