Seite 1 von 1

Funktionen mit variabler Parameteranzahl

Verfasst: Mittwoch 8. März 2023, 17:33
von Feedback1000
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

Re: Funktionen mit variabler Parameteranzahl

Verfasst: Mittwoch 8. März 2023, 18:13
von Feedback1000
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()

Re: Funktionen mit variabler Parameteranzahl

Verfasst: Mittwoch 8. März 2023, 18:32
von pillmuncher
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]

Re: Funktionen mit variabler Parameteranzahl

Verfasst: Mittwoch 8. März 2023, 18:33
von DeaD_EyE
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()


Re: Funktionen mit variabler Parameteranzahl

Verfasst: Mittwoch 8. März 2023, 19:33
von Sirius3
@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')