Deaktiviert die globale Variablensuche in Python

8

Kurz gesagt, die Frage: Gibt es eine Möglichkeit, Python daran zu hindern, nach Variablen außerhalb des aktuellen Bereichs zu suchen?

Details:

Python sucht nach Variablendefinitionen in äußeren Bereichen, wenn sie nicht im aktuellen Bereich definiert sind. Daher kann Code wie dieser leicht brechen, wenn er beim Refactoring nicht vorsichtig ist:

%Vor%

Wenn ich die Funktionsargumente umbenannt, aber vergessen habe, sie innerhalb des Funktionskörpers umzubenennen, würde der Code immer noch laufen:

%Vor%

Ich weiß es ist eine schlechte Methode, Namen von äußeren Bereichen zu überschreiben. Es gibt jedoch einige Gründe, warum dies so gemacht wird:

  • Manchmal kann es sinnvoll sein, dieselben Namen zu haben, weil sie sich auf dasselbe beziehen.
  • Man könnte keine aussagekräftigen Variablennamen mehr haben
  • Faulheit

Gibt es eine Möglichkeit, Python daran zu hindern, nach Variablen außerhalb des aktuellen Bereichs zu suchen? (Der Zugriff auf a oder b löst im zweiten Beispiel einen Fehler aus.)

Da ich faul bin, würde ich eine Lösung bevorzugen, die ohne wiederholten Kode funktioniert:)

Wenn das Problem hinsichtlich der Python-Version mehrdeutig ist, interessiert mich hauptsächlich Python 3.3 und höher.

    
kazemakase 24.06.2015, 09:40
quelle

3 Antworten

3

Nein, Sie können Python nicht sagen, Namen im globalen Bereich nicht zu sehen.

Sie könnten any andere Klassen oder Funktionen verwenden, die im Modul definiert sind, keine Objekte, die von anderen Modulen importiert wurden, noch könnten Sie eingebaute Namen verwenden. Ihr Funktionsnamensraum wird zu einer Wüste, in der fast alles fehlt und der einzige Ausweg wäre, alles in den lokalen Namensraum zu importieren. Für jede einzelne Funktion in Ihrem Modul .

Anstatt globale Suchvorgänge zu unterbrechen, sollten Sie den globalen Namespace sauber halten. Fügen Sie keine Globals hinzu, die Sie nicht mit anderen Bereichen im Modul teilen müssen. Verwenden Sie beispielsweise eine Funktion main() , um einzukapseln, was wirklich nur Einheimische sind.

Fügen Sie auch unittesting hinzu. Refactoring ohne (auch nur wenige) Tests ist immer anfällig für Bugs.

    
Martijn Pieters 24.06.2015, 09:58
quelle
8

Ja, vielleicht nicht im Allgemeinen. Sie können es jedoch mit Funktionen tun.

Sie möchten, dass die globale Funktion der Funktion leer ist. Sie können die Globals nicht ersetzen, und Sie möchten den Inhalt nicht ändern (weil das wäre nur, um globale Variablen und Funktionen loszuwerden).

Allerdings: Sie können Funktionsobjekte in Runtime erstellen. Der Konstruktor sieht wie types.FunctionType((code, globals[, name[, argdefs[, closure]]]) aus. Dort können Sie den globalen Namespace ersetzen:

%Vor%

Sie können das natürlich aufräumen, indem Sie Ihren eigenen Dekorateur definieren:

%Vor%

Streng genommen verbieten Sie es nicht, auf globale Variablen zuzugreifen, Sie lassen die Funktion nur glauben, dass es keine Variablen im globalen Namensraum gibt. Eigentlich können Sie dies auch verwenden, um statische Variablen zu emulieren, da es, wenn es eine Variable als global deklariert und ihm zuweist, in seiner eigenen Sandbox mit globalem Namespace endet.

Wenn Sie auf einen Teil des globalen Namespace zugreifen können möchten, müssen Sie die globale Sandbox der Funktionen mit dem ausfüllen, was Sie sehen möchten.

    
skyking 25.06.2015 10:06
quelle
1

Verschieben Sie Ihre Funktion in ein anderes Modul, um die Suche nach globalen Variablen zu verhindern. Es sei denn, es prüft den Call-Stack oder importiert das Aufrufmodul explizit. Es hat keinen Zugriff auf die Globals von dem Modul, das es aufruft.

Bewegen Sie Ihren Code in der Praxis in eine main() -Funktion, um unnötige globale Variablen zu vermeiden.

Wenn Sie globale Variablen verwenden, weil mehrere Funktionen den gemeinsamen Status ändern müssen, verschieben Sie den Code in eine Klasse.

    
jfs 25.06.2015 10:00
quelle

Tags und Links