@any: Nein, es ist nicht dasselbe, nicht einmal das gleiche
„def ausführen“ bedeutet, dass die
Deklaration der Funktion ausgewertet wird. Immer, wenn Python auf ein "def" stößt, erzeugt es ein neues Funktionsobjekt mit dem entsprechenden Namen und den Argument, und speichert den Körper der Funktion in diesem Objekt. Zu diesem Zeitpunkt werden auch die „Default-Werte“ ausgewertet (und dann ebenfalls im Funktionsobjekt gespeichert). Ein solches Funktionsobjekt kann man dann auch entsprechend abfragen:
Code: Alles auswählen
>>> def say_hello(names=[]):
... """Say hello to the given people"""
... return 'Hello {0}'.format(', '.join(names))
...
>>> say_hello
<function say_hello at 0x1dc6578>
>>> say_hello.__name__
'say_hello'
>>> say_hello.__doc__
u'Say hello to the given people'
>>> import inspect
>>> inspect.getargspec(say_hello)
ArgSpec(args=['names'], varargs=None, keywords=None, defaults=([],))
>>> >>> say_hello.__code__
<code object say_hello at 0x1c9ae30, file "<input>", line 2>
In der letzten, etwas seltsamen Zeile verbirgt sich ein sogenanntes "Code"-Objekt. Es enthält den gesamten Funktionskörper (also in diesem Fall das "return …").
Dieser Funktionskörper wurde aber bisher nicht ausgeführt. Das geschieht erst, wenn man die Funktion aufruft:
Code: Alles auswählen
>>> say_hello()
u'Hello '
>>> say_hello(names=['Ford', 'Zaphod'])
u'Hello Ford, Zaphod'
Dabei werden die Argumente an das Code-Objekt übergeben, welches dann ausgeführt wird. Darin besteht der Unterschied zwischen einer Funktions
deklaration und einem Funktions
aufruf
Beachte die erste Zeile in obigen Beispiel. Beim Aufruf der Funktion ohne einen Namen wird niemand bestimmtes gegrüßt. Die Gefahr von Standard-Argumenten ist nun, dass sich ihre Veränderung auf alle Funktionsaufrufe auswirkt, eben weil sie in der Funktion selbst gespeichert sind:
Code: Alles auswählen
>>> say_hello.__defaults__[0].append('Ford')
>>> inspect.getargspec(say_hello)
ArgSpec(args=['names'], varargs=None, keywords=None, defaults=([u'Ford'],))
>>> say_hello()
u'Hello Ford'
Die erste Zeile hängt an den Standardwert für das "names"-Argument einen Namen an, und auf einmal wird "Ford" gegrüßt, obwohl die Funktion erneut ohne Argumente aufgerufen wurde.