2016-08-23 2 views
-5

Hallo es Entwickler,globales Variable nicht funktioniert Python

i Code schreibt, dass die Benutzereingabe und initialisiert eine Klasse am Eingang unten wie im Beispielcode in Abhängigkeit nimmt:

class X: 
    def __init__(self): 
     return 

    def run(self): 
     print("i am X") 

def func1(cls): 
    exec("global " + cls.lower()) 
    exec(cls.lower() + " = " + cls + "()") 

def func2(mode_to_set): 
    exec(mode_to_set.lower() + ".run()") 

aber wie ich führen Sie den Code wie folgt:

ich diese Fehlermeldung erhalte:

Traceback (most recent call last): 
    File "/Users/noahchalifour/Desktop/test.py", line 16, in <module> 
    func2('X') 
    File "/Users/noahchalifour/Desktop/test.py", line 13, in func2 
    exec(mode_to_set.lower() + ".run()") 
    File "<string>", line 1, in <module> 
NameError: name 'x' is not defined 

Kann mir jemand helfen?

+2

Die Variable muss bereits im globalen Gültigkeitsbereich vorhanden sein. Auch das ist eine schreckliche Idee. Außerdem versuchen Sie, eine Instanz von "x" zu erstellen, aber Ihre Klasse heißt "X". –

+0

Warum ist es so schlimm? @MorganThrapp –

+1

Mögliches Duplikat von [Wie erstelle ich eine variable Anzahl von Variablen in Python?] (Http://stackoverflow.com/questions/1373164/how-do-i-create-a-variable-number-of-variables -in-python) –

Antwort

0

Es scheint, wie Sie func2 instantiate besser dran mit würde und führen Sie das Verfahren:

def func2(mode_to_set): 
    globals()[mode_to_set]().run() 

Auf diese Weise Sie nicht über eine ganze Reihe von undesireable cruft über in Ihrem globalen floating haben Namespace und Sie enden nicht mit einem nicht vertrauenswürdigen exec. Auch exec ing eine global Anweisung innerhalb einer Funktion funktioniert nicht (wie Sie gesehen haben) ... exec ist eine Möglichkeit, eine Zeichenfolge als Code auszuführen. Es ist nicht eine Möglichkeit, dynamisch erstellte Anweisungen in die aktuelle Funktion fallen zu lassen.

1

Eine viel bessere Möglichkeit, eine Klasse basierend auf Benutzereingaben zu instanziiert wäre eine „Fabrik Muster“ zu verwenden:

http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Factory.html

Grundsätzlich erstellen Sie eine Klasse, deren Sinn und Zweck ist, andere Klassen zu erstellen, basierend auf ein Wert. Manche Leute finden diesen Overkill, so dass Sie auch eine Funktion verwenden können, die Klassen basierend auf Eingaben erstellt.

Was auch immer Sie tun, ist die Art und Weise, wie Sie es jetzt haben, rohe, Benutzer-Eingabe-Strings mit Exec ausführen, ist eine schlechte Idee. Im besten Fall werden neue Bugs eingeführt, deren Verfolgung fast unmöglich ist, da sie nirgends aufgezeichnet werden. Worst-Case-Szenario, ein Benutzer findet irgendwie eine Möglichkeit, eine Zeichenfolge an die Funktion zu senden, haben Sie weitgehend zerstört, was auch immer Sie gehofft haben.

Grundsätzlich sollte "exec" in der Regel der letzte Ausweg sein. Es gibt normalerweise elegantere und sicherere Wege, um das Problem zu lösen.

0

Wörterbücher, Wörterbücher, Wörterbücher. Ihr Programm sollte die Kontrolle darüber behalten, welcher Code ausgeführt wird, anstatt den Benutzer dynamisch neuen Code erstellen zu lassen.

classes = {'X': X} 
instances = {} 

def func1(cls): 
    var = cls.lower() 
    instances[var] = classes[cls]() 

def func2(mode_to_set): 
    instances[mode_to_set.lower()].run() 

func1('X') 
func2('X') 

Der einzige Unterschied ist, dass Sie nicht über eine globale Variable x genannt haben; Sie haben ein globales Wörterbuch mit einem Schlüssel x, der auf Ihre Instanz verweist.

Verwandte Themen