Typ einer Variablen bestimmen

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.
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

api hat geschrieben:Nun muss ich in Abhängigkeit des Typs des Inhaltes des Strings verschiedene Dinge tun. Also so in der Form...

wenn vom Typ 'String' dann tue ...
wenn vom Typ 'Int' dann tue ...

Code: Alles auswählen

class Visitor(object):

    def __init__(self):
        self.indent = 0

    def spaces(self):
        return ' ' * (4 * self.indent)

    def visit(self, visitable):
        getattr(self, u'visit_' + type(visitable).__name__)(visitable)

    def visit_list(self, alist):
        print self.spaces() + 'list:'
        self.indent += 1
        for each in alist:
            self.visit(each)
        self.indent -= 1

    def visit_dict(self, adict):
        print self.spaces() + 'dict:'
        self.indent += 1
        for key, value in adict.iteritems():
            self.visit_pair(key, value)
        self.indent -= 1

    def visit_pair(self, key, value):
        print self.spaces() + 'pair:', repr(key), ':', repr(value)

    def visit_int(self, anint):
        print self.spaces() + 'int:', repr(anint)

    def visit_str(self, astr):
        try:  # Obacht!
              # Das wird nicht immer funktionieren, und zudem ist es gefährlich, su.:
            item = eval(astr)
        except (NameError, SyntaxError):
            print self.spaces() + 'string:', repr(astr)
        except:
            raise
        else:
            self.visit(item)


a_list = ['auto', '17', '["eine liste", 42]', '{"TEST":40, "HAUS": 50}']
visitor = Visitor()
visitor.visit(a_list)
Ergebnis:

Code: Alles auswählen

list:
    string: 'auto'
    int: 17
    list:
        string: 'eine liste'
        int: 42
    dict:
        pair: 'TEST' : 40
        pair: 'HAUS' : 50
Für evtl. Schäden, die durch den Einsatz von eval() entstehen, lehne ich jede Verantwortung ab.

Das Problem bei der ganzen Angelegenheit ist, wie schon erwähnt wurde, dass dein Datenformat Strings enthält, die für sich selbst stehen, und solche, die für Programmcode stehen. Angenommen, du verwendest in deinem Programm eine globale Variable namens TEST, wie willst du dann entscheiden, ob mit dem String 'TEST' diese Variable gemeint ist, oder ob es sich um einen String handelt, der nur zufällig aus genau derselben Buchstabenfolge besteht wie der Variablenname? Oder, noch schlimmer, was wenn der String aus der Buchstabenfolge '__import__("subprocess").call(["rm", "-rf", "/"])' oä. besteht?
In specifications, Murphy's Law supersedes Ohm's.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

pillmuncher: Was spricht dagegen, statt eval ast.literal_eval zu verwenden?
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

derdon hat geschrieben:pillmuncher: Was spricht dagegen, statt eval ast.literal_eval zu verwenden?
Du meinst so?

Code: Alles auswählen

    def visit_str(self, astr):
        try:
            item = ast.literal_eval(astr)
        except (NameError, SyntaxError, ValueError):
            print self.spaces() + 'string:', repr(astr)
        except:
            raise
        else:
            self.visit(item)
Ja, das wäre gescheiter. Daran hatte ich gar nicht gedacht. Und gerade sehe ich, dass der Vorschlag ja schon breitestens ausgewälzt wurde. :oops:
In specifications, Murphy's Law supersedes Ohm's.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Ja, so meinte ich das.
Antworten