I need to implement a bunch classes, that all need to do the same modification to the parent class. As a skilled C programmer, I would look for a template class. But this needs to be implemented in Python. Here I am a rookie. I found the "Generic" and has constructed this example to show the core in my problem. The real program is somewhat more complicated(using ReportLab to generate PDF documents). I need to subclass to benefit from the class framework, which leads me into trying to implement a Generic using inheritance.
The problem is that cannot understand how I can pass argument to the "super" class, which here I try to make a Generic.
First attempt:
super().__init__(*argv, **kwargs)
Second attempt:
super(G, self).__init__(*argv, **kwargs)
Third attempt:
T.__init__(*argv, **kwargs)
Here is the complete example:
from typing import Generic, TypeVar
class A():
def __init__(self, i : int):
self.i = i
def draw():
print(self.i)
class C():
def __init__(self, s : str):
self.s = s
def draw():
print(self.s)
T = TypeVar('T')
class G(Generic[T]):
def __init__(self, *argv, **kwargs):
super().__init__(*argv, **kwargs)
def draw():
# Here is some special going to happen
super().draw()
gA = G[A](5)
gB = G[B]('Hello')
gA.draw()
gB.draw()
The output that I get:
Traceback (most recent call last):
File "<string>", line 34, in <module>
File "/usr/lib/python3.8/typing.py", line 729, in __call__
result = self.__origin__(*args, **kwargs)
File "<string>", line 28, in __init__
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
CodePudding user response:
You have understood Python generics wrong. A Generic, say Generic[T]
, makes the TypeVar
T
act as whatever you provide the instance with.
I found this page to be very useful with learning Generics.
CodePudding user response:
typing.Generic
is specifically for type annotations; Python provides no runtime concept equivalent to either:
- Template classes, or
- Function overloads by parameter count/type
The latter has extremely limited support from functools.singledispatch
, but it only handles the type of one argument, and the runtime type-checking is fairly slow.
That said, you don't need a template-based class or a polymorphic inheritance hierarchy here; Python is perfectly happy to call draw
on anything that provides a method of that actual name. The code you're writing here can just do:
a = A(5)
b = B('Hello')
a.draw()
b.draw()
with no use of G
needed.