Neue Instance mit gleichem Typ über eine Variable?
Im nachfolgenden Beispiel arbeitet die Funktion mit Dictionaries aber wenn von aussen ein anderer Type von Dictionary hereinkommt dann soll auch innerhalb der Funktion beim Anlegen eines neuen Dictionaries der gleiche Typ verwendet werden. Wie macht man das? (Frage: kann ich vermeiden die Klasse als Parameter mitzuschleifen?) Wenn möglich sollte die Lösung auch für ältere Python Versionen (>= 2.3) funktionieren. [code] def foo(var = {}): # calc someting var["results"] = {} # <- OrderedDictionary? return var print(foo()) print(foo(OrderedDictionary())) [/code]
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Thomas Lehmann wrote:
Im nachfolgenden Beispiel arbeitet die Funktion mit Dictionaries aber wenn von aussen ein anderer Type von Dictionary hereinkommt dann soll auch innerhalb der Funktion beim Anlegen eines neuen Dictionaries der gleiche Typ verwendet werden. Wie macht man das? (Frage: kann ich vermeiden die Klasse als Parameter mitzuschleifen?)
Bitte was? Ich kann dem Code nicht viel Sinnhaftigkeit abgewinnen. Da die Variablenübergabe hier call-by-reference ist, ist auf jeden Fall das "return var" überflüssig. Du brauchst nichts zurückgeben was Du eh schon hast....bitte noch mal Nachdenken und eine sinnvolle Fragen stellen. Was ist Dein genaues Problem? - -aj
Wenn möglich sollte die Lösung auch für ältere Python Versionen (>= 2.3) funktionieren.
[code] def foo(var = {}): # calc someting var["results"] = {} # <- OrderedDictionary? return var
print(foo()) print(foo(OrderedDictionary())) [/code] _______________________________________________ python-de maillist - python-de@python.org http://mail.python.org/mailman/listinfo/python-de
- -- ZOPYX Limited | Python | Zope | Plone | MongoDB Hundskapfklinge 33 | Consulting & Development D-72074 Tübingen | Electronic Publishing Solutions www.zopyx.com | Scalable Web Solutions - -------------------------------------------------- Produce & Publish - www.produce-and-publish.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQGUBAEBAgAGBQJRoHaaAAoJEADcfz7u4AZjat8LwMNmHVgC9ZWGpV4R8J0WhCX6 Gf5YONKulgo3u2DdpBS0SPpbFpvRqK9fZd3tc8PRV27GGn72IncRnFakUugEj0PC 9J2CJZp30iUvSVZnhg+LP/yrOfHCuzEl2RrvgQfjY+w8CLG8IZROD/xYguX3i63t jxWUVyCccwC+vhMbxw//1ZlrXb0OjGRbKRdvH5VS4EBTA8pKPktib6wjan+x1+Tn i4eQcOxewroLLcM0tZivQtrjUr+N5SE919P+VgsZ43KXJOpg3WdKCuo0JXHLZOBr RsiKpmsXYBRgo4+csel/DSJ0ij/C9d+g8EdBwPxSOBQDebXiyIQ+nUFuKRiysLaz Y6TY907IxrVItNUxIDC8CV3RS5/3jtq8pZhXo10cHN7Pq3TNWZlc3yD+cuijMCB7 kZU/GuwXu9i4z2U/YJ7WFmzZNm15xcSwsdTe7NxsEhdiBW0O+QTCe72YZnJ/3A+6 Ua12Lrp4NBRnpKbh1s6vll787IcpOFA= =ItmK -----END PGP SIGNATURE-----
Hallo,
(Frage: kann ich vermeiden die Klasse als Parameter mitzuschleifen?)
ich weiß nicht so genau, ob ich die Frage richtig verstanden habe, aber wenn Du die Instanz einer Klasse hast (nennen wir sie mal YourInstance), kannst Du doch über YourInstance.__class__ Dir jederzeit die Klasse der Instanz holen und davon weider eine neue Instanz anlegen. Also in etwa so: a = YourInstance # Deine Instanz klass = YourInstance.__class__ # die Klasse Deiner Instanz NewInstanz = klass() # eine neue Instanz der Klasse Deiner Ursprungsinstanz Hilft Dir das weiter oder bin ich da auf dem Holzweg. Gruß Carsten
Thomas Lehmann wrote:
Im nachfolgenden Beispiel arbeitet die Funktion mit Dictionaries aber wenn von aussen ein anderer Type von Dictionary hereinkommt dann soll auch innerhalb der Funktion beim Anlegen eines neuen Dictionaries der gleiche Typ verwendet werden. Wie macht man das? (Frage: kann ich vermeiden die Klasse als Parameter mitzuschleifen?)
Wenn möglich sollte die Lösung auch für ältere Python Versionen (>= 2.3) funktionieren.
[code] def foo(var = {}): # calc someting var["results"] = {} # <- OrderedDictionary? return var
Die offensichtliche Lösung
from collections import defaultdict, OrderedDict def foo(var): ... dict_type = type(var) ... var["results"] = dict_type() ... return var ... items = "a1 b2 c3".split() foo(OrderedDict(items)) OrderedDict([('a', '1'), ('b', '2'), ('c', '3'), ('results', OrderedDict())]) foo(defaultdict(int, items)) defaultdict(<type 'int'>, {'a': '1', 'c': '3', 'b': '2', 'results': defaultdict(None, {})})
kommt mit `defaultdict`s nicht klar. Also
def bar(var): ... def empty(): ... c = var.copy() ... c.clear() ... return c ... var["results"] = empty() ... return var ... bar(OrderedDict(items)) OrderedDict([('a', '1'), ('b', '2'), ('c', '3'), ('results', OrderedDict())]) bar(defaultdict(int, items)) defaultdict(<type 'int'>, {'a': '1', 'c': '3', 'b': '2', 'results': defaultdict(<type 'int'>, {})})
Etwas weniger "hacky": from collections import OrderedDict, defaultdict def empty_defaultdict(d): return defaultdict(d.default_factory) def empty_any(d): return type(d)() _lookup_dict_factory = defaultdict(lambda: empty_any, {defaultdict: empty_defaultdict}) def baz(var): empty = _lookup_dict_factory[type(var)] var["result"] = empty(var) return var items = "a1 b2 c2".split() print baz(defaultdict(int, items)) print baz(OrderedDict(items))
Thomas Lehmann wrote:
def foo(var = {}):
Ohne jetzt genau auf die Frage einzugehen, was andere ja schon gemacht haben: Ist ein mutable Default-Wert für ein key-word argument nicht ein absolutes no-go? Zumindestens musste ich das selbst mal auf die harte Tour lernen und vor allem kann es je nachdem sicherheitsrelevant werden. Besser wäre def foo(var = None): var = var or {} [..] Dann wird nämlich jedes Mal eine neue Dictionary-Instanz erzeugt, falls nur foo() aufgerufen wird. Ciao, Michael.
On May 25, 2013, at 12:23 PM, Michael Ströder <michael@stroeder.com> wrote:
Thomas Lehmann wrote:
def foo(var = {}):
Ohne jetzt genau auf die Frage einzugehen, was andere ja schon gemacht haben:
Ist ein mutable Default-Wert für ein key-word argument nicht ein absolutes no-go? Zumindestens musste ich das selbst mal auf die harte Tour lernen und vor allem kann es je nachdem sicherheitsrelevant werden.
Ja, das ist gefährlich.
Besser wäre
def foo(var = None): var = var or {} [..]
Dann wird nämlich jedes Mal eine neue Dictionary-Instanz erzeugt, falls nur foo() aufgerufen wird.
Und noch besser wäre var = {} if var is None else var seit Python 2.5. Denn dieses Gefummel mit or und and statt dem ternaeren if führt ebenfalls zu seiner ganz eigenen Klasse von Fehlern. Diez
On Sat, 25 May 2013 20:23:01 +0200 Michael Ströder <michael@stroeder.com> wrote:
Thomas Lehmann wrote:
def foo(var = {}):
Ohne jetzt genau auf die Frage einzugehen, was andere ja schon gemacht haben:
Ist ein mutable Default-Wert für ein key-word argument nicht ein absolutes no-go? Zumindestens musste ich das selbst mal auf die harte Tour lernen und vor allem kann es je nachdem sicherheitsrelevant werden.
Besser wäre
def foo(var = None): var = var or {} [..]
Dann wird nämlich jedes Mal eine neue Dictionary-Instanz erzeugt, falls nur foo() aufgerufen wird.
Oha, wenn man darüber nachdenkt, fällt es einem wie Schuppen aus den Haaren.
participants (7)
-
Andreas Jung
-
Arnold Krille
-
creimer@xs4all.nl
-
Diez B. Roggisch
-
Michael Ströder
-
Peter Otten
-
Thomas Lehmann