Как я могу создать или использовать глобальную переменную в функции?
Если я создаю глобальную переменную в одной функции, как я могу использовать эту глобальную переменную в другой функции? Нужно ли мне хранить глобальную переменную в локальной переменной функции, которой нужен доступ?
Вы можете изучить понятие пространства имен. В Python модуль - естественное место для данных Глобальный:
Each module has its own private symbol table, which is used as the global symbol table by all functions defined in the module. Thus, the author of a module can use global variables in the module without worrying about accidental clashes with a user’s global variables. On the other hand, if you know what you are doing you can touch a module’s global variables with the same notation used to refer to its functions,
modname.itemname
.
Здесь описано конкретное использование global-in-a-module - Как поделиться глобальными переменными между модулями?, и для полноты его содержимое доступно здесь:
The canonical way to share information across modules within a single program is to create a special configuration module (often called config or cfg). Just import the configuration module in all modules of your application; the module then becomes available as a global name. Because there is only one instance of each module, any changes made to the module object get reflected everywhere. For example:
File: config.py
x = 0 # Default value of the 'x' configuration setting
File: mod.py
import config
config.x = 1
File: main.py
import config
import mod
print config.x
@vladosaurus from config import x
решает эту проблему?
@vladosaurus использует from config import x
Вы можете использовать глобальную переменную в других функциях, объявив ее как global
в каждой функции, которая присваивает ей значение:
globvar = 0
def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1
def print_globvar():
print(globvar) # No need for global declaration to read value of globvar
set_globvar_to_one()
print_globvar() # Prints 1
Я предполагаю, что причина этого в том, что, поскольку глобальные переменные настолько опасны, Python хочет убедиться, что вы действительно знаете, с чем играете, явно запрашивая ключевое слово global
.
См. Другие ответы, если вы хотите использовать глобальную переменную в разных модулях.
Называть глобальные объекты «настолько опасными» - это крайнее преувеличение. Глобалы прекрасно подходят для всех языков, которые когда-либо существовали и будут существовать. У них есть свое место. Вы должны были сказать, что они могут вызвать проблемы, если вы не знаете, как программировать.
Я считаю, что они довольно опасны. Однако в Python «глобальные» переменные на самом деле являются уровнями модуля, что решает множество проблем.
Я не согласен с тем, что Python требует ключевое слово global
, потому что глобальные переменные опасны. Скорее, это потому, что язык не требует от вас явного объявления переменных и автоматически предполагает, что переменная, которую вы назначаете, имеет область действия, если вы не укажете иное. Ключевое слово global
- это средство сказать обратное.
@avgvstvs: И если вы реализуете ту же программу без глобальных переменных, у вас все равно будет такое же количество путей кода. Вы привели аргумент не против глобальных переменных.
@LightnessRacesinOrbit, нет, не пойдет. В этом контексте, если вы просто добавили одно логическое значение к одной функции в этом сценарии, тогда у вас будет 2 ^ 4 + 2 ^ 3 + 2 ^ 3 (32) кодовых пути вместо (2 ^ 3 + 2 ^ 3 + 2 ^ 3) ^ 2 (576). И даже если вы добавили четвертый параметр ко ВСЕМ функциям, это 48 путей кода вместо 576.
@avgvstvs: Нет, потому что для получения той же семантики программы вам нужно будет передать это логическое значение по ссылке (чтобы изменения еще раз повлияли на все другие функции). Количество путей кода строго одинаково (даже по определению), если вы не измените семантику программы, независимо от того, как вы реализуете указанную программу.
@LightnessRacesinOrbit Я не понимаю вашей точки зрения. Если вы удаляете глобальную переменную, вы удаляете усложняющий фактор в этом сейчас, произвольные функции больше не могут изменять состояние программы, в различных точках выполнения - таким образом изменяя выполнение таким образом, который в противном случае незаметен для других функций, полагающихся на эту переменную. Вам больше не нужно отслеживать: «Изменилось ли состояние f2()
, поэтому теперь f3()
может сделать что-то неожиданное?» Теперь функции могут работать независимо от состояния внешней программы.
@avgvstvs: если вы просто удалите глобальную переменную, ваша программа должна иметь совершенно другую семантику, чем исходная, поэтому ваше аналогичное сравнение количества путей кода немедленно становится недействительным. Это так просто.
@LightnessRacesinOrbit да, я выступаю за то, чтобы вы переписывали свои программы, чтобы избежать глобальных переменных, и я не согласен с тем, что функциональный подход к программированию столь же сложен, особенно с учетом анализа выше, где я демонстрирую, что вы можете уменьшить сложность.
Вся моя задача заключалась в том, чтобы продемонстрировать, что глобальные переменные вносят ненужную сложность, и этот анализ все еще актуален.
@avgvstvs Я согласен с точкой зрения Lightness. Возможные пути кода определяются фактическим написанным кодом. Итак, если какая-либо из функций действительно взаимодействовала с глобальными переменными, то для получения эквивалентной программы без нее вам нужно было бы добавить общий параметр, который будет передаваться этим функциям, чтобы сохранить семантику, что приведет к как можно большему количеству возможных пути кода.
Мне бы очень, очень хотелось увидеть дизайн, в котором, скажем, событийно-управляемая система с несколькими точками входа (скажем, веб-сервис) может быть разработана без глобального состояния, но это не сводится к передаче тонны переменных или массивные ссылки на данные (что вряд ли ароматный дизайн). Если только это не просто абстракция над базой данных (которая в таком случае является вашим глобальным состоянием / SSoT).
@avgvstvs Может быть, вы пытаетесь подчеркнуть важность ограничения объема доступа к данным, когда это имеет смысл. Только сравнивая это со сложностью (с точки зрения путей кода), вы здесь сталкиваетесь с техническим сопротивлением и сопротивлением людей.
Передача общего параметра всем задействованным функциям по-прежнему включает функционально глобальную переменную. Я бы предположил, что вы должен изменяете семантику программы, чтобы удалить глобальное состояние. Тем не менее, я не думаю, что это обычно снижает сложность (как раз наоборот: причина, по которой начинающие программисты используют глобальные переменные, заключается в том, что их очень просто рассуждать, запрещая одновременный доступ).
Моя основная программа (main.py
) вызывала example.py
, устанавливала глобальную переменную и возвращала. Когда я вспоминаю, что в программе отображается уже установленная глобальная переменная example.py
вместо ее начального значения, это нормальный случай?
одно из значительных преимуществ использования global - это сокращение большого количества параметров функции, что делает ваш код аккуратным.
Честно говоря, иногда я удивляюсь, почему вы просто не можете набрать: def test(): global.myvariable = 6 return
Необходимость набирать global myvariable
, а затем myvariable = 6
- это головная боль, imho - особенно когда вы делаете это со многими-многими переменными в процессе.
Если вы хотите обратиться к глобальной переменной в функции, вы можете использовать ключевое слово Глобальный, чтобы объявить, какие переменные являются глобальными. Вам не нужно использовать его во всех случаях (как кто-то здесь неправильно утверждает) - если имя, указанное в выражении, не может быть найдено в локальной области или областях в функциях, в которых эта функция определена, оно ищется среди глобальных переменные.
Однако, если вы назначаете новую переменную, не объявленную в функции как глобальную, она неявно объявляется как локальная и может затмить любую существующую глобальную переменную с тем же именем.
Кроме того, глобальные переменные полезны, в отличие от некоторых фанатиков ООП, которые утверждают обратное - особенно для небольших скриптов, где ООП является излишним.
Абсолютно повторно. фанатики. Большинство пользователей Python используют его для написания сценариев и создания небольших функций для выделения небольших фрагментов кода.
Если я правильно понимаю вашу ситуацию, то, что вы видите, является результатом того, как Python обрабатывает локальные (функции) и глобальные (модули) пространства имен.
Допустим, у вас есть такой модуль:
# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
Вы могли ожидать, что это напечатает 42, но вместо этого будет напечатано 5. Как уже упоминалось, если вы добавите объявление «global
» к func1()
, то func2()
напечатает 42.
def func1():
global myGlobal
myGlobal = 42
Здесь происходит то, что Python предполагает, что любое имя назначен в любом месте функции является локальным для этой функции, если явно не указано иное. Если это только чтение от имени, и имя не существует локально, он попытается найти имя во всех содержащих его областях (например, в глобальной области видимости модуля).
Поэтому, когда вы назначаете 42 имени myGlobal
, Python создает локальную переменную, которая затеняет глобальную переменную с тем же именем. Этот локальный объект выходит за пределы области видимости и является сборщик мусора, когда возвращается func1()
; Между тем, func2()
никогда не видит ничего, кроме (неизмененного) глобального имени. Обратите внимание, что это решение о пространстве имен происходит во время компиляции, а не во время выполнения - если бы вы прочитали значение myGlobal
внутри func1()
, прежде чем назначать ему, вы бы получили UnboundLocalError
, потому что Python уже решил, что он должен быть локальным. переменная, но с ней еще не было связано никакого значения. Но с помощью оператора «global
» вы говорите Python, что он должен искать имя в другом месте, а не назначать ему локально.
(Я считаю, что это поведение возникло в основном из-за оптимизации локальных пространств имен - без этого поведения виртуальной машине Python необходимо было бы выполнять как минимум три поиска имени каждый раз, когда новое имя назначается внутри функции (чтобы гарантировать, что имя не t уже существует на уровне модуля / встроенного модуля), что значительно замедлит очень распространенную операцию.)
Вы упомянули, что решение о пространстве имен происходит в время компиляции, я не думаю, что это правда. из того, что я узнал о компиляции python проверяет только синтаксическую ошибку, а не ошибку имени, попробуйте этот пример def A (): x + = 1, если вы его не запустите, он будет не давать UnboundLocalError, пожалуйста, проверьте, спасибо
Обычно для глобальных переменных, таких как MyGlobal = 5
, используется заглавная буква.
@watashiSHUN: решение о пространстве имен делает происходит во время компиляции. Решение о том, что x
является локальным, отличается от проверки во время выполнения, было ли локальное имя привязано к значению до его использования в первый раз.
@Vassilis: Это обычные буквы все в верхнем регистре: MY_GLOBAL = 5
. См. Руководство по стилю кода Python.
Фактически вы не сохраняете глобальное значение в локальной переменной, а просто создаете локальную ссылку на тот же объект, на который ссылается ваша исходная глобальная ссылка. Помните, что почти все в Python - это имя, относящееся к объекту, и при обычной работе ничего не копируется.
Если вам не нужно было явно указывать, когда идентификатор должен ссылаться на предопределенную глобальную переменную, тогда вам, вероятно, придется явно указать, когда идентификатор является новой локальной переменной (например, с помощью чего-то вроде команды 'var' видно в JavaScript). Поскольку локальные переменные встречаются чаще, чем глобальные, в любой серьезной и нетривиальной системе, система Python в большинстве случаев имеет больше смысла.
У вас мог есть язык, который пытается угадать, используя глобальную переменную, если она существует, или создавая локальную переменную, если нет. Однако это было бы очень чревато ошибками. Например, импорт другого модуля может непреднамеренно ввести глобальную переменную с этим именем, изменив поведение вашей программы.
Python использует простую эвристику, чтобы решить, из какой области следует загружать переменную, между локальной и глобальной. Если имя переменной появляется слева от присвоения, но не объявлено глобальным, предполагается, что оно является локальным. Если он не отображается в левой части присвоения, предполагается, что он является глобальным.
>>> import dis
>>> def foo():
... global bar
... baz = 5
... print bar
... print baz
... print quux
...
>>> dis.disassemble(foo.func_code)
3 0 LOAD_CONST 1 (5)
3 STORE_FAST 0 (baz)
4 6 LOAD_GLOBAL 0 (bar)
9 PRINT_ITEM
10 PRINT_NEWLINE
5 11 LOAD_FAST 0 (baz)
14 PRINT_ITEM
15 PRINT_NEWLINE
6 16 LOAD_GLOBAL 1 (quux)
19 PRINT_ITEM
20 PRINT_NEWLINE
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
>>>
Посмотрите, как baz, который появляется слева от присваивания в foo()
, является единственной переменной LOAD_FAST
.
Эвристика ищет обязательные операции. Присвоение - это одна такая операция, импорт - другая. Но цель петли for
и имя после as
в операторах with
и except
также связаны с.
@MartijnPieters Для имени после as
в предложении except
для меня это не было очевидным. Но он автоматически удаляется для экономии памяти.
@Robert: не для экономии памяти, а во избежание создания циклической ссылки, которая может привести к утечке памяти. Это потому, что исключение ссылается на трассировку, а трассировка ссылается на каждое локальное и глобальное пространство имен по всему стеку вызовов, включая цель as ...
в обработчике исключений.
При параллельном выполнении глобальные переменные могут привести к неожиданным результатам, если вы не понимаете, что происходит. Вот пример использования глобальной переменной в многопроцессорной обработке. Мы ясно видим, что каждый процесс работает со своей собственной копией переменной:
import multiprocessing
import os
import random
import sys
import time
def worker(new_value):
old_value = get_value()
set_value(random.randint(1, 99))
print('pid=[{pid}] '
'old_value=[{old_value:2}] '
'new_value=[{new_value:2}] '
'get_value=[{get_value:2}]'.format(
pid=str(os.getpid()),
old_value=old_value,
new_value=new_value,
get_value=get_value()))
def get_value():
global global_variable
return global_variable
def set_value(new_value):
global global_variable
global_variable = new_value
global_variable = -1
print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after set_value(), get_value() = [%s]' % get_value())
processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))
Выход:
before set_value(), get_value() = [-1]
after set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]
Оказывается, ответ всегда прост.
Вот небольшой пример модуля с простым способом показать его в определении main
:
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
Вот как это показать в определении main
:
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __name__ == '__main__':
main()
Этот простой код работает именно так, и он будет выполняться. Я надеюсь, что это помогает.
спасибо, я новичок в python, но немного знаю java. то, что вы сказали, сработало для меня. и запись global a <ENTER> внутри класса ... кажется мне более понятной, чем внутри функции, записывающей 'global a' .. Я заметил, что вы не можете сказать global a = 4
Это, наверное, самый простой, но очень полезный для меня трюк с питоном. Я называю этот модуль global_vars
и инициализирую данные в init_global_vars
, которые вызываются в сценарии запуска. Затем я просто создаю метод доступа для каждой определенной глобальной переменной. Надеюсь, я смогу проголосовать за это несколько раз! Спасибо, Питер!
Что, если существует много глобальных переменных, и я не хочу перечислять их одну за другой после глобального оператора?
В дополнение к уже существующим ответам и, чтобы сделать это более запутанным:
In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a new value anywhere within the function’s body, it’s assumed to be a local. If a variable is ever assigned a new value inside the function, the variable is implicitly local, and you need to explicitly declare it as ‘global’.
Though a bit surprising at first, a moment’s consideration explains this. On one hand, requiring global for assigned variables provides a bar against unintended side-effects. On the other hand, if global was required for all global references, you’d be using global all the time. You’d have to declare as global every reference to a built-in function or to a component of an imported module. This clutter would defeat the usefulness of the global declaration for identifying side-effects.
Источник: Каковы правила для локальных и глобальных переменных в Python?.
Вы говорите, что нужно использовать такой метод:
globvar = 5
def f():
var = globvar
print(var)
f() # Prints 5
Но лучше использовать глобальную переменную следующим образом:
globvar = 5
def f():
global globvar
print(globvar)
f() #prints 5
Оба дают одинаковый результат.
Этот второй пример дает мне «NameError: имя 'globvar' не определено» в Python3.7
Pim: теперь должно работать, исправлена опечатка: s / globavar / globvar /
Вам нужно ссылаться на глобальную переменную в каждой функции, которую вы хотите использовать.
Следующим образом:
var = "test"
def printGlobalText():
global var #wWe are telling to explicitly use the global version
var = "global from printGlobalText fun."
print "var from printGlobalText: " + var
def printLocalText():
#We are NOT telling to explicitly use the global version, so we are creating a local variable
var = "local version from printLocalText fun"
print "var from printLocalText: " + var
printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""
"в каждой функции, которую вы хотите использовать" немного неверно, должно быть ближе к: "в каждой функции, где вы хотите Обновить"
Попробуй это:
def x1():
global x
x += 1
print('x1: ', x)
def x2():
global x
x = x+1
print('x2: ', x)
x = 5
print('x: ', x)
x1()
x2()
# Output:
# x: 5
# x1: 6
# x2: 7
Поздравляю! Наконец-то кто-то понял самый важный момент использования global
. А именно использование переменной в функции, которая была определена после самой функцией.
После и в качестве дополнения используйте файл, содержащий все глобальные переменные, все объявленные локально, а затем import as
:
Файл initval.py:
Stocksin = 300
Prices = []
Файл getstocks.py:
import initval as iv
def getmystocks():
iv.Stocksin = getstockcount()
def getmycharts():
for ic in range(iv.Stocksin):
В чем преимущество переноса глобальных переменных в другой файл? Просто сгруппировать глобальные переменные в крошечный файл? А зачем использовать инструкцию import ... as ...
? Почему не только import ...
?
Ах ... Я наконец понял преимущество: нет необходимости использовать ключевое слово global
:-) => +1 :-) Пожалуйста, отредактируйте свой ответ, чтобы прояснить эти допросы, которые могут быть у других людей. Ваше здоровье
If I create a global variable in one function, how can I use that variable in another function?
Мы можем создать глобал с помощью следующей функции:
def create_global_variable():
global global_variable # must declare it to be a global first
# modifications are thus reflected on the module's global scope
global_variable = 'Foo'
Написание функции фактически не запускает ее код. Итак, мы вызываем функцию create_global_variable
:
>>> create_global_variable()
Вы можете просто использовать его, если не ожидаете изменить объект, на который он указывает:
Например,
def use_global_variable():
return global_variable + '!!!'
и теперь мы можем использовать глобальную переменную:
>>> use_global_variable()
'Foo!!!'
Чтобы указать глобальную переменную на другой объект, вам необходимо снова использовать ключевое слово global:
def change_global_variable():
global global_variable
global_variable = 'Bar'
Обратите внимание, что после написания этой функции код, фактически меняющий ее, все еще не запускается:
>>> use_global_variable()
'Foo!!!'
Итак, после вызова функции:
>>> change_global_variable()
мы видим, что глобальная переменная была изменена. Имя global_variable
теперь указывает на 'Bar'
:
>>> use_global_variable()
'Bar!!!'
Обратите внимание, что «глобальный» в Python не является по-настоящему глобальным - он глобален только на уровне модуля. Таким образом, он доступен только функциям, написанным в модулях, в которых он является глобальным. Функции запоминают модуль, в котором они написаны, поэтому при экспорте в другие модули они по-прежнему ищут глобальные переменные в модуле, в котором они были созданы.
Если вы создадите локальную переменную с тем же именем, она затмит глобальную переменную:
def use_local_with_same_name_as_global():
# bad name for a local variable, though.
global_variable = 'Baz'
return global_variable + '!!!'
>>> use_local_with_same_name_as_global()
'Baz!!!'
Но использование этой неверно названной локальной переменной не меняет глобальную переменную:
>>> use_global_variable()
'Bar!!!'
Обратите внимание, что вам следует избегать использования локальных переменных с теми же именами, что и глобальные, если вы точно не знаете, что делаете, и у вас есть очень веская причина для этого. С такой причиной еще не сталкивался.
Следующий за комментарием спрашивает:
what to do if I want to create a global variable inside a function inside a class and want to use that variable inside another function inside another class?
Здесь я демонстрирую, что мы получаем то же поведение в методах, что и в обычных функциях:
class Foo:
def foo(self):
global global_variable
global_variable = 'Foo'
class Bar:
def bar(self):
return global_variable + '!!!'
Foo().foo()
И сейчас:
>>> Bar().bar()
'Foo!!!'
Но я бы посоветовал вместо использования глобальных переменных использовать атрибуты класса, чтобы не загромождать пространство имен модуля. Также обратите внимание, что мы не используем здесь аргументы self
- это могут быть методы класса (удобно, если изменить атрибут класса из обычного аргумента cls
) или статические методы (без self
или cls
).
Круто, но что делать, если я хочу создать глобальную переменную внутри функции внутри класса и хочу использовать эту переменную внутри другой функции внутри другого класса? Вроде застрял здесь
@anonmanx Я не знаю, почему вы застряли, это то же поведение в методе, что и в обычной функции. Но я дополню свой ответ вашим замечанием и демонстрационным кодом, хорошо?
хорошо, понял. Поэтому мне придется явно вызвать эту функцию для использования этой глобальной переменной.
Запись в явные элементы глобального массива, по-видимому, не требует глобального объявления, хотя запись в него «оптом» имеет это требование:
import numpy as np
hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])
def func1():
global hostValue # mandatory, else local.
hostValue = 2.0
def func2():
global hostValue # mandatory, else UnboundLocalError.
hostValue += 1.0
def func3():
global hostArray # mandatory, else local.
hostArray = np.array([14., 15.])
def func4(): # no need for globals
hostArray[0] = 123.4
def func5(): # no need for globals
hostArray[1] += 1.0
def func6(): # no need for globals
hostMatrix[1][1] = 12.
def func7(): # no need for globals
hostMatrix[0][0] += 0.33
func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix
Ссылка на пространство имен класса, в котором вы хотите, чтобы изменение отображалось.
В этом примере бегун использует Максимум из файла config. Я хочу, чтобы мой тест изменил значение Максимум, когда его использует бегун.
основной / config.py
max = 15000
основной / runner.py
from main import config
def check_threads():
return max < thread_count
тесты / runner_test.py
from main import runner # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
def test_threads(self):
runner.max = 0 # <----- 2. set global
check_threads()
Я добавляю это, поскольку не видел этого ни в одном из других ответов, и это может быть полезно для кого-то, кто борется с чем-то похожим. Функция globals()
возвращает изменяемый глобальный словарь символов, в котором вы можете «волшебным образом» сделать данные доступными для остальной части вашего кода.
Например:
from pickle import load
def loaditem(name):
with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
globals()[name] = load(openfile)
return True
а также
from pickle import dump
def dumpfile(name):
with open(name+".dat", "wb") as outfile:
dump(globals()[name], outfile)
return True
Просто позволит вам выгружать / загружать переменные из и в глобальное пространство имен. Супер удобно, без суеты. Уверен, что это только Python 3.
globals()
всегда возвращает глобальные переменные, доступные в локальном контексте, поэтому мутация здесь может не отражаться в другом модуле.
Глобалы в связи с многопроцессорностью на разных платформах / средах поскольку Windows / Mac OS с одной стороны и Linux - с другой, доставляют много хлопот.
Я покажу вам это на простом примере, указав на проблему, с которой я столкнулся некоторое время назад.
Если вы хотите понять, почему в Windows / MacO и Linux все по-другому, вы нужно знать, что механизм по умолчанию для запуска нового процесса на ...
Они разные в распределении памяти и инициализации ... (но я не буду вдаваться в подробности. здесь).
Давайте посмотрим на проблему / пример ...
import multiprocessing
counter = 0
def do(task_id):
global counter
counter +=1
print(f'task {task_id}: counter = {counter}')
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
task_ids = list(range(4))
pool.map(do, task_ids)
Если вы запустите это в Windows (и, я полагаю, в MacOS тоже), вы получите следующий результат ...
task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4
Если вы запустите это в Linux, вы получите следующее.
task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1
Есть 2 способа объявить переменную глобальной:
1. назначить переменную внутри функций и использовать глобальную строку
def declare_a_global_variable():
global global_variable_1
global_variable_1 = 1
# Note to use the function to global variables
declare_a_global_variable()
2. назначить переменную вне функций:
global_variable_2 = 2
Теперь мы можем использовать эти объявленные глобальные переменные в других функциях:
def declare_a_global_variable():
global global_variable_1
global_variable_1 = 1
# Note to use the function to global variables
declare_a_global_variable()
global_variable_2 = 2
def print_variables():
print(global_variable_1)
print(global_variable_2)
print_variables() # prints 1 & 2
Примечание 1:
Если вы хотите изменить глобальную переменную внутри другой функции, такой как update_variables()
, вы должны использовать глобальную строку в этой функции перед назначением переменной:
global_variable_1 = 1
global_variable_2 = 2
def update_variables():
global global_variable_1
global_variable_1 = 11
global_variable_2 = 12 # will update just locally for this function
update_variables()
print(global_variable_1) # prints 11
print(global_variable_2) # prints 2
Заметка 2:
Существует исключение для примечания 1 для переменных списка и словаря без использования глобальной строки внутри функции:
# declaring some global variables
variable = 'peter'
list_variable_1 = ['a','b']
list_variable_2 = ['c','d']
def update_global_variables():
"""without using global line"""
variable = 'PETER' # won't update in global scope
list_variable_1 = ['A','B'] # won't update in global scope
list_variable_2[0] = 'C' # updated in global scope surprisingly this way
list_variable_2[1] = 'D' # updated in global scope surprisingly this way
update_global_variables()
print('variable is: %s'%variable) # prints peter
print('list_variable_1 is: %s'%list_variable_1) # prints ['a', 'b']
print('list_variable_2 is: %s'%list_variable_2) # prints ['C', 'D']
по какой-то причине мне не нравится
config.x
, могу ли я от него избавиться? Я пришел сx = lambda: config.x
, а затем у меня есть значение новый вx()
. по какой-то причине наличиеa = config.x
для меня не помогает.