python中增强算术赋值是什么

  介绍

小编给大家分享一下python中增强算术赋值是什么,希望大家阅读完这篇文章后大所收获、下面让我们一起去探讨吧!

介绍

python有一种叫做<代码>增强算术赋值>

增强赋值是在python 2.0版本中加入进来的。(译注:在pep - 203中引入)

剖析<代码> -=

因为python不允许覆盖式赋值,所以相比其它有特殊/魔术方法的操作,它实现增强赋值的方式可能跟你想象的不完全一样。

首先,要知道<代码> a - b=> =a - b> a - b>

例如,最起码的好处是可以避免创建一个新对象:如果可以就地修改一个对象,那么返回自我,就比重新构造一个新对象要高效。

因此,python提供了一个__isub__()方法。如果它被定义在赋值操作的左侧(通常称为左值),则会调用右侧的值(通常称为右值)。所以对于<代码> a - b=>

如果调用的结果是NotImplemented,或者根本不存在结果,那么python会退回到常规的二元算术运算:<代码> a - b>

最终无论用了哪种方法,返回值都会被赋值给一个。

下面是简单的伪代码,<代码> a - b=>

 #实现-=b的伪代码如果hasattr (a,“__isub__"):
  _value=https://www.yisu.com/zixun/a.__isub__ (b)如果没有NotImplemented _value:
  一个=_value别的:=- b del _value别的:
  a=a - b复制代码

归纳这些方法

由于我们已经实现了二元算术运算,因此归纳增强算术运算并不太复杂。

通过传入二元算术运算函数,并做一些自省(以及处理可能发生的TypeError),它可以被漂亮地归纳成:

 def _create_binary_inplace_op (binary_op: _BinaryOp)→可调用的[[,],):
  
  binary_operation_name=binary_op.__name__ [2: 2]
  method_name=f" __i {binary_operation_name} __"
  运算符=f" {binary_op._operator}=?
  
  def binary_inplace_op(左值:右值:任何,/)→任何:
  lvalue_type=类型(左值)试题:=debuiltins方法。除了AttributeError _mro_getattr (lvalue_type method_name):通过
  其他:
  价值=https://www.yisu.com/zixun/method(左值,右值)如果价值并非NotImplemented:试题:返回值返回binary_op(左值,右值)除了TypeError exc: #如果TypeError由于二进制算术运算符,抑制
  #它我们可以适当提高>祝辞祝辞祝辞def测试():* *=b…在在在进口dis>在祝辞dis.dis LOAD_FAST(测试)1 0 0 (a) 2 LOAD_GLOBAL 0 (b) 4 INPLACE_POWER 6 STORE_FAST 0 (a) 8 LOAD_CONST 0(无)10 RETURN_VALUE复制代码

通过它,我找到了在eval循环中的<代码> INPLACE_POWER :

案例目标(INPLACE_POWER): {   PyObject * exp=POP ();   PyObject *基?最高();   PyObject * res=PyNumber_InPlacePower(基础、实验、Py_None);   Py_DECREF(基地);   Py_DECREF (exp);   SET_TOP (res);如果(res==NULL)转到错误;   调度();   }复制代码

出处:github.com/python/cpyt…

然后找到<代码> PyNumber_InPlacePower() :

 PyObject * PyNumber_InPlacePower (PyObject * v, PyObject * w, PyObject * z){如果(v→ob_type→tp_as_number,,
  v→ob_type→tp_as_number→nb_inplace_power !=NULL){返回ternary_op (v, w、z NB_SLOT (nb_inplace_power),“* *=?;
  其他}{返回ternary_op (v, w、z NB_SLOT (nb_power),“* *=?;
  }
  }复制代码

出处:github.com/python/cpyt…

松了口气~代码显示如果定义了__ipow__,则会调用它,但是只在没有__ipow__时,才会调用__pow__。

然而,正确的做法应该是:<>强如果调用__ipow__时出问题,返回了NotImplemented或者根本不存在返回,那么就应该调用__pow__和__rpow__。

换句话说,当存在__ipow__时,以上代码会意外地跳过* * b的后备语义。

实际上,大约11个月前,这个问题被部分地发现,并提交了错误。我修复了该问题,并在python-dev上作了说明。

截至目前,这似乎会在Python 3.10中修复,我们还需要在3.8和3.9的文档中添加关于* *=有bug的通知(该问题可能很早就有了,但较旧的Python版本已处于仅安全维护模式,因此文档不会变更)。

修复的代码很可能不会被移植,因为它是语义上的变化,并且很难判断是否有人意外地依赖了有问题的语义。但是这个问题花了很长时间才被注意到,这就表明* *=的使用并不广泛,否则问题早就被发现了。

python中增强算术赋值是什么