Le mardi 27 juin 2006 05:38, Phillip J. Eby a écrit : > At 05:16 PM 6/26/2006 -0700, Martin Maly wrote: > > >>> class D(object): > > > >... def getclass(self): > >... print "D.getclass" > >... return C > >... __class__ = property(getclass) > >... > > > > >>> isinstance(D(), D) > > > >True > > > > >>> isinstance(D(), C) > > > >D.getclass > >True > > > >isinstance in this case returns True to both C and D test. I would expect > > > >to see the __class__ property being called in both cases and get: > > >>> isinstance(D(), D) > > > >D.getclass > >False > > > >but that's not the case for some reason. > > That's because isinstance checks type(D()) and finds it equal to D -- this > shortcuts the process. > > > It seems that the __class__ is only accessed in some cases, but not > > always, leading to what I think is a semantic inconsistency. > > It's not inconsistent - isinstance() checks __class__ in *addition* to > type() in order to allow proxying tricks like lying about your > __class__. It therefore returns true if either your real type *or* your > __class__ matches, and as you can see, the real type is checked first. > > >class E(object): > > def getbases(self): > > print "E.getbases" > > return () > > __bases__ = property(getbases) > > > >class C(object): > > def getbases(self): > > print "C.getbases" > > return (E,) # C() claims: "E is my base > > class" __bases__ = property(getbases) > > > >class D(object): > > def getclass(self): > > print "D.getclass" > > return C() # D() claims: "C() is my > > __class__" __class__ = property(getclass) > > > > > >class F(object): pass > > > > > >print "Test 1" > >print isinstance(D(), E()) # testing against E() instance > >print "Test 2" > >print isinstance(D(), E) # testing against E class > > > >The output here is: > > > >Test 1 > >E.getbases > >D.getclass > >C.getbases > >False > > > >Test 2 > >D.getclass > >False > > > >In the 2nd test, D.getclass is called to get the __class__ of D(), which > >returns C() instance. At this point I would expect that C.getbases gets > >called as __bases__ are retrieved, which would return tuple consisting of > >E and ultimately produce True result. > > As it happens, this is due to the fact that E is a type, while E() is > not. There's an optimization in the isinstance() machinery that simply > checks to see if D().__class__ is a subtype of E. That's where your > experiment fails. > > I'm not sure whether this behavior should be considered correct or not. > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > http://mail.python.org/mailman/options/python-dev/maric%40aristote.info
Doesn't seems to be just related to isinstance implementation, furthermore, it is very surprising that old-style and new style classes behave exactly the opposite way. In [2]: class a(object) : ...: __class__ = 0 ...: ...: In [3]: a.__class__ Out[3]: <type 'type'> In [4]: a().__class__ Out[4]: 0 In [7]: class a : ...: __class__ = 0 ...: ...: In [8]: a.__class__ Out[8]: 0 In [9]: a().__class__ Out[9]: <class __main__.a at 0xa78cb4ac> -- _____________ Maric Michaud _____________ Aristote - www.aristote.info 3 place des tapis 69004 Lyon Tel: +33 426 880 097 _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com