# 详解增强算术赋值：“-=”操作是怎么实现的？

## 介绍

Python 有一种叫做增强算术赋值（augmented arithmetic assignment）的东西。可能你不熟悉这个叫法，其实就是在做数学运算的同时进行赋值，例如 a -= b 就是减法的增强算术赋值。

## 剖析-=

# 实现 a -= b 的伪代码
if hasattr(a, "__isub__"):
_value = a.__isub__(b)
if _value is not NotImplemented:
a = _value
else:
a = a - b
del _value
else:
a = a - b


## 归纳这些方法

def _create_binary_inplace_op(binary_op: _BinaryOp) -> Callable[[Any, Any], Any]:

binary_operation_name = binary_op.__name__[2:-2]
method_name = f"__i{binary_operation_name}__"
operator = f"{binary_op._operator}="

def binary_inplace_op(lvalue: Any, rvalue: Any, /) -> Any:
lvalue_type = type(lvalue)
try:
method = debuiltins._mro_getattr(lvalue_type, method_name)
except AttributeError:
pass
else:
value = method(lvalue, rvalue)
if value is not NotImplemented:
return value
try:
return binary_op(lvalue, rvalue)
except TypeError as exc:
# If the TypeError is due to the binary arithmetic operator, suppress
# it so we can raise the appropriate one for the agumented assignment.
if exc._binary_op != binary_op._operator:
raise
raise TypeError(
f"unsupported operand type(s) for {operator}: {lvalue_type!r} and {type(rvalue)!r}"
)

binary_inplace_op.__name__ = binary_inplace_op.__qualname__ = method_name
binary_inplace_op.__doc__ = (
f"""Implement the augmented arithmetic assignment a {operator} b."""
)
return binary_inplace_op


## 我发现几乎没有人使用**=

>>> def test(): a **= b
...
>>> import dis
>>> dis.dis(test)
1           0 LOAD_FAST                0 (a)
2 LOAD_GLOBAL              0 (b)
4 INPLACE_POWER
6 STORE_FAST               0 (a)
8 LOAD_CONST               0 (None)
10 RETURN_VALUE


        case TARGET(INPLACE_POWER): {
PyObject *exp = POP();
PyObject *base = TOP();
PyObject *res = PyNumber_InPlacePower(base, exp, Py_None);
Py_DECREF(base);
Py_DECREF(exp);
SET_TOP(res);
if (res == NULL)
goto error;
DISPATCH();
}


PyObject *
PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
{
if (v->ob_type->tp_as_number &&
v->ob_type->tp_as_number->nb_inplace_power != NULL) {
return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**=");
}
else {
return ternary_op(v, w, z, NB_SLOT(nb_power), "**=");
}
}


posted @ 2020-09-10 22:35  豌豆花下猫  阅读(613)  评论(0编辑  收藏  举报