Making Classes Subclassable

Steven D'Aprano steve at pearwood.info
Tue Jul 5 11:41:49 EDT 2016


On Wed, 6 Jul 2016 01:02 am, Ian Kelly wrote:

> On Mon, Jul 4, 2016 at 2:34 AM, Lawrence D’Oliveiro
> <lawrencedo99 at gmail.com> wrote:
>> On Monday, July 4, 2016 at 7:58:07 PM UTC+12, dieter wrote:
>>> --> "type(obj)" or "obj.__class__" (there are small differences)
>>> give you the type/class of "obj".
>>
>> When would it not be the same?
> 
> I think the only remaining difference in Python 3 is that
> obj.__class__ is assignable and type(obj) is not. For most uses,
> type(obj) would be preferred though, in the same way that len(obj) is
> preferable to obj.__len__().


Assigning to __class__ will change the result of type(obj).


py> class A(object):
...     pass
...
py> class B(object):
...     pass
...
py> a = A()
py> type(a)
<class '__main__.A'>
py> a.__class__ = B
py> type(a)
<class '__main__.B'>


This is a deliberate design feature! Provided your classes are designed to
be compatible, you can safely change an instance of class A into an
instance of class B, and then have a.method() correctly call B.method.

(Objective C makes *extensive* use of this technique in Cocoa's standard
library functions, but entirely behind the scenes. Apple's semi-official
stance on this is that they are allowed to do it because the know what
they're doing, but anyone else who tries it is a muppet.)

I don't know what this technique is called, but I'm going to call it
adoption (as opposed to adaption) -- your A instance gets adopted by class
B, after which it behaves like any other B instance.

Again, I stress that A and B must be compatible (and written in Python, you
can't do it with classes written in C), otherwise their methods won't find
the attributes they expect.



-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list