Skip to content

Instantly share code, notes, and snippets.

@olidroide
Last active September 15, 2022 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olidroide/48a57ba05d9446b8bb85b9bbd4019edd to your computer and use it in GitHub Desktop.
Save olidroide/48a57ba05d9446b8bb85b9bbd4019edd to your computer and use it in GitHub Desktop.
Python Generic generation from typevar Python 3.9.5 tested
from abc import abstractmethod
from typing import TypeVar, Generic, get_args, Type, List
class Fruit:
@abstractmethod
def fruit_name(self) -> str:
raise NotImplementedError
class Apple(Fruit):
def fruit_name(self) -> str:
return self.__class__.__name__
class Leaf:
@staticmethod
def leaf_color():
return "green"
_FruitType = TypeVar("_FruitType", bound=Fruit)
class Tree(Generic[_FruitType], Leaf):
_type_generic: Type[_FruitType]
_fruits: List[_FruitType]
def __init__(self) -> None:
super().__init__()
self._type_generic = get_args(self.__orig_bases__[0])[0] # magic here idea from https://stackoverflow.com/a/71720366/481637
self._fruits = list()
def generate_fruit(self):
self._fruits.append(self._type_generic())
def take_fruit(self) -> _FruitType:
if not self._fruits:
raise NotImplementedError
return self._fruits.pop()
@property
def count_fruits(self) -> int:
return len(self._fruits)
def tree_name(self):
return self.__class__.__name__
class Fuji(Tree[Apple]):
pass
class Person:
@staticmethod
def eat(food: Fruit):
print(f"eating {food.fruit_name()} ñam")
food = None
fuji_apple_tree = Fuji()
print(f"Created {fuji_apple_tree.tree_name()} Tree with {fuji_apple_tree.leaf_color()} color")
# Created Fuji Tree with green color
fuji_apple_tree.generate_fruit()
print(f"{fuji_apple_tree.tree_name()} Tree with {fuji_apple_tree.count_fruits} fruits generated")
# Fuji Tree with 1 fruits generated
fruit = fuji_apple_tree.take_fruit()
person = Person()
person.eat(fruit)
# eating Apple ñam
from abc import abstractmethod
from typing import Type, List
class Fruit:
@abstractmethod
def fruit_name(self) -> str:
raise NotImplementedError
class Apple(Fruit):
def fruit_name(self) -> str:
return self.__class__.__name__
class Leaf:
@staticmethod
def leaf_color():
return "green"
class Tree(Leaf):
_fruits: List[Fruit]
@property
@abstractmethod
def kind_of_fruit(self) -> Type[Fruit]:
raise NotImplementedError
def __init__(self) -> None:
super().__init__()
self._fruits = list()
def generate_fruit(self):
self._fruits.append(self.kind_of_fruit())
def take_fruit(self) -> Fruit:
if not self._fruits:
raise IndexError
return self._fruits.pop()
@property
def count_fruits(self) -> int:
return len(self._fruits)
def tree_name(self):
return self.__class__.__name__
class Fuji(Tree):
@property
def kind_of_fruit(self) -> Type[Apple]:
return Apple
class Person:
@staticmethod
def eat(food: Fruit):
print(f"eating {food.fruit_name()} ñam")
food = None
fuji_apple_tree = Fuji()
print(f"Created {fuji_apple_tree.tree_name()} Tree with {fuji_apple_tree.leaf_color()} color")
fuji_apple_tree.generate_fruit()
print(f"{fuji_apple_tree.tree_name()} Tree with {fuji_apple_tree.count_fruits} fruits generated")
fruit = fuji_apple_tree.take_fruit()
fruit.fruit_name()
person = Person()
person.eat(fruit)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment