0

What is the purpose of subclassing an instance of a class in Python? Here's an example:

class A:
    def __init__(*args): print(args) 

base = A() 


class Test(base): pass 

This code works properly under Python, but base is an instance of class A (1) Why do we need to subclass an instance of a class? Is it related to metaclasses?

From this question: What happens when you inherent from a module instead of a class in Python?

I understand that Test(base) will become type(base).__init__, (2) does this happen at definition time, when the class is defined? (3) How does Python know/decide that base is an instance of a class? Is it becuase type(base) doesn't return type?

Community
  • 1
  • 1
GIZ
  • 4,409
  • 1
  • 24
  • 43
  • 3
    Do you have an actual piece of production code that does this or is this just curiosity? – Martijn Pieters Sep 06 '16 at 19:42
  • Curiosity and the desire to make a rational thinking of a feature :-) – GIZ Sep 06 '16 at 19:43
  • 1
    And no, `Test(base)` does not become `type(base).__init__`. It becomes `type(base).__new__`, which in turn can call `__init__`. And yes, that's because of metaclasses. – Martijn Pieters Sep 06 '16 at 19:44
  • Since this belongs to metaclasses, this means `type(base).__init__` takes place during class definition, isn't it? And `__init__` of the returned object by `__new__` gets called. – GIZ Sep 06 '16 at 19:52
  • 3
    "What is the purpose..." - not everything you can do has a purpose. You might as well ask on cooking.stackexchange.com what the purpose of putting pizza in a blender is. – user2357112 Sep 06 '16 at 19:53
  • @user2357112 you can edit the title if you don't find it meaningful. – GIZ Sep 06 '16 at 19:55
  • 2
    `b=Test()` produces a TypeError ` 'A' object is not callable`. – hpaulj Sep 06 '16 at 20:22

1 Answers1

1

Python actually uses type(base)(classname, bases, body) to produce the class object. This is the normal metaclass invocation (unless the class specifies a specific metaclass directly).

For an instance (or a module, which is basically an instance too), that means the class __new__ static method is called to produce a new instance, and on that new instance __init__ is called. So for your class Test(base): pass syntax, you are essentially creating a new instance of A, when Python executes the class statement.

This isn't really 'definition time'; there is no such phase in Python code. Python loads the bytecode for a module and executes it when it is imported for the first time. Class statements at the top of the module (so not inside functions) are executed at that time. It is at that time then that the type(base)(...) call is executed, yes.

Python doesn't 'know' or 'decide' anything about the base class. Python's philosophy is to trust the developer that writes code in it. The assumption is that you know what you are doing, and the base classes are just treated as if they'll respond correctly. Since type(base)(....) didn't raise an exception, Python just continued.

You can use anything that's callable as a metaclass, really.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343