pythonsubclassing

Unexpected type warning in `__new__` method for `int` subclass


The following code:

class Foo(int):
    def __new__(cls, x, *args, **kwargs):
        x = x if isinstance(x, int) else 42
        
        return super(Foo, cls).__new__(cls, x, *args, **kwargs)

Results in a warning (in PyCharm): "Expected type 'str | bytes | bytearray', got 'int' instead" on x in the last line.

Why is this?

If I evaluate super(Size, cls).__new__ == int.__new__, the result is True. Wouldn't that expect an int as well?

Is there a better way to create a subclass of int, if I want to add behaviour when a value is first assigned or some value is cast to this type?

A concrete example of such a class would be a class Size(int) that could be instantiated as Size(1024) or Size('1 KiB'), with the same result.


Solution

  • The overload of int with multiple args takes a string as the first param. It is roughly equivalent to

    int(x:int = 0) -> int:
    int(x:str, base: int = 10) -> int:
    

    You are providing __new__(cls, x, *args, **kwargs), so it is expecting that there should be a string as the first param.

    So for this to not complain, drop the extra args:

    class Foo(int):
        def __new__(cls, x):
            x = x if isinstance(x, int) else 42
            return super(Foo, cls).__new__(cls, x)
    
    
    print(Foo(2))
    print(Foo("2"))
    
    2
    42