Objekt Eigenschaften iterieren

Django, Flask, Bottle, WSGI, CGI…
Antworten
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Guten Abend,

ich habe eine Klasse geschrieben die eine Liste und ein Dictionary enthält. Dieses Objekt habe ich dem Template_Renderer übergeben. Nun möchte ich die Properties des Objektes iterieren.

Leider funktioniert es nicht so einfach wie mit:

Code: Alles auswählen

{% for item in object.list %}
Leider haben die Lösungen die ich gefunden habe nichts gebracht.

Mein Ziel ist es einfach den Inhalt der Liste in HTML in einer Table auszugeben.

Gruß
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dann zeig doch mal deine Klasse.
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Ja, ich schätze da liegt das Problem. Ich bin erst vor kurzen auf Python umgestiegen und knabbern noch an der Umgewöhnung.

Die Klasse sieht so aus:

Die Klasse sieht jetzt bereits anders aus, als zu dem Zeitpunkt, als ich es gestern gepostet habe. Ich bekomm allerdings jetzt
die Fehlermeldung:

Code: Alles auswählen

HudInterface' object has no attribute '_HudInterface__products'
Ich erkenne den Fehler gerade nicht in der Syntax und warum er sagt, dass das Attribute nicht existiert. Ich dachte ich habe
diese mit self__products = [] beispielsweise initialisiert. Über die Get und Methoden arbeite ich dann mit den Eigenschaften.
Nebenbei gesagt ich möchte einen parameterlosen Konstrukt.

Code: Alles auswählen

class foo:

    def __int__(self):
        self.__products = []
        self.__matches_count = {}

    def add_product(self, value):
        self.__products.append(value)

    def add_match(self, key):
        if key not in self.__matches_count:
            self.__matches_count[key] = 1
        else:
            self.__matches_count[key] += 1

    def get_products(self):
        return self.__products

    def get_matches(self):
        return self.__matches_count

__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Gewöhn dir mal sofort ab, __ und getter zu benutzen. Das ist NICHT wofür du denkst das es ist, produziert den Fehler den du bekommst, und getter sind unnötiger Boilerplate, den man in Python nicht schreibt. Wenn ein Attribut zur öffentlichen Schnittstelle gehört, dann hat das einfach keinen unterstrich, geschweige denn zwei.

Für deinen count Mechanismus gibt es collections.Counter, oder collections.defaultdict.

Und bitte beachte PEP8 für Benamungen.

Code: Alles auswählen

from collections import Counter

class Foo:

    der __init__(self):
        self.products = []
        self.matches_count = Counter()

    def add_product(self, value):
        self.products.append(value)

    def add_match(self, key):
        self.matches_count[key] += 1
Ich finde auch die zwei Funktionalitäten in einer Klasse etwas fragwürdig. SOLID und so.

Mit dem Template hat das aber alles nicht viel zu tun. Wenn du iterieren willst über dir Produkte,musst du natürlich objekt.attribut schreiben.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Doppelte Unterstriche sind nur sehr selten sinnvoll.
In Deinem Fall brauchst Du gar keine Unterstriche, weil sowohl products als auch matches oder matches_count öffentlich sind, durch die trivialen Getter, die man in Python nicht benutzt, weil man genauso gut direkt auf die Attribute zugeifen kann.
Bleibt also

Code: Alles auswählen

class Foo:
    def __int__(self):
        self.products = []
        self.matches_count = {}

    def add_product(self, value):
        self.products.append(value)

    def add_match(self, key):
        if key not in self.matches_count:
            self.matches_count[key] = 1
        else:
            self.matches_count[key] += 1
Mit einem defaultdict, wird add_match auch noch simple:

Code: Alles auswählen

from collections import defaultdict

class Foo:
    def __int__(self):
        self.products = []
        self.matches_count = defaultdict(int)

    def add_product(self, value):
        self.products.append(value)

    def add_match(self, key):
        self.matches_count[key] += 1
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: zwei unabhängige Lösungen die im diff nur eine Zeile haben (mit dem 👁 geschätzt), hatten wir auch noch nicht so oft 😁
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Vielen Dank euch beiden :)

Bin vor kurzen erst auf Python gewechselt und die Umstellung fällt mir irgendwie schwerer als gedacht.

Code: Alles auswählen

Ich finde auch die zwei Funktionalitäten in einer Klasse etwas fragwürdig. SOLID und so. 

Mit dem Template hat das aber alles nicht viel zu tun. Wenn du iterieren willst über dir Produkte,musst du natürlich objekt.attribut schreiben.
[/quote]



Danke für den Tipp. Ich habe die Klassennamen, Properties etc abgeändert bevor ich es gepostet habe.
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Ich hab es jetzt gerade mal getestet.

Ich habe es so geschrieben wie ihr es gesagt habt. Ich hab nach wie vor den gleichen Fehler.

Das Objekt initialisiere ich wie folgt:

Code: Alles auswählen

meinObjekt = foo()
Über eine schleife füge ich der Objektliste Items hinzu:

Code: Alles auswählen

meinObjekt.add_product(object)

Es kommt nach wie vor die Meldung

Code: Alles auswählen

object has no attribute 'products '
:?:
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Bitte den gesamten Code und die komplette Fehlermeldung posten. Mit diesen Fragmenten kann man nichts anfangen.
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Code: Alles auswählen

from collections import defaultdict

class Foo:
    def __int__(self):
        self.products = []
        self.matches_count = defaultdict(int)

    def add_product(self, value):
        self.products.append(value)

    def add_match(self, key):
        self.matches_count[key] += 1



from bar import Foo


def some_method():
	meinObjekt = Foo()
	
	for product in result:
		meinObjekt.add_product(product)
	
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Manchmal muß man schon genau hinschauen. Es heißt __init__ und nicht __int__.
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Sternenregen hat geschrieben: Samstag 6. Februar 2021, 12:24

Code: Alles auswählen

from collections import defaultdict

class Foo:
    def __int__(self):
        self.products = []
        self.matches_count = defaultdict(int)

    def add_product(self, value):
        self.products.append(value)

    def add_match(self, key):
        self.matches_count[key] += 1



from bar import Foo


def some_method():
	meinObjekt = Foo()
	
	for product in result:
		meinObjekt.add_product(product)
	

Hier die Fehlermeldung:

Code: Alles auswählen

AttributeError:  'Foo' object has no attribute 'products'
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das kommt davon, wenn du Code kopierst oder irgendwie Beispiel zusammenschreibst, die nicht funktionieren. Statt echten Code und echte Fehlermeldungen zu zeigen. Wie jetzt auch, ich musste results einfügen, die Funktion (nicht Methode) aufrufen, und den sinnlosen Import entfernen. Und dann habe ich genau EINEN Buchstaben hinzugefügt, und es geht. Schau mal genau hin

Code: Alles auswählen

from collections import defaultdict

class Foo:
    def __init__(self):
        self.products = []
        self.matches_count = defaultdict(int)

    def add_product(self, value):
        self.products.append(value)

    def add_match(self, key):
        self.matches_count[key] += 1



def some_method():
	meinObjekt = Foo()
	result = [1]
	for product in result:
		meinObjekt.add_product(product)
		
some_method()
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Beruhige dich :)

Gut, das i hatte gefehlt. Das i hatte übrigends auch in meinem richtigen Code gefehlt und nicht in dem hier reingepasteten und abgeänderten Code. Ein dummer Fehler.

Der Import ist meines Erachtens keineswegs sinnlos, da ich in einer anderen Pythondatei das Objekt erstelle. Dachte das wäre anhand des Imports ersichtlich. Ich werde es beim nächsten Mal berücksichtigen und näher erläutern.
Zudem dachte ich, dass es selbsterklärend ist, dass wenn ich etwas iteriere, dass da eine entsprechende Variable dafür vorhanden sein muss.

Aber ich werde das nächste mal meinen richtigen Code posten.

Danke vielmals.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Es geht hier nicht um *den* richtigen Code, sondern um richtigen Code, der lauffähig ist, zumindest soweit, dass er den Fehler zeigt und nicht bei einem anderen Fehler hängen bleibt. Der Import ist zum Verstehen des Fehlers gar nicht nötig.
Antworten