2012-05-14 3 views
176

Ich weiß, ich sollte vermeiden, globale Variablen in erster Linie wegen Verwirrung wie diese zu verwenden, aber wenn ich sie verwenden würde, ist das folgende ein gültiger Weg, um sie zu benutzen? (Ich versuche, die globale Kopie einer Variablen in einer separaten Funktion erstellt zu nennen.)Globale Variablen der Python-Funktion?

x = somevalue 

def func_A(): 
    global x 
    # Do things to x 
    return x 

def func_B(): 
    x=func_A() 
    # Do things 
    return x 

func_A() 
func_B() 

die x Does, dass die zweite Funktion verwendet den gleichen Wert der globalen Kopie x dass func_a verwendet und modifiziert haben? Wenn die Funktionen nach der Definition aufgerufen werden, ist die Reihenfolge wichtig?

+0

Seien Sie vorsichtig, auch nicht anzunehmen, nur weil Sie in Ihrer Funktion eine Variable zugewiesen haben, die Python Referenzen vor der Zuweisung als solche behandeln wird. Bis zur ersten Zuweisung, wenn Sie x verwendet haben, wäre es nicht der globale oder der lokale. Sie werden die berüchtigte UnboundLocalError-Ausnahme in Ihrem Gesicht bekommen :) – osirisgothra

Antwort

267

Wenn Sie einfach auf eine globale Variable zugreifen möchten, verwenden Sie einfach ihren Namen. Jedoch zu Änderung seinen Wert müssen Sie das global Schlüsselwort verwenden.

z.

global someVar 
someVar = 55 

Dies würde den Wert der globalen Variable auf 55 ändern. Andernfalls würde es nur einer lokalen Variablen 55 zuweisen.

Die Reihenfolge der Funktionsdefinitionslisten spielt keine Rolle (vorausgesetzt, sie verweisen nicht aufeinander), die Reihenfolge, in der sie aufgerufen werden.

+2

In dem Code, den ich gab, ist func_B Sachen (1) zur globalen Kopie von x (wie von func_A erhalten), (2) zu einer lokalen Variable x mit der gleicher Wert des Ergebnisses von func_A oder (3) zu einer lokalen Variablen x ohne Wert und (in den Augen des Compilers) keine Beziehung zu "einem Wert" oder dem x in func_A? –

+0

'x' in' func_B' ist eine lokale Variable, die ihren Wert aus dem Rückgabewert des Aufrufs an 'func_A' bezieht - also würde ich meinen, dass es Ihre (2) – Levon

+0

ok wäre, sagen wir, x war eine zufällige Folge von Irgendeine Art, die von func_A erzeugt wurde (dh, dass func_A jedes Mal ein anderes x erzeugt hat.) Würde das Programm wie geschrieben laufen lassen func_b ein anderes x modifizieren als das, was ursprünglich beim Aufruf von func_a erzeugt wurde? Wenn ja, wie kann ich es beheben? –

0

Sie müssen die Deklaration global verwenden, wenn Sie den einer globalen Variablen zugewiesenen Wert ändern möchten.

Sie benötigen es nicht, um von einer globalen Variable zu lesen. Beachten Sie, dass das Aufrufen einer Methode für ein Objekt (selbst wenn es die Daten in diesem Objekt ändert) den Wert der Variablen, die dieses Objekt enthält, nicht ändert (keine reflektierende Magie).

+2

Diese Formulierung ist bedauerlich. In Python ist der einer Variablen zugewiesene Wert eine Referenz, also ist es technisch korrekt (und ich habe keinen Zweifel, dass du das meintest), aber viele Leser können "den Wert ändern" als "das Objekt mutieren" interpretieren, was nicht der Fall ist Der Fall - 'xs.append (xs.pop (0))' funktioniert problemlos ohne 'globale xs'. – delnan

+0

@delnan Meine Antwort ist sorgfältig formuliert, aber ich werde klären. – Marcin

12

Wie andere bemerkt haben, müssen Sie in einer Funktion eine Variable global deklarieren, wenn diese Funktion in der Lage sein soll, die globale Variable zu ändern. Wenn Sie nur darauf zugreifen möchten, brauchen Sie nicht global.

Um ein bisschen mehr darüber zu gehen, was „ändern“ bedeutet, ist: Wenn Sie der globale Name Wieder binden wollen, so dass es zu einem anderen Objekt verweist, muss der Name global in denen deklariert werden Funktion.

Viele Operationen, die (mutieren) ändern, ein Objekt nicht den globalen Namen zu einem anderen Objekt zeigen wieder binden, und so sind sie alle gültigen, ohne den Namen global in der Funktion erklärt.

d = {} 
l = [] 
o = type("object", (object,), {})() 

def valid():  # these are all valid without declaring any names global! 
    d[0] = 1  # changes what's in d, but d still points to the same object 
    d[0] += 1  # ditto 
    d.clear()  # ditto! d is now empty but it`s still the same object! 
    l.append(0) # l is still the same list but has an additional member 
    o.test = 1 # creating new attribute on o, but o is still the same object 
65

Innerhalb eines Python Umfang, jede Zuordnung zu einer Variable nicht bereits in diesem Rahmen erklärt erstellt eine neue lokale Variable es sei denn diese Variable auf eine global scoped Variable zuvor in der Funktion deklariert wird, mit dem Schlüsselwort als Verweisung global .

Blick Lassen Sie sich auf einer modifizierten Version des Pseudo-Code, um zu sehen, was passiert:

# Here, we're creating a variable 'x', in the __main__ scope. 
x = 'None!' 

def func_A(): 
    # The below declaration lets the function know that we 
    # mean the global 'x' when we refer to that variable, not 
    # any local one 

    global x 
    x = 'A' 
    return x 

def func_B(): 
    # Here, we are somewhat mislead. We're actually involving two different 
    # variables named 'x'. One is local to func_B, the other is global. 

    # By calling func_A(), we do two things: we're reassigning the value 
    # of the GLOBAL x as part of func_A, and then taking that same value 
    # since it's returned by func_A, and assigning it to a LOCAL variable 
    # named 'x'.  
    x = func_A() # look at this as: x_local = func_A() 

    # Here, we're assigning the value of 'B' to the LOCAL x. 
    x = 'B' # look at this as: x_local = 'B' 

    return x # look at this as: return x_local 

In der Tat, Sie könnten all func_B mit den Variablen umschreiben namens x_local und es wäre identisch funktionieren.

Die Reihenfolge betrifft nur die Reihenfolge, in der Ihre Funktionen Vorgänge ausführen, die den Wert des globalen x ändern. So spielt in unserem Beispiel die Reihenfolge keine Rolle, da func_Bfunc_A aufruft. In diesem Beispiel tut, um Materie:

def a(): 
    global foo 
    foo = 'A' 

def b(): 
    global foo 
    foo = 'B' 

b() 
a() 
print foo 
# prints 'A' because a() was the last function to modify 'foo'. 

Beachten Sie, dass global nur globale Objekte zu ändern, erforderlich. Sie können weiterhin innerhalb einer Funktion darauf zugreifen, ohne global zu deklarieren. So haben wir:

x = 5 

def access_only(): 
    return x 
    # This returns whatever the global value of 'x' is 

def modify(): 
    global x 
    x = 'modified' 
    return x 
    # This function makes the global 'x' equal to 'modified', and then returns that value 

def create_locally(): 
    x = 'local!' 
    return x 
    # This function creates a new local variable named 'x', and sets it as 'local', 
    # and returns that. The global 'x' is untouched. 

Beachten Sie den Unterschied zwischen create_locally und access_only-access_only ist die globale x trotz nicht Aufruf global zugreifen, und obwohl create_locally nicht global entweder verwenden ist, erstellt es eine lokale Kopie seit Es ist Zuweisung einen Wert.

Die Verwirrung hier ist, warum Sie keine globalen Variablen verwenden sollten.

+0

Ich denke nicht, dass dies in der Praxis sehr verwirrend ist, man muss nur die Scoping-Regeln von Python verstehen (http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules). – Darthfett

2

Hier ist ein Fall, der mich mit einem globalen als Standardwert eines Parameters erwischt hat.

globVar = None # initialize value of global variable 

def func(param = globVar): # use globVar as default value for param 
    print 'param =', param, 'globVar =', globVar # display values 

def test(): 
    global globVar 
    globVar = 42 # change value of global 
    func() 

test() 
========= 
output: param = None, globVar = 42 

Ich hatte erwartet, Param einen Wert von 42 zu haben. Überraschung. Python 2.7 hat den Wert von globVar beim ersten Analysieren der Funktion func ausgewertet. Das Ändern des Werts von globVar hat den Standardwert von param nicht beeinflusst. Die Evaluierung verzögerte sich wie im Folgenden, so wie ich es brauchte.

def func(param = eval('globVar')):  # this seems to work 
    print 'param =', param, 'globVar =', globVar # display values 

Oder, wenn Sie sicher sein wollen,

def func(param = None)): 
    if param == None: 
     param = globVar 
    print 'param =', param, 'globVar =', globVar # display values 
0

Sie können direkt eine globale Variable in einer Funktion zugreifen. Wenn Sie den Wert dieser globalen Variablen ändern möchten, verwenden Sie "global variable_name". Siehe das folgende Beispiel:

var = 1 
def global_var_change(): 
     global var 
     var = "value changed" 
global_var_change() #call the function for changes 
print var 

Im Allgemeinen ist dies keine gute Programmierpraxis. Durch das Brechen der Namespace-Logik kann Code schwer zu verstehen und zu debuggen sein.