Verwenden globaler Variablen in einer Funktion


3114

Wie kann ich eine globale Variable in einer Funktion erstellen oder verwenden?

Wie kann ich diese globale Variable in einer anderen Funktion verwenden, wenn ich in einer Funktion eine globale Variable erstelle? Muss ich die globale Variable in einer lokalen Variablen der Funktion speichern, auf die zugegriffen werden muss?

Antworten:


4245

Sie können eine globale Variable in anderen Funktionen verwenden, indem Sie sie wie globalin jeder ihr zugewiesenen Funktion deklarieren :

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

Ich stelle mir den Grund dafür vor, dass Python, da globale Variablen so gefährlich sind, sicherstellen möchte, dass Sie wirklich wissen, womit Sie spielen, indem Sie das globalSchlüsselwort explizit benötigen .

Weitere Antworten finden Sie, wenn Sie eine globale Variable für mehrere Module freigeben möchten.


838
Es ist extrem übertrieben, Globale als "so gefährlich" zu bezeichnen. Globals sind in jeder Sprache, die jemals existiert hat und jemals existieren wird, vollkommen in Ordnung. Sie haben ihren Platz. Was Sie hätten sagen sollen, ist, dass sie Probleme verursachen können, wenn Sie keine Ahnung haben, wie man programmiert.
Anthony

207
Ich denke, sie sind ziemlich gefährlich. In Python sind "globale" Variablen jedoch tatsächlich auf Modulebene, was viele Probleme löst.
Fábio Santos

246
Ich bin nicht der Meinung, dass Python das globalSchlüsselwort benötigt, weil Globale gefährlich sind. Dies liegt vielmehr daran, dass Sie in der Sprache keine expliziten Variablen deklarieren müssen und automatisch davon ausgehen, dass eine von Ihnen zugewiesene Variable einen Funktionsumfang hat, sofern Sie nichts anderes angeben. Das globalSchlüsselwort ist das Mittel, das bereitgestellt wird, um es anders zu sagen.
Nate CK

7
@avgvstvs: Und wenn Sie dasselbe Programm ohne Globals implementieren, haben Sie immer noch die gleiche Anzahl von Codepfaden. Das Argument, das Sie vorgebracht haben, ist kein Argument gegen Globale.
Leichtigkeitsrennen im Orbit

13
@ LightnessRacesinOrbit Ich verstehe deinen Standpunkt nicht. Wenn Sie eine globale Variable entfernen, entfernen Sie den komplizierenden Faktor, da beliebige Funktionen den Programmstatus an verschiedenen Ausführungspunkten nicht mehr ändern können. Dadurch wird die Ausführung auf eine Weise geändert, die für andere Funktionen, die auf dieser Variablen basieren, ansonsten nicht wahrnehmbar ist. Sie müssen nicht mehr f2()f3()
nachverfolgen

775

Wenn ich Ihre Situation richtig verstehe, sehen Sie, wie Python mit lokalen (Funktion) und globalen (Modul) Namespaces umgeht.

Angenommen, Sie haben ein Modul wie dieses:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

Man könnte erwarten dies 42, zu drucken , sondern druckt es 5. Wie bereits erwähnt, wenn Sie eine ‚hinzufügen global‘ Erklärung zu func1(), dann func2()wird 42 drucken.

def func1():
    global myGlobal
    myGlobal = 42

Was hier vor sich geht, ist, dass Python davon ausgeht, dass jeder Name, der irgendwo innerhalb einer Funktion zugewiesen wird, lokal für diese Funktion ist, sofern nicht ausdrücklich anders angegeben. Wenn nur von einem Namen gelesen wird und der Name lokal nicht vorhanden ist, wird versucht, den Namen in einem beliebigen Bereich nachzuschlagen (z. B. im globalen Bereich des Moduls).

Wenn Sie dem Namen 42 zuweisen myGlobal, erstellt Python daher eine lokale Variable, die die gleichnamige globale Variable schattiert. Dieser lokale Bereich ist nicht mehr gültig und wird bei der func1()Rückgabe mit Müll gesammelt . In der Zwischenzeit func2()kann nie etwas anderes als der (unveränderte) globale Name angezeigt werden. Beachten Sie, dass diese Namespace-Entscheidung zur Kompilierungszeit und nicht zur Laufzeit erfolgt. Wenn Sie den Wert von myGlobalinside lesen, func1()bevor Sie ihn zuweisen, erhalten Sie eine UnboundLocalError, da Python bereits entschieden hat, dass es sich um eine lokale Variable handeln muss hat noch keinen Wert damit verbunden. Mit der globalAnweisung ' ' teilen Sie Python jedoch mit, dass der Name an anderer Stelle gesucht werden soll, anstatt ihn lokal zuzuweisen.

(Ich glaube, dass dieses Verhalten größtenteils durch die Optimierung lokaler Namespaces entstanden ist. Ohne dieses Verhalten müsste Pythons VM jedes Mal, wenn ein neuer Name innerhalb einer Funktion zugewiesen wird, mindestens drei Namenssuchen durchführen (um sicherzustellen, dass der Name nicht vorhanden ist.) t existieren bereits auf Modul- / eingebauter Ebene), was einen sehr häufigen Vorgang erheblich verlangsamen würde.)


Sie haben erwähnt, dass die Namespace-Entscheidung zur Kompilierungszeit erfolgt. Ich glaube nicht, dass dies der Fall ist. von dem, was ich Kompilation Python lernen nur prüft , ob Fehler Syntax, nicht Name Fehler dieses Beispiel versuchen def A (): x + = 1 , wenn Sie es nicht laufen, wird es nicht UnboundLocalError geben , überprüfen Sie bitte , danke
watashiSHUN

1
Es ist üblich, einen Großbuchstaben für globale Variablen wieMyGlobal = 5
Vassilis

3
@watashiSHUN: Die Namespace-Entscheidung erfolgt zur Kompilierungszeit. Die Entscheidung, dass xlokal ist, unterscheidet sich von der Überprüfung zur Laufzeit, ob der lokale Name an einen Wert gebunden wurde, bevor er zum ersten Mal verwendet wird.
BlackJack

9
@Vassilis: Es ist üblich, alle Buchstaben in Großbuchstaben zu schreiben : MY_GLOBAL = 5. Weitere Informationen finden Sie im Style Guide für Python-Code .
BlackJack

223

Vielleicht möchten Sie den Begriff der Namespaces untersuchen . In Python ist das Modul der natürliche Ort für globale Daten:

Jedes Modul verfügt über eine eigene private Symboltabelle, die von allen im Modul definierten Funktionen als globale Symboltabelle verwendet wird. Somit kann der Autor eines Moduls globale Variablen im Modul verwenden, ohne sich über versehentliche Konflikte mit den globalen Variablen eines Benutzers Gedanken machen zu müssen. Wenn Sie jedoch wissen, was Sie tun, können Sie die globalen Variablen eines Moduls mit derselben Notation berühren, mit der auf seine Funktionen verwiesen wird modname.itemname.

Eine spezifische Verwendung von Global-in-a-Module wird hier beschrieben. Wie teile ich globale Variablen modulübergreifend? Der Vollständigkeit halber werden die Inhalte hier geteilt:

Die kanonische Möglichkeit, Informationen zwischen Modulen innerhalb eines einzelnen Programms auszutauschen, besteht darin, ein spezielles Konfigurationsmodul zu erstellen (häufig als config oder cfg bezeichnet ). Importieren Sie einfach das Konfigurationsmodul in alle Module Ihrer Anwendung. Das Modul wird dann als globaler Name verfügbar. Da es nur eine Instanz jedes Moduls gibt, werden alle am Modulobjekt vorgenommenen Änderungen überall wiedergegeben. Zum Beispiel:

Datei: config.py

x = 0   # Default value of the 'x' configuration setting

Datei: mod.py.

import config
config.x = 1

Datei: main.py.

import config
import mod
print config.x

1
aus einem Grund, den ich nicht mag, config.x kann ich es loswerden? Ich kam mit x = lambda: config.xund dann habe ich den neuen Wert in x(). Aus irgendeinem Grund a = config.xmacht es für mich nicht den Trick.
Vladosaurus

3
@vladosaurus from config import xlöst das?
Jhylands

93

Python verwendet eine einfache Heuristik, um zu entscheiden, aus welchem ​​Bereich eine Variable zwischen lokal und global geladen werden soll. Wenn ein Variablenname auf der linken Seite einer Zuweisung angezeigt wird, aber nicht als global deklariert ist, wird davon ausgegangen, dass er lokal ist. Wenn es nicht auf der linken Seite einer Zuweisung angezeigt wird, wird davon ausgegangen, dass es global ist.

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

Sehen Sie, wie baz, das auf der linken Seite einer Zuweisung in angezeigt foo()wird, die einzige LOAD_FASTVariable ist.


12
Die Heuristik sucht nach Bindungsoperationen . Die Zuweisung ist eine solche Operation, die eine andere importiert. Aber auch das Ziel einer forSchleife und der Name nach asin withund exceptAnweisungen sind gebunden.
Martijn Pieters

@MartijnPieters Für den Namen nach asin einer exceptKlausel war mir das nicht klar. Es wird jedoch automatisch gelöscht, um Speicherplatz zu sparen.
Robert

1
@Robert: Nicht um Speicherplatz zu sparen, sondern um zu vermeiden, dass ein Zirkelverweis erstellt wird, der zu Speicherlecks führen kann. Dies liegt daran, dass eine Ausnahme auf einen Traceback verweist und der Traceback auf jeden lokalen und globalen Namespace entlang des gesamten Aufrufstapels verweist, einschließlich des as ...Ziels im Ausnahmehandler.
Martijn Pieters

62

Wenn Sie in einer Funktion auf eine globale Variable verweisen möchten, können Sie mit dem Schlüsselwort global deklarieren, welche Variablen global sind. Sie müssen es nicht in allen Fällen verwenden (wie hier fälschlicherweise behauptet wird). Wenn der Name, auf den in einem Ausdruck verwiesen wird, in den Funktionen, in denen diese Funktion definiert ist, nicht im lokalen Bereich oder Bereich gefunden werden kann, wird er unter global nachgeschlagen Variablen.

Wenn Sie jedoch einer neuen Variablen zuweisen, die in der Funktion nicht als global deklariert ist, wird sie implizit als lokal deklariert und kann jede vorhandene globale Variable mit demselben Namen überschatten.

Außerdem sind globale Variablen nützlich, im Gegensatz zu einigen OOP-Eiferern, die etwas anderes behaupten - insbesondere für kleinere Skripte, bei denen OOP übertrieben ist.


Absolut re. Eiferer. Die meisten Python-Benutzer verwenden es zum Erstellen von Skripten und erstellen kleine Funktionen, um kleine Codebits zu trennen.
Paul Uszak

51

Wie kann ich diese Variable in einer anderen Funktion verwenden, wenn ich in einer Funktion eine globale Variable erstelle?

Wir können eine globale mit der folgenden Funktion erstellen:

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' 

Beim Schreiben einer Funktion wird der Code nicht ausgeführt. Also nennen wir die create_global_variableFunktion:

>>> create_global_variable()

Globale ohne Änderung verwenden

Sie können es einfach verwenden, solange Sie nicht erwarten, das Objekt zu ändern, auf das es zeigt:

Zum Beispiel,

def use_global_variable():
    return global_variable + '!!!'

und jetzt können wir die globale Variable verwenden:

>>> use_global_variable()
'Foo!!!'

Änderung der globalen Variablen innerhalb einer Funktion

Um die globale Variable auf ein anderes Objekt zu verweisen, müssen Sie das globale Schlüsselwort erneut verwenden:

def change_global_variable():
    global global_variable
    global_variable = 'Bar'

Beachten Sie, dass nach dem Schreiben dieser Funktion der tatsächlich geänderte Code immer noch nicht ausgeführt wurde:

>>> use_global_variable()
'Foo!!!'

Also nach dem Aufruf der Funktion:

>>> change_global_variable()

Wir können sehen, dass die globale Variable geändert wurde. Der global_variableName zeigt jetzt auf 'Bar':

>>> use_global_variable()
'Bar!!!'

Beachten Sie, dass "global" in Python nicht wirklich global ist - es ist nur global auf Modulebene. Es steht also nur Funktionen zur Verfügung, die in den Modulen geschrieben sind, in denen es global ist. Funktionen merken sich das Modul, in das sie geschrieben wurden. Wenn sie also in andere Module exportiert werden, suchen sie immer noch in dem Modul, in dem sie erstellt wurden, um globale Variablen zu finden.

Lokale Variablen mit demselben Namen

Wenn Sie eine lokale Variable mit demselben Namen erstellen, wird eine globale Variable überschattet:

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

Die Verwendung dieser falsch benannten lokalen Variablen ändert jedoch nichts an der globalen Variablen:

>>> use_global_variable()
'Bar!!!'

Beachten Sie, dass Sie die Verwendung lokaler Variablen mit denselben Namen wie Globals vermeiden sollten, es sei denn, Sie wissen genau, was Sie tun, und haben einen sehr guten Grund dafür. Auf einen solchen Grund bin ich noch nicht gestoßen.

Wir bekommen das gleiche Verhalten im Unterricht

Ein folgender Kommentar fragt:

Was tun, wenn ich eine globale Variable innerhalb einer Funktion innerhalb einer Klasse erstellen und diese Variable innerhalb einer anderen Funktion innerhalb einer anderen Klasse verwenden möchte?

Hier zeige ich, dass wir bei Methoden dasselbe Verhalten haben wie bei regulären Funktionen:

class Foo:
    def foo(self):
        global global_variable
        global_variable = 'Foo'

class Bar:
    def bar(self):
        return global_variable + '!!!'

Foo().foo()

Und nun:

>>> Bar().bar()
'Foo!!!'

Ich würde jedoch vorschlagen, anstelle globaler Variablen Klassenattribute zu verwenden, um eine Überlastung des Modul-Namespace zu vermeiden. Beachten Sie auch, dass wir hier keine selfArgumente verwenden - dies können Klassenmethoden (praktisch, wenn das Klassenattribut vom üblichen clsArgument mutiert wird ) oder statische Methoden (no selfoder cls) sein.


Cool, aber was tun, wenn ich eine globale Variable innerhalb einer Funktion innerhalb einer Klasse erstellen und diese Variable innerhalb einer anderen Funktion innerhalb einer anderen Klasse verwenden möchte? Ein
bisschen

2
@anonmanx Ich weiß nicht, warum du feststeckst, es ist das gleiche Verhalten in einer Methode wie in einer regulären Funktion. Aber ich werde meine Antwort mit Ihrer Bemerkung und einem Demo-Code aktualisieren, ok?
Aaron Hall

1
@anonmanx wie ist das?
Aaron Hall

Okay, verstanden. Daher muss ich diese Funktion explizit aufrufen, um diese globale Variable zu verwenden.
Anonmanx

47

Zusätzlich zu bereits vorhandenen Antworten und um dies verwirrender zu machen:

In Python sind Variablen, auf die nur innerhalb einer Funktion verwiesen wird, implizit global . Wenn einer Variablen irgendwo im Funktionskörper ein neuer Wert zugewiesen wird, wird davon ausgegangen, dass es sich um einen lokalen Wert handelt . Wenn einer Variablen jemals ein neuer Wert innerhalb der Funktion zugewiesen wird, ist die Variable implizit lokal und muss explizit als 'global' deklariert werden.

Obwohl zunächst etwas überraschend, erklärt dies eine kurze Überlegung. Einerseits bietet das Erfordernis global für zugewiesene Variablen einen Balken gegen unbeabsichtigte Nebenwirkungen. Wenn andererseits global für alle globalen Referenzen erforderlich wäre, würden Sie immer global verwenden. Sie müssten jeden Verweis auf eine integrierte Funktion oder auf eine Komponente eines importierten Moduls als global deklarieren. Diese Unordnung würde die Nützlichkeit der globalen Erklärung zur Identifizierung von Nebenwirkungen zunichte machen.

Quelle: Welche Regeln gelten für lokale und globale Variablen in Python? .


34

Bei paralleler Ausführung können globale Variablen zu unerwarteten Ergebnissen führen, wenn Sie nicht verstehen, was passiert. Hier ist ein Beispiel für die Verwendung einer globalen Variablen innerhalb der Mehrfachverarbeitung. Wir können deutlich sehen, dass jeder Prozess mit einer eigenen Kopie der Variablen arbeitet:

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

Ausgabe:

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]

25

Was Sie sagen, ist, die Methode wie folgt anzuwenden:

globvar = 5

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

f()  # Prints 5

Der bessere Weg ist jedoch, die globale Variable wie folgt zu verwenden:

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

Beide geben die gleiche Ausgabe.


25

Wie sich herausstellt, ist die Antwort immer einfach.

Hier ist ein kleines Beispielmodul mit einer einfachen Möglichkeit, es in einer mainDefinition darzustellen :

def five(enterAnumber,sumation):
    global helper
    helper  = enterAnumber + sumation

def isTheNumber():
    return helper

So zeigen Sie es in einer mainDefinition:

import TestPy

def main():
    atest  = TestPy
    atest.five(5,8)
    print(atest.isTheNumber())

if __name__ == '__main__':
    main()

Dieser einfache Code funktioniert einfach so und wird ausgeführt. Ich hoffe, es hilft.


1
danke, ich bin neu in python, kenne aber ein bisschen java. Was du gesagt hast, hat für mich funktioniert. und das Schreiben von global a <ENTER> innerhalb der Klasse .. scheint mir sinnvoller zu sein als innerhalb einer Funktion, die 'global a' schreibt .. Ich
stelle

2
Dies ist wahrscheinlich der einfachste und doch sehr nützliche Python-Trick für mich. Ich benenne dieses Modul global_varsund initialisiere die Daten init_global_vars, die im Startskript aufgerufen werden. Dann erstelle ich einfach eine Accessormethode für jede definierte globale Variable. Ich hoffe, ich kann dies mehrmals verbessern! Danke Peter!
Swdev

1
Was ist, wenn es viele, viele globale Variablen gibt und ich sie nicht nach einer globalen Anweisung einzeln auflisten muss?
jtlz2

23

Sie müssen in jeder Funktion, die Sie verwenden möchten, auf die globale Variable verweisen.

Wie folgt:

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

3
'in jeder Funktion, die Sie verwenden möchten' ist subtil falsch, sollte näher sein an: 'in jeder Funktion, in der Sie aktualisieren möchten '
spazm

21

Sie speichern das Globale nicht in einer lokalen Variablen, sondern erstellen lediglich einen lokalen Verweis auf dasselbe Objekt, auf das sich Ihr ursprünglicher globaler Verweis bezieht. Denken Sie daran, dass so ziemlich alles in Python ein Name ist, der sich auf ein Objekt bezieht, und im normalen Betrieb nichts kopiert wird.

Wenn Sie nicht explizit angeben müssen, wann ein Bezeichner auf ein vordefiniertes globales Element verweisen soll, müssen Sie vermutlich explizit angeben, wann ein Bezeichner stattdessen eine neue lokale Variable ist (z. B. mit dem Befehl 'var') in JavaScript gesehen). Da lokale Variablen in jedem ernsthaften und nicht trivialen System häufiger vorkommen als globale Variablen, ist das Python-System in den meisten Fällen sinnvoller.

Sie könnten eine Sprache haben, die versucht hat zu raten, indem sie eine globale Variable verwendet, falls vorhanden, oder eine lokale Variable erstellt, wenn dies nicht der Fall ist. Dies wäre jedoch sehr fehleranfällig. Wenn Sie beispielsweise ein anderes Modul importieren, wird möglicherweise versehentlich eine globale Variable mit diesem Namen eingeführt, wodurch sich das Verhalten Ihres Programms ändert.


17

Versuche dies:

def x1():
    global x
    x = 6

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

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


14

Verwenden Sie im Anschluss und als Add-On eine Datei, um alle global deklarierten globalen Variablen zu enthalten, und dann import as:

Datei initval.py :

Stocksin = 300
Prices = []

Datei getstocks.py :

import initval as iv

def getmystocks(): 
    iv.Stocksin = getstockcount()


def getmycharts():
    for ic in range(iv.Stocksin):

1
Was ist der Vorteil, um die globalen Variablen in eine andere Datei zu verschieben? Ist es nur, die globalen Variablen in einer winzigen Datei zusammenzufassen? Und warum die Aussage verwenden import ... as ...? Warum nicht einfach import ...?
Olibre

1
Ah ... ich habe endlich den Vorteil verstanden: Das Schlüsselwort muss nicht verwendet werden global:-) => +1 :-) Bitte bearbeiten Sie Ihre Antwort, um diese Fragen zu klären, die möglicherweise auch andere Personen haben. Prost
olibre

13

Das Schreiben in explizite Elemente eines globalen Arrays erfordert anscheinend nicht die globale Deklaration, obwohl das Schreiben in "Wholesale" diese Anforderung erfordert:

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

7

Ich füge dies hinzu, da ich es in keiner der anderen Antworten gesehen habe und es für jemanden nützlich sein könnte, der mit etwas Ähnlichem zu kämpfen hat. Die globals()Funktion gibt ein veränderbares globales Symbolwörterbuch zurück, in dem Sie "magisch" Daten für den Rest Ihres Codes verfügbar machen können. Zum Beispiel:

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

und

from pickle import dump
def dumpfile(name):
    with open(name+".dat", "wb") as outfile:
        dump(globals()[name], outfile)
    return True

Sie können nur Variablen aus und in den globalen Namespace ausgeben. Super praktisch, kein Muss, keine Aufregung. Ich bin mir ziemlich sicher, dass es nur Python 3 ist.


3
globals()Gibt immer Globals zurück, die im lokalen Kontext verfügbar sind, sodass eine Mutation hier möglicherweise nicht in einem anderen Modul angezeigt wird.
Kiran Jonnalagadda

6

Verweisen Sie auf den Klassennamensraum, in dem die Änderung angezeigt werden soll.

In diesem Beispiel verwendet Runner Max aus der Dateikonfiguration. Ich möchte, dass mein Test den Wert von max ändert, wenn der Läufer ihn verwendet.

main / config.py

max = 15000

main / running.py

from main import config
def check_threads():
    return max < thread_count 

tests / running_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()

1

Globals sind in Ordnung - außer bei Multiprocessing

Globale Funktionen im Zusammenhang mit Multiprocessing auf verschiedenen Plattformen / Umgebungen wie Windows / Mac OS einerseits und Linux andererseits sind problematisch.

Ich werde Ihnen dies anhand eines einfachen Beispiels zeigen, das auf ein Problem hinweist, auf das ich vor einiger Zeit gestoßen bin.

Wenn Sie verstehen möchten, warum die Dinge unter Windows / MacOs und Linux anders sind, müssen Sie wissen, dass der Standardmechanismus zum Starten eines neuen Prozesses auf ...

  • Windows / MacOs ist "Spawn"
  • Linux ist 'Gabel'

Sie unterscheiden sich in der Speicherzuordnung und Initialisierung ... (aber darauf gehe ich hier nicht ein).

Schauen wir uns das Problem / Beispiel an ...

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

Wenn Sie dies unter Windows ausführen (und ich nehme an, auch unter MacOS), erhalten Sie die folgende Ausgabe ...

task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4

Linux

Wenn Sie dies unter Linux ausführen, erhalten Sie stattdessen Folgendes.

task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.