Iteration

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
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Gibt es eigentlich eine Möglichkeit über ein Klassenobjekt iterieren.
zB. wenn man es als enum nutzt.

Code: Alles auswählen

class AnimalSound:
    cat = "miau"
    dog = "wuff"
Ist nur ein Beispiel :mrgreen:,
mir geht es wirklich nur darum ob es hier ein direkte Möglichkeit gibt über AnimalSound zu iterieren. Das man zB alle Attribute und/oder alle Attributwerte bekommt, ohne eine Instanz zu haben.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ja, indem du `__iter__` implementierst.
Edit: Alternativ auch `__getitem__`, mehr hier: http://docs.python.org/library/functions.html#iter
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

__iter__ nützt mir doch nur etwas bei einer Instanz, oder ?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Mir schwebte eher etwas in der Richtung vor:

Code: Alles auswählen

def iterobj(obj):
    for attr in obj.__dict__:
        if not attr.startswith("_"):
            yield attr, obj.__dict__[attr]

for animal, sound in iterobj(AnimalSound):
    print(animal, sound)
Gibt es da nicht was schöneres ?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@Xynon1: Du solltest auf jeden Fall von dem direkten Zugriff auf `__dir__` Abstand nehmen, denn das kann ein Objekt ja mittlerweile als Methode implementieren um auch die Namen von berechneten Attributen nach aussen bekannt zu machen. Mit einem Generatorausdruck wird's ein Einzeiler:

Code: Alles auswählen

def iter_attributes(obj):
    return ((n, getattr(obj, n)) for n in dir(obj) if not n.startswith('_'))
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Xynon1 hat geschrieben:__iter__ nützt mir doch nur etwas bei einer Instanz, oder ?
Achso ja .. dann helfen dir Metaklassen.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@blackjack
Ok, danke für den Hinweis, ein paar Zeichen mehr und es ist kein Einzeiler mehr :D
und du meintest sicherlich von __dict__ wegkommen und nicht von __dir__ - da warst du wohl mit den Gedanken schon einen Schritt weiter.
cofi hat geschrieben: Achso ja .. dann helfen dir Metaklassen.
Inwiefern ?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@Xynon1: Ja genau, ich meinte `__dict__`. :-)

Ich denke cofi meint wenn Du eine `Enum`-Klasse schreiben möchtest, dann hilft Dir dabei eine Metaklasse. Da gibt's auch schon fertige Implementierungen, falls Du das Rad nicht noch einmal neu erfinden möchtest.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Achso, das mir aber nicht explizit um Enums geht habe ich ja schon im ersten Post geschrieben und ja ich weiß das es dafür fertige Implementierungen gibt :wink:

Im Prinzip reicht mir mein-verbesserter/dein Code.
Hierzu hätte ich nur noch eine Style frage:
Ist es wirklich besser immer Listkompression zu nutzen, da diese auch nur bis zu einem gewissen Grad besser lesbar ist, spätestens wenn sie über die Zweite Zeile geht, finde ich diese doch sehr unübersichtlich.
Bei deinem Beispiel geht es ja noch, aber bei einem weiteren "if" sollte, man dann doch lieber die Liste -dekompremieren-, oder ?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

Die Dinger heissen "list compre*hension*". :-) Zu viel sollte man da nicht reinstecken, aber zwei Zeilen finde ich persönlich noch in Ordnung. Drei auch noch wenn ein ``if`` beteiligt ist. Dann kann man die Operation, die einzelne Elemente beschreibt; den ``for``-Ausdruck; und die Bedingung in jeweils eigene Zeilen schreiben. Hat ein bisschen was von einer SQL-Abfrage.

In meinem Beispiel war's übrigens ein Generatorausdruck und keine "list comprehension", aber das ist syntaktisch ja sehr nah beieinander.

Letztendlich ist das "lesbar" wohl auch ein wenig Gewöhnungssache.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ok, danke für die richtig Stellung :D - oder eher :idea:
BlackJack hat geschrieben:In meinem Beispiel war's übrigens ein Generatorausdruck und keine "list comprehension", aber das ist syntaktisch ja sehr nah beieinander.
Ah richtig, die Klammern :oops:
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Antworten