I'm talk from the point of view of descriptors. Consider a.x = lambda self:None # simple function
When a.x is later got, what criterion is used to see if a class (and so the func would have __get__(None, a) called on it)? Pre-metaclasses, one might assume it was isinstance(a, (types.TypeType, types.ClassType)) but nowadays the type of a type could be anything. Is there a simple Python-level interface to determine what constitutes a type, as there is for, say, iterators? Could an object start being a type just by appropriately setting certain members, or is this distinction enforced at a lower level? To confuse matters further, the descriptor docs in 2.4 say that descriptors can only be bound to objects, not classic class instances, but a few moments with a Python console disproves this (it is the descriptors themselves that have to be objects.) >>> def getting(*a): print "Getting!" >>> class oldDesc: __get__ = getting >>> class newDesc(object): __get__ = getting >>> class Q:pass # classic class >>> Q.x = oldDesc() >>> Q.x <__main__.oldDesc instance at 0x009ACAA8> >>> Q.y = newDesc() >>> Q.y Getting! This seems to be a more sensible state of affairs (otherwise function-to-method wrapping would have to be a special case), but http://www.python.org/doc/2.4/ref/descriptor-invocation.html says different. What is the canonical distinction between classes and types, and between instances and objects? How would it apply in the face of such perversions as from types import * class C1: __metaclass__ = TypeType class C2(object): __metaclass__ = ClassType or reassignment of __class__ from an class to a type or vice versa? I would have thought that "most of the time" (i.e. excluding the above tricksiness) all that would be needed was isinstance(x, object) but this returns true when x is an Exception, which is guaranteed to be an instance and hence not an object. Thanks John -- http://mail.python.org/mailman/listinfo/python-list