Funktionen mit variabler Parameteranzahl

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
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Hallo.

Heute mal ein Problem aus dem Hause Funktionen mit variabler Parameteranzahl:
Ich habe Listen mit dicts mit zumindest einem identem keys. Dieses möchte ich aus jeder Liste auslesen und in separate Variablen packen.
Die Funktion soll so gestrickt sein, dass sie unterschiedliche Anzahl an Parametern übergebenbekommen kann und dann (und das ist meine Schwierigkeit) auch dementsprechend viele Rückgabewerte haben soll.

Hier habe ich das mal versucht herzuleiten:

Code: Alles auswählen

liste_a = [
    {'name': 'Sophie', 'alter': 42, 'schuhgroesse': 42},
    {'name': 'Moritz', 'alter': 8, 'schuhgroesse': 15},
    {'name': 'Michaela', 'alter': 23, 'schuhgroesse': 500},
]
liste_b = [
    {'name': 'Anna', 'hausnummer': '42'},
    {'name': 'Julia', 'hausnummer': '42a'},
]
liste_c = [
    {'name': 'Fabian'},
    {'name': 'Hauke'},
    {'name': 'Hans'},
    {'name': 'Kristin'},
    {'name': 'Paul'},
    {'name': 'Brit'},
]


def bspfunktion(*listen):
    namen = []
    for liste in listen:
        for i in range(len(liste)):
            namen.append(liste[i]['name'])
    # print(namen)


def main():
    # namen_a, namen_b, namen_c = bspfunktion(liste_a, liste_b, liste_c)
    bspfunktion(liste_a, liste_b, liste_c)
    print('\nTest-Lauf')


if __name__ == '__main__':
    main()
In diesem Beispiel werden alle Namen in eine Liste gepackt, das will ich nicht - weis aber auch nicht wie ich es ändern kann.

Also 'name' soll aus jeder Liste ausgelesen werden und dann auch dementsprechend oft zurückgegeben werden. Also in namen_a sollen als liste alle name aus liste_a landen, alle name aus liste_b soll in names_b landen usw..

Ja. man könnte das auch mit Listcomprihention o.Ä. einfach für jede Liste machen, aber natürlich passiert innerhalb des "richtigen" Projekts innerhalb der Funktion noch deutlich mehr als dass nur ein Eintrag ausgelesen wird und dieser zurück gegeben werden soll. Mir geht es in erster Linie "nur" um die Syntax.

Ich hoffe, dass man mein Problem nachvollziehen kann und ihr mir helfen könnt.

VG
Feedback
Feedback1000
User
Beiträge: 88
Registriert: Dienstag 20. September 2022, 21:21

Habe eine Lösung gefunden, aber es wäre cool, wenn mal ein Profi drüber schuat und sagt, ob das so Sinn gibt:

Code: Alles auswählen

liste_a = [
    {'name': 'Sophie', 'alter': 42, 'schuhgroesse': 42},
    {'name': 'Moritz', 'alter': 8, 'schuhgroesse': 15},
    {'name': 'Michaela', 'alter': 23, 'schuhgroesse': 500},
]
liste_b = [
    {'name': 'Anna', 'hausnummer': '42'},
    {'name': 'Julia', 'hausnummer': '42a'},
]
liste_c = [
    {'name': 'Fabian'},
    {'name': 'Hauke'},
    {'name': 'Hans'},
    {'name': 'Kristin'},
    {'name': 'Paul'},
    {'name': 'Brit'},
]


def bspfunktion(*args):
    namen = [[] for _ in range(len(args))]
    for i, liste in enumerate(args):
        for j in range(len(liste)):
            namen[i].append(liste[j]['name'])
    return namen


def main():
    namen_a, namen_b, namen_c = bspfunktion(liste_a, liste_b, liste_c)
    print(namen_a)
    print(namen_b)
    print(namen_c)
    print('\nTest-Lauf')


if __name__ == '__main__':
    main()
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ja, das könnte man wohl so machen, aber mir wäre das zu kompliziert. Warum nicht so?

Code: Alles auswählen

def f(*args):
    return [[each['name'] for each in arg] for arg in args]
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1240
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Kann man noch kürzer machen:

Code: Alles auswählen

liste_a = [
    {"name": "Sophie", "alter": 42, "schuhgroesse": 42},
    {"name": "Moritz", "alter": 8, "schuhgroesse": 15},
    {"name": "Michaela", "alter": 23, "schuhgroesse": 500},
]
liste_b = [
    {"name": "Anna", "hausnummer": "42"},
    {"name": "Julia", "hausnummer": "42a"},
]
liste_c = [
    {"name": "Fabian"},
    {"name": "Hauke"},
    {"name": "Hans"},
    {"name": "Kristin"},
    {"name": "Paul"},
    {"name": "Brit"},
]


def bspfunktion(*args):
    for collection in args:
        yield [name for entry in collection if (name := entry.get("name"))]


def main():
    for namen in bspfunktion(liste_a, liste_b, liste_c):
        print(namen)

    print("\nTest-Lauf")


if __name__ == "__main__":
    main()

sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@Feedback1000: `bspfunktion` ist ein schlechter Funktionsname, der sollte beschreiben, was die Funktion tut, z.B. extract_names.
Man belegt keine Listen vor, sondern erzeugt sie, so wie man sie braucht.
Man benutzt keine Indizes in Listen, sondern iteriert direkt über die Elemente.

Code: Alles auswählen

def extract_names(*lists):
    all_names = []
    for items in lists:
        names = []
        for item in items:
            names.append(item['name'])
        all_names.append(names)
    return all_names
Das könnte man jetzt mit List-Comprehension kürzer schreiben:

Code: Alles auswählen

def extract_names(*lists):
    return [
        [item['name'] for item in items]
        for items in lists
    ]
Die Funktion an sich ist aber schlecht. Mit *-Argumenten sollte man sparsam umgehen, besser ist es mit Listen zu arbeiten.
Für jedes Element einer Liste etwas zu machen, dafür gibt es aber schon passende Funktionen (map), das in eine Funktion zu packen ist unnötig.

Code: Alles auswählen

def extract_names(items):
    return [item['name'] for item in items]

def main():
    namen_a, namen_b, namen_c = map(extract_names, [liste_a, liste_b, liste_c])
    print(namen_a)
    print(namen_b)
    print(namen_c)
    print('\nTest-Lauf')
Antworten