Since Python 3.5 you can use Generics and other interesting stuff described in PEP-0484. I tried that and here's a code I have:
from typing import TypeVar, Generic, Optional
...
_T = TypeVar('T')
_S = TypeVar('S')
class Pool(Generic[_S, _T]):
def __init__(self) -> None:
self.pool = dict()
... getters and setters here...
This code works perfectly and does what is expected. Then I decided to extend this class to make some additional work. That's how I did that:
class PoolEx(Pool[_S, _T]):
ARGUMENTS = []
def __init__(self) -> None:
print("self=", self, self.__class__.__bases__)
super(PoolEx, self).__init__()
self.arguments_pool = dict()
... other code here ...
To test Pool
class I created MyPool
which looked like this:
class MyPool(Pool[str, Hello]):
pass
Then I put something like mypool = MyPool()
and it worked fine. Once I implemented PoolEx
, I've updated MyPool
to this:
class MyPool(PoolEx[str, Hello]):
ARGUMENTS = ['name', 'surname']
And tried to do the same thing: mypool = MyPool()
. Unfortunately I got:
self= <__main__.MyPool object at 0x1068644e0> (__main__.PoolEx[str, __main__.Hello],)
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/8bitjoey/.../utils/pool.py", line 141, in <module>
mypool = MyPool()
File "/Users/8bitjoey/.../utils/pool.py", line 52, in __init__
super(PoolEx, self).__init__()
TypeError: super(type, obj): obj must be an instance or subtype of type
As you can see, I also put self.__class__.__bases
to the log. When I tried to test isinstance(self, PoolEx)
and similar with issubclass
, I got False. Same as super()
verifications.
Is it something with my code or such classes can't have descendants? And if I still want to have PoolEx I have to use composition rather than inheritance.
You cannot inherit a generic type. // class Derived20 : T {}// NO!
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.
In Python a class can inherit from more than one class. If a class inherits, it has the methods and variables from the parent classes. In essence, it's called multiple inheritance because a class can inherit from multiple classes. This is a concept from object orientated programming.
The function isinstance() returns True if the object is an instance of the class or other classes derived from it. Each and every class in Python inherits from the base class object .
Well, just for the record, I have just run your code on Python 3.8.10, and I've got no errors. It runned perfectly. Then I've pulled the docker image python:3.5.0 from Docker Hub and run it again, and then I've got your exact same error:
TypeError: super(type, obj): obj must be an instance or subtype of type
So it seems to have been and issue with the first implementations of such features, which have already been fixed in latest versions.
Here follows the file I used for testing, in case anyone will ever be interested in reproduce any similar errors:
from typing import TypeVar, Generic, Optional
_T = TypeVar('T')
_S = TypeVar('S')
class Pool(Generic[_S, _T]):
def __init__(self) -> None:
self.pool = dict()
class PoolEx(Pool[_S, _T]):
ARGUMENTS = []
def __init__(self) -> None:
print("self=", self, self.__class__.__bases__)
super(PoolEx, self).__init__()
self.arguments_pool = dict()
class MyPool(Pool[str, int]):
pass
mypool = MyPool()
class MyPool(PoolEx[str, int]):
ARGUMENTS = ['name', 'surname']
mypool2 = MyPool()
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