On Tue, 17 Dec 2013 23:35:10 +1300, Gregory Ewing wrote: > Steven D'Aprano wrote: >> I think I need to see an actual working demonstration, because as far >> as I can see, type(obj) returns obj.__class__. > > Nope: > > >>> class C(object): > ... def f(self): > ... return "Surprise!" > ... __class__ = property(f) > ... > >>> c = C() > >>> type(c) > <class '__main__.C'> > >>> c.__class__ > 'Surprise!'
Well, that is a surprise, but I don't think that is intended behaviour. I think that's something which only works by accident. The intention is that __class__ returns the instance's type, not arbitrary values. If you try to set it to a non-class on the instance, it fails: py> class D(object): ... pass ... py> d = D() py> d.__class__ = property(lambda self: 'Surprise!') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __class__ must be set to a class, not 'property' object Same when you try to set it on the class object itself: py> D.__class__ = property(lambda self: 'Surprise!') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __class__ must be set to a class, not 'property' object So my guess is that the fact that your code works at all is an accident. I can demonstrate that changing the __class__ of an instance causes type(obj) to return a different value, and also to dynamically change the behaviour of the object: py> class Spam(object): ... def method(self): ... return "spam" ... py> class Ham(object): ... def method(self): ... return "ham" ... py> ham = Ham() py> ham.method() 'ham' py> ham.__class__ = Spam py> ham.method() 'spam' py> type(ham) <class '__main__.Spam'> So this is a case where type(obj) returns obj.__class__ rather than it's internal type field. That's the point I was trying to make: type(obj) may return obj's internal type field, but if you set obj.__class__, type(obj) will then return the new class, not the internal one. -- Steven -- https://mail.python.org/mailman/listinfo/python-list