4

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)

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the link looks promising..
1

typing.Generic is specifically for type annotations; Python provides no runtime concept equivalent to either:

  1. Template classes, or
  2. 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.

3 Comments

It is the ReportLab library that forces me into wanting this template like construct. I need to create a new subclass that does the exact same as super but just rotate the canvas beforehand. I'll have to see if I can find another way around the problem. Thanks for your clarifications.
@PaulGroskopf: Would it be practical to write a mix-in class that both A and B inherit from, and have both A and B invoke super().draw() before doing the rest of their work? If super() is used consistently, even a diamond inheritance hierarchy would work (for classes Mix, A(Mix), and B(Mix), and C(A, B) where each draw invokes super().draw() before doing their own thing [LIFO invocation order] would end up calling C.draw,A.draw,B.draw,Mix.draw in that order, but the LIFO order would do the work Mix first, then B, then A, then C).
That looks like how I ended up doing it. I made a common super class. And then added a parameter to control what I needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.