x parametre

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.
Sync32
User
Beiträge: 141
Registriert: Mittwoch 27. Januar 2010, 12:42

Wie baue ich eine Funktion, wo man nicht genau weiß wieviele Parameter da rein kommen?
Weils immer unterschiedlich ist, je nach dem wo man diese einsetzt.
geht sowas?
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

klar

Code: Alles auswählen

def function(p1, p2, *args, **kwargs):
    print ("Parameter 1: ", p1)
    print ("Parameter 2: ", p2)
    print ("Liste:", args)
    print ("Dictionary: ", kwargs)
Edit: Ups, die Erklärung vergessen.
p1 und p2 ist ein einfacher PArameter, wie du ihn sicher schon kennst
args erwartet eine Liste, also zB:

Code: Alles auswählen

def function(*args):
    print (args)
function(1,2,3,4,5)
und **kwargs erwartet eine zuweisung zB.

Code: Alles auswählen

def function(**kw):
    print (kw)
function(para1=1, para2=2)
Zuletzt geändert von Xynon1 am Freitag 15. Oktober 2010, 13:35, insgesamt 1-mal geändert.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Siehe auch den entsprechenden Abschnitt im Tutorial: http://docs.python.org/tutorial/control ... -functions
https://www.xing.com/go/invite/18513630.6a91d4
BlackJack

@Sync32: Wobei man die */**-"Magie" nicht benutzen sollte wenn es Alternativen gibt, zum Beispiel eine Liste als Argument statt beliebig viele Argumente.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Als gutes Anwendungsbeispiel fallen mir die div. Template-Engines und deren "render"-Funktionen ein. Da man üblicherweise nicht wissen kann, welche und wie viele Objekte an ein Template übergeben werden müssen, nutzen diese Libs diese Funktionalität.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Hyperion hat geschrieben:Als gutes Anwendungsbeispiel fallen mir die div. Template-Engines und deren "render"-Funktionen ein. Da man üblicherweise nicht wissen kann, welche und wie viele Objekte an ein Template übergeben werden müssen, nutzen diese Libs diese Funktionalität.
Ganz schlechtes Beispiel, da hat man schliesslich einen Kontext den man übergibt und da wäre es besser einfach explizit ein dict zu übergeben.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

DasIch hat geschrieben:Ganz schlechtes Beispiel, da hat man schliesslich einen Kontext den man übergibt und da wäre es besser einfach explizit ein dict zu übergeben.
Wie wäre es denn dann mit Dekoratoren?
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

/me hat geschrieben:Wie wäre es denn dann mit Dekoratoren?
Du meinst Dekoratoren die eine Funktion zurückgeben, dir die dekorierte Funktion/Klasse aufruft? Das wäre tatsächlich ein gutes Beispiel, da kommt man schliesslich nicht drum herum.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

DasIch hat geschrieben:
Hyperion hat geschrieben:Als gutes Anwendungsbeispiel fallen mir die div. Template-Engines und deren "render"-Funktionen ein. Da man üblicherweise nicht wissen kann, welche und wie viele Objekte an ein Template übergeben werden müssen, nutzen diese Libs diese Funktionalität.
Ganz schlechtes Beispiel, da hat man schliesslich einen Kontext den man übergibt und da wäre es besser einfach explizit ein dict zu übergeben.
Kannst Du das ein wenig näher ausführen? Im Moment sehe ich da nicht, worauf damit hinaus willst. Sowohl in bottle, jinja und mako sieht man viele Beispiele, bei denen man Keyword-Parameter an eine render()-Funktion übergibt. Ich dachte genau darüber reden wir hier u.a.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

IMHO ist es schlechtes Design Keyword Argumente für etwas anderes zu nutzen als optionale Argumente, erst recht wenn ich sie dafür nutze um Daten zu repräsentieren. Die syntaktische und semantische Ebene der Programmiersprache sollte einfach nicht mit der Verarbeitung der Daten vermischt werden, aus dem gleichen Grund vermeidet man schliesslich auch Typprüfungen.
lunar

@DasIch: I„Syntaktische und semantische Ebene“?! Ist das jetzt nicht etwas sehr dogmatisch? Der Kontext eines Templates ist doch fast immer statisch, alle darin enthaltenen Namen sind meist zur Entwicklungszeit bekannt. Es ist doch nur pragmatisch und praxisnah, wenn die API den Kontext über Schlüsselwörter abbildet, statt auf einem separat zu erzeugenden Wörterbuch zu beharren.

Ganz abgesehen davon kann man diese Argumentation auch ganz einfach umdrehen. Der Kontext ist ja letztlich nichts anderes als der Namensraum für das Template, ein Schlüssel im Kontext also eigentlich dasselbe wie ein Name in Python. Der Kontext ist im Template auf der „syntaktischen und semantischen Ebene“, und sollte es somit auch in Python sein.
BlackJack

@lunar: Also ich seh's ähnlich dogmatisch. ``ham(something, spam=42, eggs=23)`` vs. ``ham(something, dict(spam=42, eggs=23))`` erscheint mir jetzt echt nicht unzumutbar viel mehr Tipparbeit. Und man verbaut sich nicht die Möglichkeit der `ham()`-Funktion selbst später noch benannte Argumente hinzufügen zu können die auch im Dictionary vorkommen dürfen/können.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nun frage ich mich aber, wieso die div. Template Autoren diese Möglichkeit vorgesehen haben? Sehen die das allesamt anders, oder ist es eine Art "historische" Entwicklung? In vielen Tutorials sehe ich aber auch, dass die Autoren davon Gebrauch machen, anstatt die auch mögliche dict()-Variante zu nutzen.

@DasIch: Nutzt ihr in inyoka also die "render(name, dict())"-Variante?

Ich persönlich habe mir ehrlich gesagt nie solche Gedanken darüber gemacht; da ich dieses Konzept von den div. render()-Funktionen einfach kannte. Daher habe ich das mal "naiv" als gutes Beispiel genannt; vielleicht ist es hier also gar nicht "gut", sondern nur ein Beispiel, wo das in der Praxis verwendet wird? (und ggf. also sogar ein schlechtes)

Ich selber habe im Sommer mal eine Template Engine für Java benutzt und fand es dort extrem nervig, dass ich mir erst eine Map zusammenbasteln musste, in der ich dann die div. Parameter an mein Template übergeben konnte. In dem Zusammenhang empfand ich die Möglichkeit in Python, beliebig viele Parameter an eine Funktion zu übergeben, als angenehmer. Aber ich gebe zu ich bin auch kein Experte bei solchen Sprach theoretischen Diskussionen und lasse mich da gerne eines besseren belehren.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Hyperion hat geschrieben:@DasIch: Nutzt ihr in inyoka also die "render(name, dict())"-Variante?
Die Views haben einen templated Dekorator und geben den Kontext als dict zurück.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

DasIch hat geschrieben:
Hyperion hat geschrieben:@DasIch: Nutzt ihr in inyoka also die "render(name, dict())"-Variante?
Die Views haben einen templated Dekorator und geben den Kontext als dict zurück.
Ok, also quasi wie in der flask-Doku erklärt. Danke für die Info!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Ist das hauptsächlich nervige bei Java nicht, dass es weder `Map`-Literale noch die Möglichkeit gibt ein `Map`-Exemplar wie `dict()` mit Schlüsselwort-Argumenten zu füllen? Das werden in Java dann ja erst mal richtig viele Quelltextzeilen für etwas was eigentlich ganz einfach ist, oder zumindest sein sollte.

Bei der Signatur von `dict()` kann ich mich übrigens auch an Diskussionen in der englishsprachigen Newsgroup erinnern, dass es blöd ist, dass man sich dadurch Möglichkeiten verbaut hat, wie zum Beispiel ``dict(capacity=100)`` um die Hashtabelle beim Erstellen auf eine bestimmte Grösse vorzuinitialisieren, oder in Anlehnung an das `key`-Argument bei `list.sort()`/`sorted()`/`min()` usw. eine andere Funktion anzugeben als `hash()` um den Schlüssel in die Hashtabelle einzutragen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben:@Hyperion: Ist das hauptsächlich nervige bei Java nicht, dass es weder `Map`-Literale noch die Möglichkeit gibt ein `Map`-Exemplar wie `dict()` mit Schlüsselwort-Argumenten zu füllen?
Stimmt! Ginge das, wäre es auch in Java in solchen Fällen erträglich(er). Ok, dank Eclipse und Co. tippern sich solche Snippets auch relativ fix, dennoch ist es ziemliche viel Boilerplate.
Bei der Signatur von `dict()` kann ich mich übrigens auch an Diskussionen in der englishsprachigen Newsgroup erinnern, dass es blöd ist, dass man sich dadurch Möglichkeiten verbaut hat, wie zum Beispiel ``dict(capacity=100)`` um die Hashtabelle beim Erstellen auf eine bestimmte Grösse vorzuinitialisieren, oder in Anlehnung an das `key`-Argument bei `list.sort()`/`sorted()`/`min()` usw. eine andere Funktion anzugeben als `hash()` um den Schlüssel in die Hashtabelle einzutragen.
Stimmt. An solche Dinge denkt man irgend wie selten - bis es einen "trifft". Andererseits fällt mir nicht ein, wie man das sonst lösen könnte / sollte? Manchmal ist der hauptsächliche use-case imho wichtiger, als alle Eventualitäten abzudecken.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

@BlackJack: Es ist Dir bestimmt nicht entgangen, dass auch die von Dir gezeigte Alternative, die in der Tat nicht wesentlich mehr Tipparbeit darstellt, nur deswegen funktioniert, weil auch die Signatur von "dict()" dank **-Magie beliebig viele Schlüsselwortargumente akzeptiert. Ich bedauere, Dir zu widersprechen, doch es fällt mir angesichts dieses Umstandes schwer, Dein Dogma zu verstehen.

Ich will bestimmt nicht abstreiten, dass die Asterik-Formen in der Signatur der Lesbarkeit des Quelltexts durchaus abträglich sein können, und den Gebrauch anderer Namen in der Signatur erschweren oder gar verhindern, doch in Fällen, in denen diese Formen der Lesbarkeit zuträglich sind, ist ihrer Anwendung meines Erachtens durchaus zu begrüßen. Der diskutierte Fall der ".render()"-Methoden für Template-Objekte fällt nun genau in diese Kategorie.

Im Übrigen stellt die Signatur dieser Methoden in den üblichen Template-Engines nun mittlerweile ein mehr oder weniger unveränderliches Faktum dar, so dass die Diskussion über Sinn und Unsinn dieses speziellen Falls mir reichlich überflüssig erscheint.
BlackJack

@lunar: Nein das ist mir nicht entgangen -- warum das auch bei `dict()` schlecht ist, habe ich aber auch schon geschrieben. Nur kann ich die Signatur von `dict()` nicht mehr ändern -- da ist die API nun mal vergeigt worden -- aber ich kann sehr wohl in meinem Quelltext nicht den gleichen Fehler machen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mir ist in dem Zusammenhang noch ein schönes Beispiel eingefallen: die format()-Methode von Strings! Auch da ließe sich die Argumentation der dict()-Befürworter anwenden, oder irre ich hier?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten