+ Turns out I provoked this by adding classify_class_attrs() to inspect.py, and then foolishly added a test for it <wink>. The symptom can be provoked by one judiciously chosen line:
C:\Code\python\PCbuild>python Python 2.2a3+ (#23, Sep 20 2001, 19:43:51) [MSC 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information.
staticmethod(42) # "object at" output <staticmethod object at 0x00788710> len(staticmethod.__dict__) # and you think this is harmless <wink> 10 staticmethod(42) # whoa! now it's "instance at" output <staticmethod instance at 0x00788710>
That is, just asking for a type's __dict__ can change the values in the type slots. This doesn't seem right -- or does it?
Argh. Sorry. The short answer: my bad, fixed in CVS now. The long answer: There's a default repr() implementation in object.c, which uses "object". This is in PyObject_Repr() when the object doesn't have a tp_repr slot. But there's also a default repr() implementation in typeobject.c, and this one used "instance". (The fix was to change it to use "object" too; it was clearly my intention that this would yield the same output as the default in PyObject_Repr().) The version in typeobject.c is the tp_repr slot of 'object', the universal base class. When a type's initialization is completed by PyType_Ready(), a NULL tp_repr slot is replaced by the tp_repr slot inherited from its base class -- and if there's no explicit base class, the base class 'object' is assumed. Because we currently don't explicitly initialize all type object, most types are auto-initialized on their first attribute requested from one of their instances, by PyObject_GenericGetAttr(): this calls PyType_Ready(tp) if the type is not fully initialized. Asking a type's attribute also auto-initializes the type, because the getattr operation does the same thing that PyObject_GenericGetAttr() does. So repr(T()) does not initialize T, because it doesn't request an attribute (it merely looks at the tp_repr slot). But asking for T.__dict__ *does* initialize T. Yes, this is a mess. We may be better off requesting that all types are initialized explicitly; for most standard types, we can do that in a new function called from Py_Initialize(). But there's a catch: PyType_Ready() uses some other types as helpers, in particular it may create tuples and dictionaries and use them. So at least these two types (and of course strings, which are used as keys) have to be usable without being initialized, in order for their own initialization to be able to proceed. Maybe others. --Guido van Rossum (home page: http://www.python.org/~guido/)