覆盖“”=” 在Python中? (__iadd__() 方法)

发布于 2024-07-25 01:46:02 字数 24 浏览 3 评论 0原文

是否可以在Python中重写+=?

Is it possible to override += in Python?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

琴流音 2024-08-01 01:46:02

是的,覆盖 __iadd__< /a> 方法。 例子:

def __iadd__(self, other):
    self.number += other.number
    return self    

Yes, override the __iadd__ method. Example:

def __iadd__(self, other):
    self.number += other.number
    return self    
時窥 2024-08-01 01:46:02

除了上面答案中正确给出的内容之外,值得明确澄清的是,当覆盖 __iadd__ 时,x += y 操作不会以 的结尾结束>__iadd__ 方法。

相反,它以 x = x.__iadd__(y) 结尾。 换句话说,Python 在实现完成后将 __iadd__ 实现的返回值分配给您要“添加到”的对象。

这意味着可以改变 x += y 操作的左侧,从而导致最终的隐式步骤失败。 考虑一下当您添加到列表中的内容时会发生什么:

>>> x[1] += y # x 有两个项目

现在,如果您的 __iadd__ 实现(x[1] 处对象的方法)错误或故意从列表开头删除第一项 (x[0]),然后 Python 将运行您的 __iadd__ 方法) & 尝试将其返回值分配给x[1]。 它将不再存在(它将位于 x[0]),从而导致 ÌndexError

或者,如果您的 __iadd__ 在上例的 x 开头插入一些内容,您的对象将位于 x[2],而不是 x[1],之前位于 x[0] 的内容现在将位于 x[1] 并被赋予 x[0] 的返回值code>__iadd__ 调用。

除非人们了解正在发生的事情,否则所产生的错误可能会是一场难以修复的噩梦。

In addition to what's correctly given in answers above, it is worth explicitly clarifying that when __iadd__ is overriden, the x += y operation does NOT end with the end of __iadd__ method.

Instead, it ends with x = x.__iadd__(y). In other words, Python assigns the return value of your __iadd__ implementation to the object you're "adding to", AFTER the implementation completes.

This means it is possible to mutate the left side of the x += y operation so that the final implicit step fails. Consider what can happen when you are adding to something that's within a list:

>>> x[1] += y # x has two items

Now, if your __iadd__ implementation (a method of an object at x[1]) erroneously or on purpose removes the first item (x[0]) from the beginning of the list, Python will then run your __iadd__ method) & try to assign its return value to x[1]. Which will no longer exist (it will be at x[0]), resulting in an ÌndexError.

Or, if your __iadd__ inserts something to beginning of x of the above example, your object will be at x[2], not x[1], and whatever was earlier at x[0] will now be at x[1]and be assigned the return value of the __iadd__ invocation.

Unless one understands what's happening, resulting bugs can be a nightmare to fix.

二货你真萌 2024-08-01 01:46:02

除了重载 __iadd__(记住返回 self!)之外,您还可以回退到 __add__,因为 x += y 的工作方式类似于 x = x + y。 (这是 += 运算符的陷阱之一。)

>>> class A(object):
...   def __init__(self, x):
...     self.x = x
...   def __add__(self, other):
...     return A(self.x + other.x)
>>> a = A(42)
>>> b = A(3)
>>> print a.x, b.x
42 3
>>> old_id = id(a)
>>> a += b
>>> print a.x
45
>>> print old_id == id(a)
False

它甚至 让专家困惑

class Resource(object):
  class_counter = 0
  def __init__(self):
    self.id = self.class_counter
    self.class_counter += 1

x = Resource()
y = Resource()

您期望 x.idy.idResource 的值是什么.class_counter 有吗?

In addition to overloading __iadd__ (remember to return self!), you can also fallback on __add__, as x += y will work like x = x + y. (This is one of the pitfalls of the += operator.)

>>> class A(object):
...   def __init__(self, x):
...     self.x = x
...   def __add__(self, other):
...     return A(self.x + other.x)
>>> a = A(42)
>>> b = A(3)
>>> print a.x, b.x
42 3
>>> old_id = id(a)
>>> a += b
>>> print a.x
45
>>> print old_id == id(a)
False

It even trips up experts:

class Resource(object):
  class_counter = 0
  def __init__(self):
    self.id = self.class_counter
    self.class_counter += 1

x = Resource()
y = Resource()

What values do you expect x.id, y.id, and Resource.class_counter to have?

呆橘 2024-08-01 01:46:02

http://docs.python.org/reference/datamodel.html#emulated -数字类型

例如执行语句
x += y,其中 x 是 a 的实例
具有 __iadd__() 方法的类,
x.__iadd__(y) 被调用。

http://docs.python.org/reference/datamodel.html#emulating-numeric-types

For instance, to execute the statement
x += y, where x is an instance of a
class that has an __iadd__() method,
x.__iadd__(y) is called.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文