I'm attempting to create algebras in Python, and I'm finding it difficult to create parameterized classes. As an example, consider this ProductWeight class. It holds two other Weight objects, with enforced types (at least statically, via mypy). This will fail because (by design) I cannot access the classes for W1 and W2 to call their classmethods like zero. (They're not specified; ProductWeight is not templated.) ProductWeight doesn't know, when I create an instance, which types to bind to it. from typing import Generic, TypeVar W1 = TypeVar("W1") W2 = TypeVar("W2") class ProductWeight(Generic[W1, W2]): def __init__(self, value1: W1, value2: W2): self.value1_ = value1 self.value2_ = value2 @classmethod def zero(cls): return cls(W1.zero(), W2.zero()) # Will fail - no access to W1 and W2. By contrast, this is straightforward in C++: because the type is parameterized, it is able to look up W1::Zero. template<typename W1, typename W2> public: ProductWeight(W1 w1, W2 w2) : value1_(w1), value2_(w2) {} static ProductWeight Zero() { return ProductWeight(W1::Zero(), W2::Zero()); } private: W1 value1_; W2 value2_; }; Is there a workaround for this in Python? Either creating an inner class, or otherwise somehow providing types to the class (rather than to class instances)? For the sake of a minimal reproducible example, you can use this implementation of another Weight type. class SimpleWeight: def __init__(self, value): assert value in {True, False} self.value_ = value @classmethod def zero(cls): return cls(False) weight1 = SimpleWeight(False) weight2 = SimpleWeight(True) product = ProductWeight(weight1, weight2) print(SimpleWeight.zero()) # So far, so good. print(ProductWeight.zero()) # Oof. # Predictably, it failed because `ProductWeight` is not specialized. And here's the predictable error message: Traceback (most recent call last): File "garbage.py", line 32, in <module> print(ProductWeight.zero()) # Oof. File "garbage.py", line 14, in zero return cls(W1.zero(), W2.zero()) # Will fail - no access to W1 and W2. AttributeError: 'TypeVar' object has no attribute 'zero' Ideally, it would be possible to create a parametric type like this: product = ProductWeight[SimpleWeight, SimpleWeight](weight1, weight2) # And similarly: print(ProductWeight[SimpleWeight, SimpleWeight].zero()) Continue reading...