Использование "глобального" ключевого слова в Python

Из прочтения документации я понимаю, что в Python есть отдельное пространство имен для функций, и если я хочу использовать глобальную переменную в этой функции, мне нужно использовать global,

Я использую Python 2.7, и я попробовал этот маленький тест

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

Кажется, что все работает хорошо, даже без global, Я смог получить доступ к глобальной переменной без каких-либо проблем.

Я что-то пропустил? Кроме того, следующее из документации Python:

Имена, перечисленные в глобальном операторе, не должны быть определены как формальные параметры или как цель управления циклом for, определение класса, определение функции или оператор import.

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

12 ответов

Решение

Ключевое слово global полезно только для изменения или создания глобальных переменных в локальном контексте, хотя создание глобальных переменных редко считается хорошим решением.

def bob():
    me = "locally defined"    # Defined only in local context
    print me

bob()
print me     # Asking for a global variable

Вышеуказанное даст вам:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print me
NameError: name 'me' is not defined

Хотя, если вы используете global Скажем, переменная станет доступной "вне" области действия функции, фактически превратившись в глобальную переменную.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print me

bob()
print me     # Asking for a global variable

Таким образом, приведенный выше код даст вам:

locally defined
locally defined

Кроме того, из-за природы Python, вы также можете использовать global объявлять функции, классы или другие объекты в локальном контексте. Хотя я бы посоветовал против этого, так как это вызывает кошмары, если что-то идет не так или требуется отладка.

Хотя вы можете получить доступ к глобальным переменным без global ключевое слово, если вы хотите изменить их, вы должны использовать global ключевое слово. Например:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

В вашем случае вы просто получаете доступ к списку sub,

В этом разница между доступом к имени и его привязкой в области видимости.

Если вы просто ищете переменную, чтобы прочитать ее значение, вы получите доступ к глобальной и локальной области видимости.

Однако, если вы назначаете переменную, имя которой не входит в локальную область, вы привязываете это имя к этой области (и если это имя также существует как глобальное, вы его скрываете).

Если вы хотите иметь возможность присваивать глобальное имя, вам нужно указать парсеру использовать глобальное имя, а не связывать новое локальное имя - это то, что делает ключевое слово "global".

Привязка в любом месте блока приводит к тому, что имя в этом блоке становится связанным, что может привести к некоторым довольно странным последствиям (например, UnboundLocalError, внезапно появляющийся в ранее работающем коде).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 

Другие ответы отвечают на ваш вопрос. Еще одна важная вещь, которую нужно знать об именах в Python, это то, что они являются локальными или глобальными для каждой области действия.

Рассмотрим это, например:

value = 42

def doit():
    print value
    value = 0

doit()
print value

Вы, вероятно, можете догадаться, что value = 0 оператор будет присваивать локальной переменной и не повлияет на значение той же переменной, объявленной вне doit() функция. Вы можете быть более удивлены, обнаружив, что приведенный выше код не будет работать. Заявление print value внутри функции производит UnboundLocalError.

Причина в том, что Python заметил, что в другом месте функции вы назначаете имя value, а также value нигде не объявлено global, Это делает его локальной переменной. Но когда вы пытаетесь распечатать его, локальное имя еще не определено. В этом случае Python не прибегает к поиску имени в качестве глобальной переменной, как это делают некоторые другие языки. По сути, вы не можете получить доступ к глобальной переменной, если вы определили локальную переменную с тем же именем в любом месте функции.

Доступ к имени и присвоение имени отличаются. В вашем случае вы просто получаете доступ к имени.

Если вы присваиваете переменную внутри функции, эта переменная считается локальной, если вы не объявили ее глобальной. В отсутствие этого он считается глобальным.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2
  • Вы можете получить доступ к глобальным ключевым словам без ключевого слова global
  • Чтобы иметь возможность их изменять, вам необходимо явно указать, что ключевое слово является глобальным. В противном случае ключевое слово будет объявлено в локальной области.

Пример:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]

Это хорошо объясняется в FAQ по Python.

Каковы правила для локальных и глобальных переменных в Python?

В Python переменные, на которые есть ссылки только внутри функции, неявно являются глобальными. Если переменной присваивается значение где-нибудь в теле функции, оно считается локальным, если явно не объявлено как глобальное.

Поначалу это немного удивительно, но небольшое размышление объясняет это. С одной стороны, требуяglobalдля присвоенных переменных обеспечивает защиту от нежелательных побочных эффектов. С другой стороны, еслиglobal требуется для всех глобальных ссылок, вы должны использовать globalвсе время. Вам нужно будет объявить какglobalкаждая ссылка на встроенную функцию или компонент импортированного модуля. Этот беспорядок сводит на нет полезностьglobal объявление для выявления побочных эффектов.

https://docs.python.org/3/faq/programming.html

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

делает переменную видимой для всего в модуле , модульной области , как если бы вы определили ее на верхнем уровне в самом модуле. Он не виден снаружи модуля, и его нельзя импортировать из модуля до тех пор, пока он не будет установлен, так что не беспокойтесь, он не для этого.

Когда решает настоящие проблемы? (Примечание: проверено только на Python 3.)

      # Attempt #1, will fail
# We cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to 
# do it automatically  when importing this module

top_level_something_or_other = None

def foo1():
    import catbus
    # Now ``catbus`` is visible for anything else defined inside ``foo()`` 
    # at *compile time*
    bar()  # But ``bar()`` is a call, not a definition. ``catbus`` 
           # is invisible to it.

def bar():
    # `bar()` sees what is defined in the module
    # This works:
    print(top_level_something_or_other)
    # This doesn't work, we get an exception: NameError: name 'catbus' is not defined
    catbus.run()

Это можно исправить с помощью:

      # Attempt #2, will work
# We still cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to 
# do it automatically  when importing this module

top_level_something_or_other = None

def foo2():
    import catbus
    global catbus  # Now catbus is also visible to anything defined 
                   # in the top-level module *at runtime* 
    bar()

def bar():
    # `bar` sees what is defined in the module and when run what is available at run time
    # This still works:
    print(top_level_something_or_other)
    # This also works now:
    catbus.run()

Это не было бы необходимо, если бы было определено внутри fooвот так:

      # Attempt 3, will work
# We cannot import ``catbus`` here
# as that would lead to an import loop somewhere else,
# or importing ``catbus`` is so expensive that you don't want to 
# do it automatically  when importing this module

top_level_something_or_other = None

def foo3():

    def bar():
        # ``bar()`` sees what is defined in the module *and* what is defined in ``foo()``
        print(top_level_something_or_other)
        catbus.run()

    import catbus
    # Now catbus is visible for anything else defined inside foo() at *compile time*
    bar()  # Which now includes bar(), so this works

Определив вне foo(), bar()можно импортировать во что-то, что может импортировать catbusнапрямую или смоделируйте его, как в модульном тесте.

это запах кода, но иногда вам нужен именно грязный хак, например global. В любом случае, «глобальный» — это плохое имя для него, поскольку в python нет такой вещи, как глобальная область видимости, это модули до самого низа.

Глобал делает переменную "Глобал"

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

Это заставляет 'x' действовать как обычная переменная вне функции. Если вы вынули глобальную переменную, это выдаст ошибку, поскольку она не может распечатать переменную внутри функции.

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)

Это означает, что вы не должны делать следующее:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"

Я приведу простой пример: подумайте об этом коде:

myVar = 0 
print (myVar )      # 01 line: returns 0

def func():
    myVar  = "def"
    print (myVar )

func()              # 02 line: returns def
print (myVar )      # 03 line: returns 0

как вы можете видеть, последняя строка кода вернет 0, потому что внутри функции переменная myVar не переназначена, она только что была изменена, и она изменится только при вызове функции, не затрагивая основную переменную myVar, потому что она определена внутри наша функция (означает, что это локальная переменная), но с использованием глобального ключевого слова как такового:

 myVar  = 0 
print (myVar )       # 01 Line : returns 0

def func():
    global myVar 
    myVar  = "def"
    print (myVar )

func()               # 02 Line : returns def
print (myVar )       # 03 Line : returns def

мы фактически заказываем python, что эта переменная внутри def не является локальной, используем глобальную переменную с именем myVar для ее изменения.

Другие вопросы по тегам