Seite 1 von 1

Summieren einer Liste in einem Dictionary

Verfasst: Freitag 7. Oktober 2022, 17:43
von sc19
Ich möchte die Punkte (points), innerhalb einer For-Schleife Summieren.
Wie man in meinem Code sehen kann, ist die Anzahl der Elemente (Einträge) in "points" unterschiedlich.
Kann mir jemand dabei helfen, das pytonisch umzusetzen?

[code
student1 = {'name': 'Hans', 'points': [285, 210, 135, 100, 300]}
student2 = {'name': 'Peter', 'points': [65, 56, 48]}

students = [student1, student2]

for stud in students:
sumpoints = stud['points'][0]+stud['points'][1]+stud['points'][2]

print(sumpoints)]
[/code]

Re: Summieren einer Liste in einem Dictionary

Verfasst: Freitag 7. Oktober 2022, 18:53
von sparrow
Ich denke, sum() wird dein Problem lösen.

Re: Summieren einer Liste in einem Dictionary

Verfasst: Freitag 7. Oktober 2022, 20:09
von __blackjack__
@sc19: Ergänzende Anmerkungen: Man nummeriert keine Namen. Die werden hier ja auch gar nicht wirklich gebraucht — man kann die `students`-Datenstruktur auch einfach komplett literal hinschreiben:

Code: Alles auswählen

    students = [
        {"name": "Hans", "points": [285, 210, 135, 100, 300]},
        {"name": "Peter", "points": [65, 56, 48]},
    ]
Namen sollte man auch nicht kryptisch abkürzen. `stud` gibt es ja tatsächlich als englisches Wort und das bedeutet nicht Student.

`sumpoints` ist zwar keine Abkürzung aber eine komische Wortschöpfung. Mal vom fehlenden Unterstrich abgesehen klingen „Summenpunkte“ irgendwie schräg. Das ist eine Punkt-Summe oder besser Gesamptpunktzahl, also in Englisch so etwas wie `total_points`.

Zwischenstand bei der Berechnung/Ausgabe:

Code: Alles auswählen

    for student in students:
        print(student["name"], sum(student["points"]))
Was jetzt noch unschön ist, sind die Wörterbücher für etwas das eigentlich Objekte sind. Wörterbücher mit einem festen Satz an Schlüsseln, sind ja keine allgemeinen Abbildungen von Schlüsseln auf Werte sondern etwas spezialisierteres, wo man nur Wörterbücher verwendet wenn die Sprache nichts besseres für Verbunddatentypen bietet. Also in Python minimal so etwas wie `collections.namedtuple()`:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import namedtuple

Student = namedtuple("Student", "name points")


def main():
    students = [
        Student("Hans", [285, 210, 135, 100, 300]),
        Student("Peter", [65, 56, 48]),
    ]
    for student in students:
        print(student.name, sum(student.points))


if __name__ == "__main__":
    main()
Wenn man Werte zu einem Objekt zusammenfasst, macht manchmal aber auch eine eigene Klasse Sinn, denn die Gesamptpunktzahl kann man auch als eine Eigenschaft von einem Studenten-Objekt auffassen, statt etwas das ausserhalb berechnet wird:

Code: Alles auswählen

#!/usr/bin/env python3


class Student:
    def __init__(self, name, points):
        self.name = name
        self.points = points

    @property
    def total_points(self):
        return sum(self.points)


def main():
    students = [
        Student("Hans", [285, 210, 135, 100, 300]),
        Student("Peter", [65, 56, 48]),
    ]
    for student in students:
        print(student.name, student.total_points)


if __name__ == "__main__":
    main()

Re: Summieren einer Liste in einem Dictionary

Verfasst: Freitag 7. Oktober 2022, 20:22
von sc19
Vielen Dank für die ausführliche Erklärung!

Re: Summieren einer Liste in einem Dictionary

Verfasst: Samstag 8. Oktober 2022, 08:09
von snafu
Übrigens, durch Vererbung kann man die eigene Klasse auch mit dem namedtuple kombinieren und sich somit die __init__()-Methode sparen:

Code: Alles auswählen

#!/usr/bin/env python3
from collections import namedtuple

class Student(namedtuple("Student", "name points")):
    @property
    def total_points(self):
        return sum(self.points)


def main():
    students = [
        Student("Hans", [285, 210, 135, 100, 300]),
        Student("Peter", [65, 56, 48]),
    ]
    for student in students:
        print(student.name, student.total_points)


if __name__ == "__main__":
    main()

Re: Summieren einer Liste in einem Dictionary

Verfasst: Samstag 8. Oktober 2022, 08:32
von __blackjack__
@snafu: Das ist IMHO nicht so gut weil damit `Student` tatsächlich ein Tupel ist, wegen der Vererbung und so Sachen wie eine Länge hat, iterierbar ist, und mit anderen Tupeln vergleichbar, sowohl normalen als auch anderen `NamedTupel`. Das hat man bei einem reinen `namedtuple()` zwar auch, aber da finde ich das wesentlich weniger überraschend.

Da würde ich dann eher auf das externe `attrs`-Package zugreifen wenn ich mir die triviale `__init__()` sparen möchte.

Code: Alles auswählen

#!/usr/bin/env python3
from attr import attrib, attrs


@attrs(frozen=True)
class Student:
    name = attrib()
    points = attrib()

    @property
    def total_points(self):
        return sum(self.points)


def main():
    students = [
        Student("Hans", [285, 210, 135, 100, 300]),
        Student("Peter", [65, 56, 48]),
    ]
    for student in students:
        print(student.name, student.total_points)


if __name__ == "__main__":
    main()