Відповіді:
Ви можете використовувати глобальну змінну в інших функціях, оголосивши її як 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
ключове слово.
Дивіться інші відповіді, якщо ви хочете поділитися глобальною змінною між модулями.
global
ключового слова в тому, що глобальні поля небезпечні. Скоріше, це тому, що мова не вимагає від вас явного декларування змінних і автоматично передбачає, що змінна, яку ви призначаєте, має область функцій, якщо ви не скажете це інше. global
Ключове слово є засобом , яке надається сказати інакше.
f2()
змінився стан, щоб тепер f3()
зробити щось несподіване? Тепер функції можуть діяти агностично до стану зовнішньої програми.
Якщо я правильно розумію вашу ситуацію, ви бачите результат того, як 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 передбачає, що будь-яке ім'я, призначене будь-де в межах функції, є локальною для цієї функції, якщо прямо не сказано інше. Якщо воно читається лише з імені, а ім’я не існує локально, воно спробує знайти ім'я в будь-яких областях, що містять область (наприклад, глобальна область застосування модуля).
myGlobal
Отже, призначаючи ім'я 42 , Python створює локальну змінну, яка затінює глобальну змінну того самого імені. Це місцеве виходить за межі та збирається сміття під час func1()
повернення; тим часом, func2()
ніколи не можна побачити нічого, крім (немодифікованого) глобального імені. Зауважте, що це рішення простору імен відбувається під час компіляції, а не під час виконання - якщо ви повинні прочитати значення myGlobal
внутрішньої частини func1()
перед тим, як призначити його, ви отримаєте UnboundLocalError
, оскільки Python вже вирішив, що він повинен бути локальною змінною, але це ще не мала з цим пов'язаного значення. Але використовуючи global
оператор ' ', ви кажете Python, що він повинен шукати інше ім'я, а не призначати його локально.
(Я вважаю, що така поведінка в основному виникла за рахунок оптимізації локальних просторів імен - без такої поведінки VM Python потрібно було б виконати щонайменше три пошукові імена щоразу, коли нове ім'я присвоюється всередині функції (для того, щоб ім'я не було ' t вже існує на рівні модуля / вбудованого), що значно сповільнить дуже поширену операцію.)
MyGlobal = 5
x
місцевого значення відрізняється від перевірки під час виконання, якщо локальне ім'я було прив'язане до значення до його першого використання.
MY_GLOBAL = 5
. Дивіться посібник зі стилів для Python Code .
Ви можете вивчити поняття просторів імен . У Python модуль є природним місцем для глобальних даних:
У кожного модуля є своя приватна таблиця символів, яка використовується як глобальна таблиця символів усіма функціями, визначеними в модулі. Таким чином, автор модуля може використовувати глобальні змінні в модулі, не турбуючись про випадкові зіткнення з глобальними змінними користувача. З іншого боку, якщо ви знаєте , що ви робите , ви можете торкнутися глобальних змінних модулем , з тими ж позначеннями , які використовуються для позначення своїх функцій
modname.itemname
.
Тут описано конкретне використання модуля global-in-a-a - Як я поділяю глобальні змінні між модулями? , а для повноти вміст поділився тут:
Канонічним способом обміну інформацією між модулями в межах однієї програми є створення спеціального модуля конфігурації (часто його називають config або cfg ). Просто імпортуйте модуль конфігурації у всі модулі вашої програми; Потім модуль стає доступним як глобальна назва. Оскільки в кожному модулі є лише один екземпляр, будь-які зміни, внесені в об'єкт модуля, відображаються всюди. Наприклад:
Файл: config.py
x = 0 # Default value of the 'x' configuration setting
Файл: mod.py
import config config.x = 1
Файл: main.py
import config import mod print config.x
config.x
можу я її позбутися? Я прийшов, x = lambda: config.x
і тоді я отримав нове значення x()
. чомусь, що a = config.x
не робить для мене хитрощів.
from config import x
вирішує це?
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
операторах також зобов'язані.
as
в except
пункті для мене це було не очевидно. Але це автоматично видаляється, щоб зберегти пам'ять.
as ...
ціль у обробнику винятків.
Якщо ви хочете посилатися на глобальну змінну у функції, ви можете використовувати ключове слово global, щоб оголосити, які змінні є глобальними. Використовувати його не потрібно в усіх випадках (як хтось тут неправильно стверджує) - якщо ім'я, на яке посилається вираз, не може бути знайдено в локальному масштабі або області дії функцій, в яких визначена ця функція, вона шукається серед глобальних змінні.
Однак якщо ви призначите нову змінну, не оголошену як глобальну у функції, вона неявно оголошується локальною, і вона може затьмарити будь-яку існуючу глобальну змінну з тим самим іменем.
Також глобальні змінні корисні, всупереч деяким завзяттям OOP, які стверджують інакше - особливо для менших сценаріїв, де OOP є надмірним.
Якщо я створюю глобальну змінну в одній функції, як я можу використовувати цю змінну в іншій функції?
Ми можемо створити глобальний за допомогою наступної функції:
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!!!'
Щоб вказати глобальну змінну на інший об'єкт, вам потрібно знову використовувати ключове слово:
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!!!'
Зауважте, що вам слід уникати використання локальних змінних з тими ж іменами, що і глобальні, якщо ви точно не знаєте, що ви робите, і у вас є дуже вагомі причини для цього. Я ще не стикався з такою причиною.
Наступний коментар запитує:
що робити, якщо я хочу створити глобальну змінну всередині функції всередині класу та хочу використовувати цю змінну всередині іншої функції всередині іншого класу?
Тут я демонструю, що ми отримуємо таку ж поведінку в методах, що і у звичайних функціях:
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
).
На додаток до вже існуючих відповідей і зробити це більш заплутаним:
У Python є змінні, на які посилається лише всередині функції неявно глобальні . Якщо змінній присвоєно нове значення в будь-якому місці в тілі функції, вона вважається локальною . Якщо змінній колись присвоюється нове значення всередині функції, змінна неявно локальна, і вам потрібно явно оголосити її як "глобальну".
Хоча спочатку трохи дивно, це пояснює момент. З одного боку, вимога глобального для призначених змінних забезпечує смугу проти непередбачуваних побічних ефектів. З іншого боку, якби глобальний був необхідний для всіх глобальних посилань, ви б використовували глобальний весь час. Вам доведеться оголосити як глобальну кожну посилання на вбудовану функцію або на компонент імпортного модуля. Ця сутичка загрожує корисності глобальної декларації для виявлення побічних ефектів.
Джерело: Які правила для локальних та глобальних змінних у Python? .
При паралельному виконанні глобальні змінні можуть спричинити несподівані результати, якщо ви не розумієте, що відбувається. Ось приклад використання глобальної змінної в рамках багатопроцесорної обробки. Ми чітко бачимо, що кожен процес працює з власною копією змінної:
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()
Цей простий код працює саме так, і він буде виконуватися. Я сподіваюся, що це допомагає.
global_vars
і ініціалізую дані в init_global_vars
, які викликаються в сценарії запуску. Потім я просто створюю метод accessor для кожного визначеного глобального var. Я сподіваюся, що зможу підтвердити це кілька разів! Дякую Петру!
Вам потрібно посилатися на глобальну змінну у кожній функції, яку ви хочете використовувати.
Так:
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]
"""
Ви насправді не зберігаєте глобальний код у локальній змінній, просто створюєте локальну посилання на той самий об’єкт, на який посилається ваша первісна глобальна посилання. Пам'ятайте, що майже все в Python - це ім'я, що посилається на об'єкт, і нічого не копіюється при звичайній роботі.
Якщо вам не потрібно було чітко вказувати, коли ідентифікатор повинен посилатися на заздалегідь визначений глобальний, ви, мабуть, повинні явно вказати, коли ідентифікатор замість цього є новою локальною змінною (наприклад, з чимось на зразок команди 'var' видно в JavaScript). Оскільки локальні змінні більш поширені, ніж глобальні змінні в будь-якій серйозній і нетривіальній системі, система Python має більш сенс у більшості випадків.
Ви можете мати мову, яка намагалася відгадати, використовуючи глобальну змінну, якщо вона існує, або створивши локальну змінну, якщо вона не була. Однак це було б дуже схильним до помилок. Наприклад, імпорт іншого модуля може ненавмисно ввести глобальну змінну за цим іменем, змінивши поведінку вашої програми.
Спробуйте це:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
Якщо у вас є локальна змінна з тим самим іменем, ви можете скористатися globals()
функцією .
globals()['your_global_var'] = 42
Після цього і як додавання використовуйте файл, щоб містити всі глобальні змінні, всі оголошені локально, а потім 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 :-) Будь ласка, відредагуйте свою відповідь, щоб уточнити ці допити, які можуть також мати інші люди. Ура
Писати в явні елементи глобального масиву, очевидно, не потрібно глобальної декларації, хоча написання до неї "оптом" має таку вимогу:
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
Я додаю це, оскільки я не бачив цього в жодній з інших відповідей, і це може бути корисним для тих, хто бореться з чимось подібним. 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()
завжди повертає глобальний доступний локальний контекст, тому мутація тут може не відображатися в іншому модулі.
Посилайтеся на простір імен класів, де потрібно відобразити зміну.
У цьому прикладі бігун використовує max з конфігурації файлу. Я хочу, щоб мій тест змінив значення max, коли бігун використовує його.
main / config.py
max = 15000
main / 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()
Глобальні мережі, пов'язані з багатопроцесорною роботою на різних платформах / оточеннях, як 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