Parameterwert mit dem gleichen Namen übergeben...

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
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

... auch wenn dieser nicht derselbe ist?

Code: Alles auswählen

def func(foo, bar):
    return another_func(foo=foo, bar=bar)
Bisher hat's funktioniert, aber ich hör' schon wieder die Flöhe husten... :wink:
Auch wenn die Namensräume getrennt sind, könnte es ein Problem geben, von dem ich nichts weiß?

mutetella


Hmm... ist `foo` in `func` eigentlich der gleiche oder derselbe Name wie `foo` in `another_func`? Doch wohl eher der gleiche, oder?
Nur: Wo findet dann die Unterscheidung statt, d. h., wo steht das Schild "Sie verlassen nun `func`"?
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich versteh irgendwie dein Problem wieder nicht, aber das bin ich ja bei dir gewohnt ;)

So aus dem Stehgreif würd ich aus deinem Code einfach dieses machen:

Code: Alles auswählen

func = another_func
Und nun sag mir was du erreichen willst und was du mit gleichen oder selben haben willst. Vielleicht hilft dir das schon: in Python werden Namen nie übergeben. Es werden Objekte übergeben. Also bekommt deine Funktion ``func`` zwei Obekte, die sie in ihrem lokalen Namensraum an ``foo`` und ``bar`` bindet. Dann übergibt sie die an diese Identifier gebundenen Objekte an die Funktion ``another_func``. Aber damit erzähle ich jetzt auch nix weltbewegendes.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo,

das ist in Ordnung so, damit bekommst du keine Probleme.

Zu den Namen: `foo` ist in `func` ein vollkommen anderer Name als in `another_func`. Alles ande wäre auch ein sehr seltsames Verhalten und es könnten gleich alle Parameter durch globale Variablen ersetzt werden. Schreibe dir mal eine kleines Testprogramm und schaue mit einem Dissasembler nach, was für Bytecode generiert wird. Dann verstehst du den Mechanismus sehr schnell.

Sebastian
Das Leben ist wie ein Tennisball.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Leonidas hat geschrieben:Und nun sag mir was du erreichen willst und was du mit gleichen oder selben haben willst.
Ich habe eine Funktion, die mir eine Auswahl an Termineinträgen in einer bestimmten Reihenfolge zurückgeben soll.
Diese Funktion habe ich unter anderem mit einem Parameter `reverse` versehen. Innerhalb der Funktion wird `sorted()` aufgerufen, der ich wiederum den Wert aus `reverse` übergebe. So in etwa:

Code: Alles auswählen

def get_entries(reverse=False):
    ...
    return sorted(entries, reverse=reverse)
Und jetzt war ich mir nicht ganz sicher, ob ich mir für meinen `reverse`-Parameter einen anderen Namen überlegen sollte, falls es aus irgendeinem Grund einmal ein Problem geben könnte.
EyDu hat geschrieben:Dann verstehst du den Mechanismus sehr schnell.
Dass Du das glaubst, ehrt mich sehr... :)
Aber aus der Ausgabe von `dis()` kann ich nur herauslesen, was mir irgendwie schon klar ist und Leonidas beschrieben hat.

Code: Alles auswählen

In [52]: def sort_seq(seq, reverse):
    return sorted(seq, reverse=reverse)
   ....: 

In [54]: dis.dis(sort_seq)
  2           0 LOAD_GLOBAL              0 (sorted)
              3 LOAD_FAST                0 (seq)
              6 LOAD_CONST               1 ('reverse')
              9 LOAD_FAST                1 (reverse)
             12 CALL_FUNCTION          257
             15 RETURN_VALUE
Die Antwort auf meine Frage scheint mir hinter `LOAD_CONST` und `LOAD_FAST` zu liegen. Ich verstehe allerdings den Unterschied nicht...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: An dem disassemblierten Code kann man eigentlich nichts sehen. Wenn Dir nicht klar ist, dass verschiedene lokale Namensräume nichts miteinander zu tun haben, dann würde nur ein nachvollziehen des Quelltextes vom Interpreter helfen. Und das ist ungleich schwieriger als die IMHO simple Einsicht das lokale Namensräume ziemlich sinnfrei wären wenn lokale Namen Probleme in anderen lokalen Namensräumen verursachen könnten.

Zum Bytecode: LOAD_CONST lädt eine Konstante auf den Stapel und LOAD_FAST den Wert einer lokalen Variable. Was da abgeht ist also folgendes: Per LOAD_GLOBAL wird das Objekt mit dem Namen `sorted` auf den Stapel geladen. Dann wird der Wert der lokalen Variablen `seq` auf den Stapel geladen. Dann die Zeichenkette 'reverse'. Zum Schluss der Wert der lokalen Variable `reverse`. An der Stelle könnte der Stapelinhalt also zum Beispiel so aussehen wenn man ``sort_seq([3, 1, 2], True)`` ausgeführt hat:

Code: Alles auswählen

4: ...
3: <built-in function sorted>
2: [3, 1, 2]
1: 'reverse'
0: True
Ausgehend von diesem Zustand wird der Bytecode-Befehl ``CALL_FUNCTION 257`` ausgeführt, wobei das Argument 257 die Anzahl der Positions- und Schlüsselwortargumente kodiert. Das ist ein 16-Bit-Wert, bei dem die unteren 8 Bit die Anzahl der Positionsargumente und die oberen 8 die Anzahl der Schlüsselwortargumente angibt:

Code: Alles auswählen

In [202]: 257 & 0xff
Out[202]: 1

In [203]: 257 >> 8 & 0xff
Out[203]: 1
Wie man erwarten würde ist beides 1. Damit weiss der Interpreter dann wie viele Einzelobjekte für Positionsargumente und Schlüssel-Wert-Paare für Schlüsselwortargumente auf dem Stapel liegen, bevor das aufrufbare Objekt kommt, welches mit den Argumenten aufrufen werden soll.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:Wenn Dir nicht klar ist, dass verschiedene lokale Namensräume nichts miteinander zu tun haben, ...
Das ist mir natürlich klar.
Die Frage entstand für mich deshalb, weil ja zum Zeitpunkt des Funktionsaufrufes, also in dieser Zeile

Code: Alles auswählen

sorted(seq, reverse=reverse)
sich der Name `reverse` zum einen auf `sorted()` und zum anderen auf `sort_seq()` bezieht.
Aber ok, es wird mir mehr und mehr klarer...

Das was Du zu `dis` schreibst muss ich mir heute abend noch in aller Ruhe einverleiben... :wink:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Zu dem Zeitpunkt bezieht sich das alles noch auf `sorted_seq()`. Das ``reversed=reversed`` könnte man ja auch als ``**{'reversed': reversed}`` ausdrücken. Erst im Code der aufgerufenen Funktion werden die Werte aus dieser Abbildung an deren lokale Variablen gebunden.
Antworten