Skip to content

overloading __new__ #3307

@Rouslan

Description

@Rouslan

I propose allowing the use of @overload on __new__ to specify the return type. E.g.:

T = TypeVar('T')

class MyClass(Generic[T]):
    @overload
    def __new__(cls,val: str) -> 'MyClass[int]':
        pass
    @overload
    def __new__(cls,val: int) -> int:
        pass
           
    def __new__(cls,val):
        if isinstance(val,int):
            return val
        r = super().__init__(cls)
        if isinstance(val,str):
            r.val = int(val)
        r.val = val
        return r

Then, if @overload is allowed to have return types that only differ by the generic type argument (e.g. MyClass[int] vs MyClass[str]), this would allow specifying default type arguments (which is already requested in python/typing#307) as well as more complicated type argument deduction, such as when a certain type gets cast to another type (not with the cast function but like in the above code with str to int).

And if this is allowed, I don't see why it shouldn't be permissible to specify a return type that isn't an instance of the containing class. This is not essential, but it's something Python allows. I have used it for automatically simplifying expressions in a domain-specific language and SymPy does this with symbolic math:

>>> from sympy import *
>>> x = Symbol('x')
>>> Pow
<class 'sympy.core.power.Pow'>
>>> type(Pow(x,1))
<class 'sympy.core.symbol.Symbol'>

In such cases, it might be useful to mark the class return type as a super-class of itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions