在 `int` 子类的 `__new__` 方法中出现了意外的类型警告。

huangapple go评论62阅读模式
英文:

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

问题

以下是翻译好的部分:

以下是翻译好的部分

以下代码
```python
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)

在PyCharm中产生警告:“期望类型为'str | bytes | bytearray',但实际为'int'”在最后一行的x上。

为什么会这样?

如果我评估super(Size, cls).__new__ == int.__new__,结果是True。这不也期望一个int吗?

如果我想在首次分配值或将某个值强制转换为此类型时添加行为,是否有更好的方法来创建int的子类?

这样的类的具体示例是class Size(int),可以实例化为Size(1024)Size('1 KiB'),结果相同。


<details>
<summary>英文:</summary>

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): &quot;`Expected type &#39;str | bytes | bytearray&#39;, got &#39;int&#39; instead`&quot; on `x` in the last line.

Why is this?

If I evaluate `super(Size, cls).__new__ == int.__new__`, the result is `True`. Wouldn&#39;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(&#39;1 KiB&#39;)`, with the same result.

</details>


# 答案1
**得分**: 2

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

```python
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
英文:

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

int(x:int = 0) -&gt; int:
int(x:str, base: int = 10) -&gt; 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(&quot;2&quot;))
2
42

huangapple
  • 本文由 发表于 2023年5月26日 09:22:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76337109.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定