referenced - python3 global variable




在函數中使用全局變量 (12)

如果我在一個函數中創建一個全局變量,我如何在另一個函數中使用該變量?

我們可以使用以下函數創建一個全局:

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!!!'

請注意,除非您確切知道自己在做什麼並且有充分的理由這樣做,否則應該避免使用與globals同名的局部變量。 我還沒有遇到過這樣的道理。

如何在函數中創建或使用全局變量?

如果我在一個函數中創建一個全局變量,我如何在另一個函數中使用該全局變量? 我是否需要將全局變量存儲在需要訪問的函數的局部變量中?


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        
>>> 

看看在foo()賦值左側出現的baz是唯一的LOAD_FAST變量。


你要說的是使用這樣的方法:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

但更好的方法是使用這樣的全局變量:

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

兩者都給出相同的輸出。


如果您有一個具有相同名稱的局部變量,您可能希望使用globals()函數

globals()['your_global_var'] = 42

如果要在函數中引用全局變量,可以使用global關鍵字聲明哪些變量是全局變量。 您不必在所有情況下都使用它(因為此處有人錯誤地聲稱) - 如果表達式中引用的名稱無法在定義此函數的函數的本地範圍或範圍中找到,則在全局範圍內查找變量。

但是,如果分配給函數中未聲明為全局的新變量,則它將隱式聲明為local,並且它可以掩蓋具有相同名稱的任何現有全局變量。

此外,全局變量是有用的,與一些聲稱不同的OOP狂熱者相反 - 特別是對於較小的腳本,其中OOP是過度的。


實際上,您並未將全局存儲在局部變量中,只是創建對原始全局引用所引用的同一對象的本地引用。 請記住,Python中的所有內容都是一個引用對象的名稱,並且在通常的操作中不會復制任何內容。

如果您不必明確指定標識符何時引用預定義的全局,那麼您可能必須明確指定標識符何時是新的局部變量(例如,使用類似'var'命令的內容在JavaScript中看到)。 由於局部變量在任何嚴重且非平凡的系統中比全局變量更常見,因此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]

引用要在其中顯示更改的類命名空間。

在此示例中,runner正在使用文件配置中的max 。 我希望我的測試在跑步者使用它時改變max的值。

主/ 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()

您需要在要使用的每個函數中引用全局變量。

如下:

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]
"""

我添加了這個,因為我沒有在任何其他答案中看到它,它可能對某些類似的東西掙扎有用。 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。


試試這個:

def x1():
    global x
    x = 6

def x2():
    global x
    x = x+1
    print x

x = 5
x1()
x2()  # output --> 7

除了已經存在的答案,並使這更令人困惑:

在Python中,僅在函數內引用的變量是隱式全局變量。 如果在函數體內的任何位置為變量分配了一個新值,則假定它是一個局部變量。 如果在函數內部為變量賦予了新值,則該變量隱式為局部變量,您需要將其顯式聲明為“全局”。

雖然起初有點令人驚訝,但片刻的考慮解釋了這一點。 一方面,要求全局指定變量可以防止意外的副作用。 另一方面,如果所有全局引用都需要全局,那麼您將始終使用全局。 您必須將對內置函數或導入模塊的組件的每個引用聲明為全局。 這種混亂會破壞全球聲明識別副作用的有用性。

來源: Python中的局部變量和全局變量有哪些規則?





scope