Befehl aus einem String lesen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
PhysicPat
User
Beiträge: 5
Registriert: Montag 28. Mai 2018, 20:41

Hallo,

ich bin recht neu bei Python und wollte fragen ob es möglich ist, einen Befehl aus einem String auszulesen, das heißt:

Code: Alles auswählen

problem = "wetter()"
Wobei der Befehl - wetter() - definiert wurde und unter direkter Ansprache ausgeführt wird. Da problem hier ein string ist wird der Befehl nicht ausgeführt.
Aus einem anderen Befehl erhalte ich über return den String problem.


Ich hoffe ihr versteht die Frage und könnte mir helfen.

MfG
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Du solltest dir überlegen, ob du nicht ein Mapping für deine problem-Typen implementierst, z.B. über ein Dictionary. So kannst du die Funktionen den Strings explizit zuordnen:

Code: Alles auswählen

>>> def wetter():
...     print("Wir haben schönes Wetter!")
...
>>> mapping = {"wetter()": wetter}
>>> problem = "wetter()"
>>> mapping.get(problem).__call__()
Wir haben schönes Wetter!
When we say computer, we mean the electronic computer.
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@sls: Warum rufst du `get` nicht auch mit `__call__` auf ‽ Und um konsequent zu sein, müsstest du `print` auch nur so verwenden:

Code: Alles auswählen

print.__call__("Hello World")
Dann stellt sich natürlich die Frage, warum du die `__call__`-Methode nicht mit `__call__` aufrufst:

Code: Alles auswählen

print.__call__.__call__("Hello World")
Außerdem ist ein `get` auf einem Dictionary ohne sinnvollen Defaultwert nicht sinnvoll, weil man damit den `KeyError`, den man bekommen würde, unterdrückt und einen Fehler an einer anderen Stelle bekommt, wenn man versucht, das `None` zu verwenden.

Die einfache Lösung wäre natürlich, das redundante `__call__`und das unsinnige `get` einfach wegzulassen:

Code: Alles auswählen

mapping["wetter()"]()
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

@narpfel: mir war nicht klar, dass man direkt an das dict einen Funktionsaufruf mit den Klammern starten kann, das macht die Sache ja wesentlich entspannter. Das get() ist sinnlos, was ich eigentlich wollte war das hier:

Code: Alles auswählen

mapping[problem].__call__()
Danke für den Tipp.
When we say computer, we mean the electronic computer.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Je nach Anwendungsfall kann es ja einen sinnvollen Default geben:

Code: Alles auswählen

def wetter():
    print("Wir haben schönes Wetter!")

def unknown():
    print("Befehl unbekannt!")

mapping = {"wetter()": wetter}

problem = "regen()"
mapping.get(problem, unknown)()
PhysicPat
User
Beiträge: 5
Registriert: Montag 28. Mai 2018, 20:41

Danke für die schnellen Antworten.

Eine andere Möglichkeit ein String zu "ent-Stringen" gibt es also nicht? Ohne das mapping zu verwenden.
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

PhysicPat hat geschrieben: Sonntag 3. Juni 2018, 11:02 Eine andere Möglichkeit ein String zu "ent-Stringen" gibt es also nicht? Ohne das mapping zu verwenden.
Keine, die man verwenden sollte. Das, was dir vorgeschlagen wurde, ist schon die beste Variante. Die Idee, irgendetwas "ent-stringen", d.h. Code in einer Zeichenkette interpretieren zu wollen ist zumindest in Python in der überwiegenden Anzahl aller Fälle schon vom Ansatz her falsch.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@PhysicPat: was ist das eigentliche Problem, das Du zu lösen versuchst? Vielleicht ist der String ja schon der falsche Weg.
Antworten