HerrHagen hat geschrieben:bords0 hat geschrieben:Deshalb halte ich es für etwas klarer, das Problem nicht auf die mutablen Default-Argumente zu schieben, sondern auf das Mutieren selbst.
Das Problem mit der Geschichte ist, dass der Umstand, dass ein default-Argument nur einmalig erzeugt wird, vielen nicht bekannt,
Richtig.
überdies auch sehr unintuitiv,
Eigentlich nur, bis man verstanden hat, dass das "def"-Statement tatsächlich ausgeführt wird - und zwar zur
Definition der Funktion, nicht beim Aufruf derselben.
und IMO auch ziemlich unsinnig ist.
Da sind wir überhaupt nicht einer Meinung... weil es IMO keine sinnvollere Alternative gibt.
Um solche Probleme wie oben gesehen zu vermieden, sollte man auf solche Sachen von vornherein verzichten. Wenn das Objekt also sowieso nicht verändert werden sollte, dann sollte dies auch durch die Datenstruktur entsprechend abgebildet werden (also unveränderliche Liste = tuple).
Das ist m.E. zwar i.W. richtig, aber es gibt Ausnahmen.
Code: Alles auswählen
>>> def shuffled_range(n, extra=[]):
import random
r = range(n) + extra
random.shuffle(r)
return r
>>> shuffled_range(5)
[2, 0, 4, 3, 1]
>>> shuffled_range(10, [-1, "Zehn"])
['Zehn', 9, 6, -1, 5, 0, 8, 3, 7, 1, 4, 2]
>>> shuffled_range(5, ())
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
shuffled_range(5, ())
File "<pyshell#5>", line 3, in shuffled_range
r = range(n) + extra
TypeError: can only concatenate list (not "tuple") to list
Oder auch
Code: Alles auswählen
>>> class Spam(object):
def __init__(self, attrs={}):
self.__dict__.update(attrs)
>>> s = Spam()
>>> s.__dict__
{}
>>> t = Spam({"foo": "bar", "baz": "blubb"})
>>> t.__dict__
{'foo': 'bar', 'baz': 'blubb'}
>>> t.baz
'blubb'
Letzteres würde zwar auch mit einem leeren tuple funktionieren, aber so finde ich es viel klarer. (Naja, mit einem nicht-leeren tuple wäre das Beispiel wohl besser gewesen.)