[Python-de] Neue Instance mit gleichem Typ über eine Variable?

Peter Otten __peter__ at web.de
Sa Mai 25 12:02:19 CEST 2013


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))




Mehr Informationen über die Mailingliste python-de