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

77 views Asked by At

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.

1

There are 1 answers

4
flakes On BEST ANSWER

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