[Python-Dev] q about __dict__

Guido van Rossum guido@python.org
Tue, 13 Aug 2002 11:15:30 -0400


> Anybody, please explain me, is this a bug? :

No and yes.  It's curently defined as a feature -- you can subclass
dict, but it's not always safe to override operations like __getitem__
because Python internally takes shortcuts for dicts used to implement
namespaces.  For dicts used for namespaces, it's only safe to add new
methods; for dicts not used for namespaces, it's safe to override
special methods.

> Code
> === begin ===
> class Dict(dict):
> 	def __setitem__(*x):
> 		raise Exception, "Please, do not touch me!"
> 
> class A:
> 	def __init__(*x):
> 		self.__dict__ = Dict()
> 
> A().x = 12
> ===  end  ===
> doesn't raise Exception, i. e. my __setitem__ function is not called.
> 
> Patching that is simple: in Objects/classobject.c need to replace
> 	PyDict_SetItem -> PyObject_SetItem
> 	PyDict_GetItem -> PyObject_GetItem
> 	PyDict_DelItem -> PyObject_DelItem
> and maybe something else (not much).
> 
> Overhead is minimal, and as bonus python gets ability of assigning
> object of any type (not inherited from dict) to __dict__.

Have you tried this?  Because PyDict_GetItem() doesn't set an
exception condition when the key is not found, a lot of code would
have to be changed.

> Motivation:
> 
> Somethimes I want to write strange classes, for example, class with
> ordered attributes. I know, that it is possibe to implement this
> redefining class attributes __setattr__, etc., but setting __dict__
> looks clearer.

For this particular situation (instance variables) I'm not totally
against fixing this, but I don't find it has a high priority.  You can
help by providing a patch that implements your idea above, and showing
some benchmark results (e.g. based on PyBench) that indicate the
minimal performance impact you're claiming.  If you don't feel like
doing this yourself (e.g. because you're not confident about your C
coding skills), ask around on comp.lang.python for help.

--Guido van Rossum (home page: http://www.python.org/~guido/)