I'm just curious what will happen when I inherit an instance into a class.
So I tried:
class X:
def __init__(self, x):
self.x = x
def print(self):
print(self.x)
def inherit(obj):
class Child(obj): # Line 20
pass # or maybe added functionality
return Child
param = 5
x = X(param)
y = inherit(x) # Line 27
y.print()
I get (at least) the following error:
Traceback (most recent call last):
File "/test.py", line 27, in <module>
y = inherit(x)
File "/test.py", line 20, in inherit
class Child(obj):
TypeError: __init__() takes 2 positional arguments but 4 were given
I just wonder: Is inheriting an instance anything meaningful/useful or just plain nonsense?
(The question is a bit academic and specifically about the details of inheriting an instance. It's not about alternatives like object delegation or general design practices.)
Inheritance is a required feature of every object oriented programming language. This means that Python supports inheritance, and as you'll see later, it's one of the few languages that supports multiple inheritance.
Inheritance is a powerful feature in object oriented programming. It refers to defining a new class with little or no modification to an existing class. The new class is called derived (or child) class and the one from which it inherits is called the base (or parent) class.
Inheritance allows us to define a class that inherits all the methods and properties from another class. Parent class is the class being inherited from, also called base class. Child class is the class that inherits from another class, also called derived class.
A class can be derived from more than one base class in Python, similar to C++. This is called multiple inheritance.
Classes are just like instances; they have a type. For instances that type is the class, but for classes, the type is called a metaclass. Inheriting from a class normally would call the metatype of the base class to produce a new class object (using type(base)
; for multiple bases restrictions apply). The standard metatype is the type
object, but you can create your own metaclasses.
By inheriting from an instance, Python tries to create a new class by calling type(obj)(classname, bases, body_namespace)
. Since type(obj)
is X
and X.__init__()
doesn't support those arguments, the call fails. However, there is nothing stopping you from making that part work!
>>> class X:
... def __init__(self, classname, parents, namespace):
... print('Creating {}{}'.format(classname, parents))
...
>>> class Child(X('X', (), {})): pass
...
Creating X()
Creating Child(<__main__.X object at 0x10372b4a8>,)
>>> Child
<__main__.X object at 0x10372b470>
>>> Child()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'X' object is not callable
Of course, type
provides a lot more functionality that a class won't offer out of the box; there are a series of descriptors to provide attributes on a class that other parts of Python expect to exist. Your class would have to cover all of those instead; in the above sample output, you'll note that repr(Child)
produces <__main__.X object at 0x...>
rather than the expected <class '__main__.Child'>
, and there is no __call__
method to produce instances for the class. So using an instance as a base class for another can work, you just have to put in the extra work to define all that expected functionality.
In the end, using an instance as a base class may be possible, but has no practical uses, not when any of the use-cases are already covered by metaclasses instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With