Is there a way in python to restrict generic types to ones that can be instantiated?
I'm looking for an equivalent to C#'s
where T : new()
I am already using type hints as follows
T = TypeVar("T", bound=Button)
And I'd like to know if there something like
T = TypeVar("T", bound=Button,new())
For example, given that Button is an abstract class (ABC) this code should create a menu composed of any subtype of Button
class Button(ABC):
def __init__(self) -> None:
self._name = ""
@abstractmethod
def show(self) -> None:
pass
def set_name(self, value:str) -> None:
self._name = value
class SquareButton(Button):
def show(self) -> None:
print("[",self._name,"]")
class CircleButton(Button):
def show(self) -> None:
print("(",self._name,")")
T = TypeVar("T", bound=Button) # restricting type here
class MenuBuilder:
def build(self,class_type: Type[T]) -> None:
pb1: Button = class_type()
pb2: Button = class_type()
pb3: Button = class_type()
pb1.set_name("button1")
pb2.set_name("button2")
pb3.set_name("button3")
pb1.show(); pb2.show(); pb3.show()
#main
mb: MenuBuilder = MenuBuilder()
mb.build(Button) # fails at run time - I want a pre-run error here
mb.build(CircleButton) # OK
As it stands now, it allows calling the method with an abstract type Button, which fails at run time when I try to create instances of it.
I am using python 3.8.1 and VS Code with pylance
Edit: One of the answers suggested replacing the Generics by Protocol to make sure Buttons functions were implemented. While this prevents sending the abstract class, it allows sending classes that don't inherit from Button. I'm looking for away to enforce both restrictions.
mypy
will raise an error here – Luge