UserDict.UserDict vs. dict

16/02/2014 - 17:34 von Michael Ströder | Report spam
Hallo zusammen,

kann mich mal jemand erhellen, was der feine Unterschied ist, wenn ich eine
Klasse von UserDict.UserDict oder dict ableite und die in der Python Format
String Syntax verwende?

Gegeben ist der Code unten und ich würde in beiden Fàllen die selbe Ausgabe
erwarten (Python 2.7.5).

Ist aber unterschiedlich:

$python tmp/dict_template_test.py
Str1stValueUserDict Classic: Foo a1 bar b1
Str1stValueUserDict New: Foo a1 bar b1
Str1stValueDict Classic: Foo a1 bar b1
Str1stValueDict New: Foo ['a1', 'a2'] bar ['b1', 'b2']

Warum?

Ciao, Michael.

import UserDict

class Str1stValueUserDict(UserDict.UserDict):

def __getitem__(self,key):
return UserDict.UserDict.__getitem__(self,key)[0]

e = {
'a':['a1','a2'],
'b':['b1','b2'],
}

e_1st = Str1stValueUserDict(e)

print 'Str1stValueUserDict Classic:','Foo %(a)s bar %(b)s' % e_1st

print 'Str1stValueUserDict New:','Foo {a} bar {b}'.format(**e_1st)

class Str1stValueDict(dict):

def __getitem__(self,key):
return dict.__getitem__(self,key)[0]

e_1st = Str1stValueDict(e)

print 'Str1stValueDict Classic:','Foo %(a)s bar %(b)s' % e_1st

print 'Str1stValueDict New:','Foo {a} bar {b}'.format(**e_1st)
 

Lesen sie die antworten

#1 Peter Otten
16/02/2014 - 18:19 | Warnen spam
Michael Ströder wrote:

Hallo zusammen,

kann mich mal jemand erhellen, was der feine Unterschied ist, wenn ich
eine Klasse von UserDict.UserDict oder dict ableite und die in der Python
Format String Syntax verwende?

Gegeben ist der Code unten und ich würde in beiden Fàllen die selbe
Ausgabe erwarten (Python 2.7.5).

Ist aber unterschiedlich:

$python tmp/dict_template_test.py
Str1stValueUserDict Classic: Foo a1 bar b1
Str1stValueUserDict New: Foo a1 bar b1
Str1stValueDict Classic: Foo a1 bar b1
Str1stValueDict New: Foo ['a1', 'a2'] bar ['b1', 'b2']

Warum?

Ciao, Michael.

import UserDict

class Str1stValueUserDict(UserDict.UserDict):

def __getitem__(self,key):
return UserDict.UserDict.__getitem__(self,key)[0]

e = {
'a':['a1','a2'],
'b':['b1','b2'],
}

e_1st = Str1stValueUserDict(e)

print 'Str1stValueUserDict Classic:','Foo %(a)s bar %(b)s' % e_1st

print 'Str1stValueUserDict New:','Foo {a} bar {b}'.format(**e_1st)

class Str1stValueDict(dict):

def __getitem__(self,key):
return dict.__getitem__(self,key)[0]

e_1st = Str1stValueDict(e)

print 'Str1stValueDict Classic:','Foo %(a)s bar %(b)s' % e_1st

print 'Str1stValueDict New:','Foo {a} bar {b}'.format(**e_1st)



Ich glaube, dass der entscheidende Unterschied für dein Beispiel ist, dass
Python durch den **-call implizit ein neues dict baut. Für dict-subclasses
wird dabei ein optimierter code-path verwendet, der nicht auf __getitem__()
zugreift.

class U(UserDict):






... def __getitem__(self, key): return 42
...
u = U("aA bB cC".split())
dict(u)






{'c': 42, 'a': 42, 'b': 42}
class D(dict):






... def __getitem__(self, key): return 42
...
d = D("aA bB cC".split())
dict(d)






{'c': 'C', 'a': 'A', 'b': 'B'}

PS: Eine einzige Zeile müsste geàndert werden, damit sich dict wie UserDict
verhàlt:

Python 3.4.0rc1+ (default:2ba583191550+, Feb 16 2014, 18:12:05)
[GCC 4.6.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
class D(dict):






... def __getitem__(self, key): return 42
...
d = D("aA bB cC".split())
dict(d)






{'b': 42, 'c': 42, 'a': 42}







[1]+ Angehalten ./python
$ hg diff
diff -r 2ba583191550 Objects/dictobject.c
a/Objects/dictobject.c Tue Feb 11 18:40:56 2014 +0100
+++ b/Objects/dictobject.c Sun Feb 16 18:14:02 2014 +0100
@@ -1954,7 +1954,7 @@
return -1;
}
mp = (PyDictObject*)a;
- if (PyDict_Check(b)) {
+ if (PyDict_CheckExact(b)) {
other = (PyDictObject*)b;
if (other == mp || other->ma_used == 0)
/* a.update(a) or a.update({}); nothing to do */

Ähnliche fragen