Fkt mit variabler anzahl an argumente aufrufen, ohne fkt zu verändern?

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
Scholastik
User
Beiträge: 53
Registriert: Freitag 7. Juli 2017, 12:35

Hallo :)

ist es möglich, wenn ich viele Funktionen habe die ähnlich funktionieren und gleich heißen, aber manche ein-zwei parameter mehr brauchen, dass ich sie alle mit einem call aufrufen kann, ohne die funktionen selbst zu verändern (also ohne zb * oder ** in die definitionszeile der funktionen zu schreiben)?

Beispiel:

Code: Alles auswählen

class Hans:
    def machwas(self,info1):
        print(info1)
        
class Peter:
    def machwas(self,info1,info2):
        print(info1,info2)

info1,info2 = 1,2        
Leute = {"Peter":Peter(),"Hans":Hans()}
for name, klasse in Leute.items():
    klasse.machwas(info1,info2)
Ich gehe also davon aus, dass ich die Klassen bzw die Fkt machwas() nicht verändern kann. Möchte aber alle machwas Funktionen mit so wenig Zeilen wie möglich aufrufen, anstatt einzeln für Hans eines und für Peter zwei Argumente zu übergeben.
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Was spricht denn gegen *-Argumente als dynamischer Übergabeparameter in der jeweiligen Methode? Für sowas ist das doch gemacht.

Wenn die Methoden gleich heißen, und ähnlich funktionieren würde ich über Vererbung nachdenken. Ich denke es ist besser wenn man eine abstrakte Klasse hat, somit macht man den Code wartbar. Auch kannst du somit umgehen dass die Übergabeparameter dynamisch übergeben werden. IMO sollte eine Methode nur das übergeben bekommen, was sie auch wirklich benötigt.
When we say computer, we mean the electronic computer.
Scholastik
User
Beiträge: 53
Registriert: Freitag 7. Juli 2017, 12:35

Es handelt sich um ~30 skripte mit jeweils einer Klasse. Und da ich keine Lust hatte, bei jedem einzelnen Skript in jede Fkt (~10 Fkt pro skript) nun noch den * Kram einzubauen, wollte ich mich erkunden, obs eben nicht auch andersrum geht.

Aber das Stichwort vererben ist gut, ist ohnehin immer nervig bei Änderungen alle 30 Skripte anzupassen, die grob das gleiche machen (aber ab und zu halt doch unterschiedlich und mit anderen werten und teils auch anderem code)

Dh. ich erstelle ein allgemeines Skript, welches eine Klasse mit all den üblichen Funktionen enthält. Bei diesen Fkt verwende ich dann direkt (**kwargs) ?
Und wie gehts dann weiter? Diese 30 Klassen erben dann von der allgemeinen Klasse. Dennoch müssen die Fkt ja für den Anwendungsfall angepasst werden. Und das geht doch nur mit überschreiben der allgemeinen Fkt, oder nicht?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du scheinst einen etwas seltsamen Hang zur Vrkrzg zu haben....

Wenn du garantieren kannst, dass die Funktionen (mit Vokalen) immer mit der gleichen Liste an Parametern, nur manchmal halt nicht allen, aufgerufen werden koennen, dann kannst du das auch durch das Abfangen des Typfehlers(TypeError) machen. So lange die Parameter verkuerzen, bis die Funktion durchlaeuft.

Elegant und ueblich ist das allerdings nicht. Sondern eher ein Workaround fuer eine Situation, die man besser anders loesen sollte. Eine Moeglichkeit waere zB ein Dekorator an jeder Funktion, welche die Argumente entsprechend beschneided. Das kann sogar dynamisch erfolgen (nicht ueber die massen getestet):

Code: Alles auswählen

def cutoffparams(func):
        paramlength = len(inspect.getargspec(func).args)
        def wrapper(*args):
                return func(*args[:paramlength])
        return wrapper

@cutoffparams
def foo(a, b, c, d):
             ....
Scholastik
User
Beiträge: 53
Registriert: Freitag 7. Juli 2017, 12:35

Dafür dass Funktion so ein langes Wort ist, finde ich Fkt als Abkürzung jetzt nicht sonderlich verkehrt. Gibt ja auch "vllt" für vielleicht, von daher passt das ins Muster :D

Aber okay, danke für eure Ideen und scheinbar gibt es keinen sonderlich tollen Weg, ohne die Funktion selbst zu verändern, sei es durch hinzufügen von *args oder eben einem decorator.
Die Idee mit dem Typeerror würde man dann vermutlich am besten mit einer Liste und dem aufruf klasse.machwas(*infoliste) machen und bei fehlschlag die Liste um eins verkürzen. Das scheint dann wohl die einzige Lösung zu sein, die möglich wäre, wenn man die Klassen und Funktionen darin tatsächlich nicht verändern kann oder will.

Dankeschön :)

PS: Kann ich den Thread mit "solved" markieren, oder kann das nur ein Moderator? Editieren kann ich den ersten Post jedenfalls nicht mehr
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Scholastik: Dein Problem liegt wahrscheinlich an einer ganz anderen Stelle. Kannst Du mal erklären, was Du mit den Funktionen machst, und warum die überhaupt eine unterschiedliche Anzahl an Parametern haben?

Eine Funktion hat normalerweise eine feste Anzahl an Parametern, und wenn eine Schnittstelle immer gleich aufgerufen wird, dann bedeutet das ja auch, dass alle Methoden die selben Parameter haben, im Einzelfall aber ein paar davon nicht brauchen. Dann ist die Lösung, allen Methoden die selben Parameter zu geben, aber nicht mit *-Magie zu arbeiten.
Antworten