Klassen nach Variablen durchsuchen

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
Frostie
User
Beiträge: 15
Registriert: Freitag 14. April 2017, 18:16

Hallo!

Ich habe ein kleines Programm in dem sich mehrere Klassen (auch mit mehreren Unterklassen) mit vielen Variablen (Dictionarys) befinden.

Mein Ziel ist es über Input() einen Namen einzugeben und Python dann alle Klassen durchsucht und schaut ob ein Dictionary diesen Key enthält. Was ich dann brauche ist der Pfad zu diesem Key (also Klasse.Unterklasse.Dictionary...). Am besten in einer Liste falls der Key mehrfach vorhanden ist.

Ein kleines Beispiel:

Code: Alles auswählen

class hallo:
    class test:
        var = {"name": "Frostie", "Lieblingsessen": "Nutella"}
        lalala = {"bahnhof": "test", "nix": "nix"}
    class bahnhof:
        a = {"bowling": "alsdkj"}

class bye:
    f = {"h": "j", "lll": "bbb"}
    class unterklasse:
        class nocheineunterklasse:
            var = {"test": "tach"}
            #Hier sollte "test" gefunden werden

i = input()

#Und hier eine Funktion
durchsuche_klassen_und_variablen_nach_key("test")

#Output: bye.unterklasse.nocheineunterklasse.var
Nach nämlich gefühlt tausenden Versuchen habe ich immer noch nichts hinbekommen ich komme einfach nicht weiter :(

Würde mich auf eure Hilfe freuen!

Mit freundlichen Grüße, Frostie
Zuletzt geändert von Anonymous am Sonntag 23. Juli 2017, 12:23, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Solche Klassenhierarchien sind zwar möglich, aber eigentlich unüblich. Statt Klassen als Datenstrukturen (womöglich auch noch veränderbar) zu missbrauchen solltest du einfach eine Datenstruktur direkt aufbauen. In deinem Fall ein großes Wörterbuch. Kleine hast du ja schon verteilt.

Und dann wird deine Aufgabe ein simples rekursives suchen.
BlackJack

@Frostie: Ich würde das ja noch etwas deutlicher formulieren: Das ist absolut unüblich, habe ich so noch nie gesehen und Du hast da auch nur formal gesehen Klassen. Das ist ein totaler Missbrauch von ``class``. Klassen beschreiben eine Klasse von Objekten und dienen als Bauplan für konkrete Exemplare in denen Daten und Funktionen zu Objekten zusammengefasst werden. Nichts davon macht Dein eigenartiges Konstrukt.
Frostie
User
Beiträge: 15
Registriert: Freitag 14. April 2017, 18:16

Okay danke Leute dann bau ich das mal um
BlackJack

Nicht nachmachen! :-D

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function
import inspect


class hallo:
    class test:
        var = {'name': 'Frostie', 'Lieblingsessen': 'Nutella'}
        lalala = {'bahnhof': 'test', 'nix': 'nix'}
    class bahnhof:
        a = {'bowling': 'alsdkj'}
 

class bye:
    f = {'h': 'j', 'lll': 'bbb'}
    class unterklasse:
        class nocheineunterklasse:
            var = {'test': 'tach'}
     

def is_dictionary(obj):
    return isinstance(obj, dict)


def durchsuche_klasse_und_variablen_nach_key(class_, key, path=None):
    if path is None:
        path = list()
    path += [class_.__name__]
    
    for name, mapping in inspect.getmembers(class_, is_dictionary):
        if key in mapping:
            path.append(name)
            return '.'.join(path)

    for _, nested_class in inspect.getmembers(class_, inspect.isclass):
        result = durchsuche_klasse_und_variablen_nach_key(
            nested_class, key, path
        )
        if result is not None:
            return result

    return None


def durchsuche_klassen_und_variablen_nach_key(key):
    module = __import__(__name__)
    for _, class_ in inspect.getmembers(module, inspect.isclass):
        result = durchsuche_klasse_und_variablen_nach_key(class_, key)
        if result:
            return result
    raise KeyError('{0!r} not found'.format(key))


def main():
    # Output: bye.unterklasse.nocheineunterklasse.var
    print(durchsuche_klassen_und_variablen_nach_key('test'))
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

BlackJack hat geschrieben:Nicht nachmachen!
Wieso? Läuft doch! :)

Jedenfalls mit Python 2. Python 3 wirft einen RecursionError.
Bin da jetzt nicht eingestiegen, vermute aber, dass es an inspect.getmembers() liegt.

EDIT: funktioniert nur mit old style classes.
BlackJack

Also bei mir funktioniert es auch mit Python 3. Aber wenn ich in Python 2 von `object` erbe, dann gibt es tatsächlich eine ”Endlosrekursion” weil die Klassen als Attribute `__base__` haben und das hat `__class__` als Attribut was wiederum `__base__` als Attribut hat, was wiederum `__class__` als Attribut hat, …

Dagegen hilft das ausfiltern von Attributen deren Name mit einem Unterstrich beginnen:

Code: Alles auswählen

def durchsuche_klasse_und_variablen_nach_key(class_, key, path=None):
    if path is None:
        path = list()
    path += [class_.__name__]
   
    for name, mapping in inspect.getmembers(class_, is_dictionary):
        if key in mapping:
            path.append(name)
            return '.'.join(path)
 
    for name, nested_class in inspect.getmembers(class_, inspect.isclass):
        if not name.startswith('_'):
            result = durchsuche_klasse_und_variablen_nach_key(
                nested_class, key, path
            )
            if result is not None:
                return result
     
    return None
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

BlackJack hat geschrieben:Also bei mir funktioniert es auch mit Python 3.
Das finde ich erstaunlich, denn wenn Klassen in Python 2 von object erben, sollten sie sich wie Python 3 Klassen verhalten — new style eben. Bei mir ist das jedenfalls so, d.h. Python 3 hat das Rekursionsproblem, solange dunder-Classes nicht gefiltert werden. Ich habe mit 2.7 und 3.6 getestet.
Antworten