Python:如何注释操作员dunder方法?

发布于 2025-02-08 09:42:23 字数 1457 浏览 2 评论 0原文

假设我有一个类a支持+操作,以便可以将a的实例添加到其他实例中a,结果是a的另一个实例。例如:

class A:
    ...

    def __add__(self, other):
        if not isinstance(other, A):
            return NotImplemented
        else:
            return A(self._value + other._value)  # or whatever

我应该如何注释该方法?我可以想到三个选择,这对我来说听起来都不好。

所有三个选项的标题

为简单起见,我将使用

from types import NotImplementedType
from typing import Any, Self, overload

。选项1

def __add__(self, other: Self) -> Self:

这就像对我说谎,因为__添加__可能会返回nimplemented。另外(正如评论中提到的Richard Ambler),其他可能不是a的实例,因此不应注释为self

选项2

def __add__(self, other: Any) -> Self | NotImplementedType:

现在,它可以查看a() + a() + a() is a |的类型Checker notimplempledtype,然后在obj = a()+a()之后; f(obj);我会收到一些警告,例如“预期a,但obj可能是notimplemented”。

选项3:

@overload
def __add__(self, other: A) -> Self: ...
@overload
def __add__(self, other: Any) -> Self | NotImplementedType: ...

def __add__(self, other):
   ...  # implementation

我还不能测试这个问题,因为显然Mypy尚未实现self,但这看起来应该很好。但是,这确实比我预期的要多,因为这种功能是相当标准的样板。


有记录的最佳实践吗?这是上述方法之一,还是我没有想到的另一种方法?

Suppose I have a class A with support to the + operation, so that instances of A can be added to other instances of A, and the result is another instance of A. For example:

class A:
    ...

    def __add__(self, other):
        if not isinstance(other, A):
            return NotImplemented
        else:
            return A(self._value + other._value)  # or whatever

How should I annotate that method? I can think of three options, none of which sounds great to me.

Header for all three options

I'll use Python 3.11's Self for simplicity, but that's not important.

from types import NotImplementedType
from typing import Any, Self, overload

Option 1

def __add__(self, other: Self) -> Self:

This feels like lying to me, since it's possible that __add__ will return NotImplemented. Also (as Richard Ambler mentioned in the comments), other might not be an instance of A, and therefore shouldn't be annotated as Self.

Option 2

def __add__(self, other: Any) -> Self | NotImplementedType:

Now, it looks to the type checker that the type of A() + A() is A | NotImplementedType, and then after obj=A()+A(); f(obj); I would get some warnings like "expected an A but obj might be NotImplemented".

Option 3:

@overload
def __add__(self, other: A) -> Self: ...
@overload
def __add__(self, other: Any) -> Self | NotImplementedType: ...

def __add__(self, other):
   ...  # implementation

I can't test this yet because apparently mypy hasn't implemented Self, but this looks like it should work fine. However, it does feel way more verbose than I expected it to be, since this functionality is honestly quite standard boilerplate.


Is there a documented best practice? Be it one of the above methods, or another one I haven't thought of?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文