def f(x[i]):

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
hubgra
User
Beiträge: 53
Registriert: Donnerstag 20. Juli 2023, 17:20

wird als Syntaxfehler zurückgewiesen, warum? Darf ein Listeneintrag kein formaler Parameter sein?
Sirius3
User
Beiträge: 17767
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum willst Du als Parameter einen Listeneintrag?
Also was soll Deiner Meinung nach diese Syntax bewirken? Kannst Du ein vollständiges Pseudo-Beispiel geben, in der diese Syntax sinnvoll verwendet wird?

Code: Alles auswählen

def function(some_list, index):
    print(some_list[index])
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

hubgra hat geschrieben: Dienstag 22. August 2023, 10:56 wird als Syntaxfehler zurückgewiesen, warum? Darf ein Listeneintrag kein formaler Parameter sein?
Du kannst einen Listeneintrag als Parameterwert übergeben, aber der Name des Parameters selber muss eben das sein: ein Name.

Ich schließe mich da Sirius an: Was erwartest du, was da passieren soll?
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

Naja, man könnte erwarten, dass Parameter so wie alle anderen Zuweisungen funktionieren:

Code: Alles auswählen

In [1]: xs = [0, 1, 2]

In [2]: xs[0] = 42

In [3]: xs
Out[3]: [42, 1, 2]

In [4]: for xs[0] in range(10):
   ...:     print(xs)
   ...:
[0, 1, 2]
[1, 1, 2]
[2, 1, 2]
[3, 1, 2]
[4, 1, 2]
[5, 1, 2]
[6, 1, 2]
[7, 1, 2]
[8, 1, 2]
[9, 1, 2]

In [5]: xs
Out[5]: [9, 1, 2]

In [6]: (xs[0], xs[1]) = 27, 42

In [7]: xs
Out[7]: [27, 42, 2]
Warum sollte bei

Code: Alles auswählen

def f(xs[0]):
    pass

f(42)
nicht auch `xs` verändert werden? Von der Sinnhaftigkeit sehe ich das ungefähr auf einer Ebene mit `xs[0]` als Iterationsvariable in einer `for`-Schleife.
Benutzeravatar
snafu
User
Beiträge: 6744
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Krass, mir war bisher gar nicht klar, dass ``for xs[0] in range(10): print(xs)`` überhaupt funktioniert. Wollte auch etwas entsprechendes schreiben. Habe es vorher jedoch ausprobiert und gesehen, dass das gezeigte Ergebnis tatsächlich zutrifft. :o
Benutzeravatar
snafu
User
Beiträge: 6744
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Zur Frage: Der Name für ein Argument der Funktion ist ja bloß ein Stellvertreter für den übergebenen Wert. Also etwa: "Übergebe Wert 1 als x". Das ist ein anderes Konzept als wenn der Wert magisch zur Laufzeit ermittelt wird. Was übergibt man in dem Fall? Die komplette Liste `xs` und er zieht sich den Wert an Index 0?
Benutzeravatar
__blackjack__
User
Beiträge: 13131
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@narpfel: Naja, es ist noch ein bisschen sinnloser als eine Zuweisung an ``x[0]`` im Kopf einer ``for``-Schleife: `xs` müsste ja eigentlich eine Konstante sein, denn sonst würde die Funktion hier ja auf einem globalen Wert arbeiten. Wenn es eine Konstante ist, dann sollte man der aber keine anderen Werte/Elemente zuweisen. Also gäbe es für so ein Konstrukt noch weniger Anwendungsfälle.

Wie spielt das mit expliziten Schlüsselwortargumenten zusammen? Was ist mit Default-Werten? Was ist mit ``*``- und ``**``-Magie beim Aufruf der Funktion, wie funktioniert das? ``f(xs[0]=42)`` kann man sich ja noch vorstellen. Aber geht dann auch ``f(xs[1]=42)``? Wie müsste `d` in ``f(**d)`` aussehen wenn man so eine Funktion aufrufen möchte? Wie müssen die entsprechenden Aufrufe bzw. Ergebnisse aus dem `inspect`-Modul dann aussehen? Heissen die Argumentnamen dann nicht mehr Argumentnamen sondern Argumentausdrücke? Und werden die dann statt als Zeichenketten mit dem Namen, als AST-Nodes zurückgegeben? Wie komplex wird Code der jetzt mit Zeichenketten mit Namen arbeitet dadurch, also was bezahlt man da am Ende über zusätzliche Komplexität, für welchen Gewinn?
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
hubgra
User
Beiträge: 53
Registriert: Donnerstag 20. Juli 2023, 17:20

Den Schlüssel hat mir /me gegeben; der Parameter nuss ein Name sein.
Mein Ziel war, die Einträge einer Liste von Permutationen von 1,2,3,4 zeilenweise in ein 2x2-Fenster einer Matrix zu schreiben und so ein 4x4-Soduko herzustellen. Das ist gelungen, jedoch kommen dabei viermal solche Zuweisungen mit immer gleichen rechten Seiten für verschiede p und i vor:
a[0][2] = p[0]
a[0][3] = p[1]
a[1][2] = p[2]
a[1][3] = p[3]
Das wollte ich vereinfachen, indem ich eine Funktion sq(p) aufrufe, um ein 9x9-Sudoku herzustellen.
Und die Definition dieser Funktion ist misslungen.
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@__blackjack__: Hm, gute Fragen. Da man ja Funktionen auch lokal definieren kann, ist „`xs` müsste global sein“ IMHO kein Argument. Genauso wie `for xs[0] in ...` auch global erlaubt ist, aber nicht benutzt werden sollte.

Man könnte erfordern, dass diese Art von Parametern positional-only ist, weil es keine richtige Syntax gibt (bzw. geben kann), um den Namen beim Aufruf anzugeben.

Für `inspect` könnte man entweder sagen, dass der Parameter keinen Namen hat (Wozu braucht ein positional-only-Parameter einen Namen? Und nicht alle Callables haben `inspect`able Signaturen, z. B. wenn sie in C geschrieben sind.) oder es könnte das, was tatsächlich im Quelltext steht, als Parametername genommen werden. Also bei `def f((xs + ys)[42 + 27]): pass` wäre der Name dann `(xs + ys)[42 + 27]`. Zeichenkette ist Zeichenkette, würde sich dadurch also wirklich Code verkomplizieren?

Und für welchen Gewinn? Keine Ahnung, aber ich fand die Frage nachvollziehbar, warum das nicht erlaubt ist, weil es eine scheinbar willkürliche Restriktion ist. (Auch wenn die Frage am Ende doch was anderes gefragt hat. ;-)) Insbesondere auch, weil so was ähnliches in Python2 ja erlaubt war: Tuple unpacking in Signaturen:

Code: Alles auswählen

>>>> def f((a, b), (c, d), **e):
....     pass
....
>>>> inspect.getargspec(f)
ArgSpec(args=[['a', 'b'], ['c', 'd']], varargs=None, keywords='e', defaults=None)
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

narpfel hat geschrieben: Mittwoch 23. August 2023, 17:47 Und für welchen Gewinn? Keine Ahnung, aber ich fand die Frage nachvollziehbar, warum das nicht erlaubt ist, weil es eine scheinbar willkürliche Restriktion ist.
Vermutlich weil es keinen Sinn hat. Nichts in dieser Diskussion konnte mir bisher vermitteln, dass so etwas eine intelligente Lösung für was auch immer wäre.
Benutzeravatar
__blackjack__
User
Beiträge: 13131
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@narpfel: Ich weiss nicht ob ich das als willkürliche Restriktion bezeichnen würde. Das wäre es wenn es eigentlich schon implementiert ist und dann zusätzlicher Code das verhindert. Hier ist es ja anders herum: man müsste zusätzlich Code schreiben der das möglich machen würde.

Den Ausdruck einfach als Zeichenkette zu betrachten ist IMHO nicht sinnvoll/möglich. Denn "a[40 + 2]" und "a[42]" sind ja eigentlich gleich. Das es in C implementierte Funktionen gibt wo Positionsargumente keinen Namen haben ist richtig — und richtig scheisse, weil da bestimmte Sachen wie `functools.partial()` mit Namen und ``**`` bei Aufruf nicht funktionieren. Da will man weniger von, nicht noch mehr.
“There will always be things we wish to say in our programs that in all known languages can only be said poorly.” — Alan J. Perlis
Antworten