Question presented to candidate:
"I have a Shape class with chainable setters like set_scale() that return self, and a Circle subclass. If I annotate the setters -> Shape, chaining into a Circle-only method fails type checking. How does typing.Self fix that, and what did people do before it existed?"
What a strong answer should cover:
Self(PEP 673, Python 3.11,typing_extensionsfor older versions) means the type of the instance the method is called on, soCircle().set_scale(2)is aCircle- Annotating
-> "Shape"loses the subclass; the pre-3.11 fix was a TypeVar bound to the class withself: T(andcls: type[T]for classmethods) Selfis equivalent to that bound TypeVar but needs no extra TypeVar, no annotatedself, and works on attributes (next: Self | None), classmethods,__enter__and Protocols- Returning
Selfobliges you to returnself,cls(...)ortype(self)(...):return Shape()is a type error, and runtime confirms it would give the wrong class - Limits: not allowed in static methods or module-level functions;
Selfin a parameter means "the same subclass", which is stricter than the base class
Code / implementation expected: Optional β a small fluent builder or alternative constructor, showing the -> Self annotation and the subclass coming back.