2009-08-27 9 views
2

Ich habe angefangen, über Python zu lernen und liest gerade durch ein Skript von jemand anderem geschrieben. Ich bemerkte, dass Globals im ganzen Skript verstreut sind (und ich mag es nicht) .. Abgesehen davon, ich habe auch bemerkt, dass, wenn ich Code wie dieserPython Variable Bereich

def some_function(): 
    foo.some_method() 
    # some other code 

if __name__ == '__main__' : 
    foo = Some_Object() 

    some_function() 

obwohl ich nicht passieren in foo in some_function(), aber some_function ist immer noch in der Lage, foo (??!) zu manipulieren. Ich mag das nicht, obwohl es dem Javascript-Abschluss (?) Ähnelt. Ich würde gerne wissen, ob es möglich ist, some_function() davon abzuhalten, auf foo zuzugreifen, wenn foo nicht als Funktionsargument übergeben wird? Oder das ist der bevorzugte Weg in Python ??! (Ich verwende Python 2.5 unter ubuntu hardy im Moment)

Antwort

4

Das Skript hat wirklich ernsthafte Probleme mit Stil und Organisation - zum Beispiel, wenn jemand es importiert sie müssen irgendwie göttlich die Tatsache, dass sie thescript.foo zu einer Instanz von Some_Object setzen müssen, bevor some_function Aufruf ... yeurgh! -)

Es ist bedauerlich, dass Sie Python aus einem schlecht geschriebenen Skript lernen müssen, aber ich bin mir nicht sicher, ob ich Ihre Frage verstehe. Der Variablenbereich in Python ist Locals (einschließlich Argumente), Nonlocal (d. H. Locals von umgebenden Funktionen, für verschachtelte Funktionen), Globals, Builtins.

Möchten Sie den Zugriff auf Globals beenden? some_function.func_globals ist schreibgeschützt, aber man konnte eine neue Funktion mit leeren Globals machen:

import new 
f=new.function(some_function.func_code, {}) 

jetzt f() Aufruf wird eine Ausnahme NameError: global name 'foo' is not defined gegeben. Sie können diese wieder in das Modul-Set mit dem Namen some_function, oder sogar über einen Dekorateur systematisch tun, z.B .:

def noglobal(f): 
    return new.function(f.func_code, {}) 
... 
@noglobal 
def some_function(): ... 

dies garantiert die Ausnahme passiert, wenn some_function genannt wird. Ich weiß jedoch nicht, welchen Nutzen Sie daraus ziehen sollten. Vielleicht kannst du klären ...?

+0

gerade fertig mit dem Entfernen der Globals, bin ich derzeit auf Nicht-Locals (Einheimische der umliegenden Funktionen - für verschachtelte Funktionen) Ich möchte die Menge an nicht-lokalen verwendet wahrscheinlich aufgrund einer Gewohnheit, die ich aus dem Codieren in PHP gebracht - wenn eine Variable wird nicht in eine Funktion übergeben, dann existiert die Variable nicht in der Funktion (was IMO, es ist leichter zu debuggen, wenn schlimme Dinge passieren) – Jeffrey04

+0

@ Jeffrey, ja wrt globals, aber nonlocals, besonders wenn eine Funktion gerade ist auf sie zuzugreifen und sie NICHT neu zuzuweisen (letzteres ist erst ab 2.6 eine Option mit dem 'nonlocal'-Schlüsselwort), ist eigentlich kein Problem - und ich spreche auf der Basis von jahrzehntelanger hart erkämpfter Erfahrung ;-). –

+0

@Alex danke für die Info – Jeffrey04

2

Soweit ich weiß, der einzige Weg, some_function den Zugriff auf foo zu stoppen, ist die foo Variable aus some_function ‚s Umfang zu beseitigen, möglicherweise wie:

tmp = foo 
del foo 
some_function() 
foo = tmp 

Natürlich wird dies Ihren (aktuellen) Code zum Absturz bringen, da foo nicht mehr im Umfang von some_function existiert.

In Python werden Variablen lokal gesucht, dann im Gültigkeitsbereich bis global und schließlich nach Einbauten gesucht.

Eine weitere Option könnte sein:

with some_object as foo: 
    some_function() 

Aber dann werden Sie mindestens some_object.__exit__, vielleicht some_object.__enter__ auch zu erklären haben. Das Endergebnis ist, dass Sie steuern, welche foo im Bereich von some_function ist.

Weitere Erklärung zur "mit" -Anweisung here.

+0

Das Ersetzen von Globalen mit übergebenen Argumentwerten ist immer eine Herausforderung. Es scheint, als gäbe es immer einen albernen Hinweis auf das globale Schweben. Benennen Sie daher bei der Behebung dieses globalen Chaos Ihre alten globalen Variablen um, wenn Sie Ihre Funktionen so umschreiben, dass sie Argumente anstelle von globalen Variablen verwenden. Dann brechen die Dinge aus dem richtigen Grund. –

1

In Python ist etwas wie foo kein Wert, es ist ein Name.Wenn Sie versuchen, darauf zuzugreifen, versucht Python, den damit verbundenen Wert zu finden (z. B. Dereferenzierung eines Zeigers). Dazu sucht es zuerst im lokalen Bereich (der Funktion), dann arbeitet es sich nach außen, bis es den Modulbereich (d. H. Global) erreicht, und baut es schließlich so lange ein, bis es einen passenden Namen gefunden hat.

, dass etwas wie diese Arbeit macht:

def foo(): 
    bar() 

def bar(): 
    pass 

Trotz der Tatsache, dass bar nicht existiert, wenn Sie foo definiert, wird die Funktion arbeiten, weil Sie später bar in einem Umfang definiert, die foo umschließt.

Genau das Gleiche passiert in dem Code, den Sie posten, es ist nur, dass foo die Ausgabe von Some_Object() ist, keine Funktionsdefinition.

Wie Alex sagte, die Tatsache, dass Sie können Code schreiben wie das bedeutet nicht, dass Sie sollte.

+0

das Problem ist jetzt ... Ich schaue nicht auf meinen eigenen Code – Jeffrey04