строка питона по умолчанию глобальная - PullRequest
1 голос
/ 01 октября 2010

У меня есть вопрос о глобальной переменной в Python.Код следующий.Если я не использую глобальный M в функциональном тесте, он выдаст ошибку.Но почему это не показывает ошибку для строки s.Я не объявляю это глобальным.

global M
M = []
s = "abc"

def test():
    ### global M
    print M 
    M.append(s)

print M UnboundLocalError: локальная переменная 'M', на которую ссылается перед присваиванием

Ответы [ 3 ]

6 голосов
/ 01 октября 2010

Если я не использую глобальный M в функции test, выдаст ошибку.

Это ваше утверждение просто не правда !!!

>>> M = []
>>> s = "abc"
>>> 
>>> def test():
...     M.append(s)
... 
>>> M
[]
>>> test()
>>> M
['abc']

Я думаю, что вы путаете два совершенно и совершенно разных понятия:

  1. привязка голого имени - обычно по назначению (т.е. =), но также возможно несколькими другими утверждениями (def, & c)

  2. вызов метода (например, append), который "может" произойти, чтобы изменить объект (только если этот объект изменчив и метод является, конечно, мутатором, но это применяется, когда объект является списком и метод append)

Я не уверен, почему люди могут смешивать два полюса, но они, безусловно, могут. Может быть, это тот факт, что некоторые не-ванильные «виды» присваивания фактически вызывают (особый) метод «за кулисами», например, присваивание квалифицированным именам (a.b=c фактически вызывает type(a).__setitem__(a, b), поэтому, вызывая метод, не привязывающий никакое голое имя) и расширенное присваивание (a+=b фактически выполняет a = type(a).__iadd__(a, b), поэтому и вызывают метод и , повторно связывающее голое имя).

Вам нужно global (увы) тогда и только тогда, когда вы делаете «1»: повторное связывание голого имени (включая повторное связывание с помощью расширенного назначения, но не , включая любой другой особый случай). Откажитесь от global, если это действительно не нужно (и многие скажут, что оно никогда не будет действительно незаменимым ... просто "очевидно, удобно" в некоторых случаях; -).

3 голосов
/ 01 октября 2010

Я не совсем уверен, какую ошибку вы бы получили, но вы, похоже, используете глобальную неправильность.

Глобальное ключевое слово не требуется (или не рекомендуется) для объявления глобалов. Вместо этого он используется внутри функции, чтобы указать, что локальная переменная не должна создаваться. Рассмотрим 2 разные функции:

M = []

def test1():
    M = [1]

def test2():
    global M
    M = [2]

test1 создаст новую локальную переменную, а test2 запишет в глобальную M

0 голосов
/ 03 октября 2010

Как @Alex Martelli указал, что ваш код, показанный на рисунке, не приводит к ошибке, но, отложив ее на время до ответа @ cobbal (извините, я пока не могу комментировать), вы должны быть очень осторожными когда дело доходит до области действия

В ответе @ cobbal:

def test1():
    M = [1]

создает новую переменную M, локальную для функции test1.Однако, если бы вместо выполнения присваивания M = [1] он использовал M.append(1), как это было сделано в вопросе, вместо создания новой локальной переменной Python выглядел бы из локальной области видимости функции в более высокие области, в этомcase глобальная область действия, где действительно уже есть переменная M, которая указывает на пустой список.В этом случае Python найдет эту переменную и просто добавит к существующему списку, в результате чего глобальный M теперь будет указывать на [1].

Во втором примере:

def test2():
    global M
    M = [2]

Использованиеключевого слова global важно, чтобы избежать локального присваивания, которое могло бы произойти.Вызвав global использование M в локальной области действия функции, вы укажете на уже существующий объект [] вне функции.

Вы можете доказать это себе, вставив id(M) вразличные формы функции, чтобы показать, какие реализации заставляют M внутри функции указывать на глобальный или локальный объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...