In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains the "Python arithmetic assignment-= operation is how to achieve", the article explains the content is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in-depth, together to study and learn "arithmetic assignment-= operation in Python is how to achieve" it!
Introduction
Python has something called enhanced arithmetic assignment (augmented arithmetic assignment). Maybe you are not familiar with this term, which is actually assigning values while doing mathematical operations. for example, a-= b is the enhanced arithmetic assignment of subtraction.
Enhanced assignments are added in the Python 2.0 version.
Analyze-=
Because Python does not allow overlay assignments, it may not implement enhanced assignments in exactly the same way as you might think compared to other operations with special / magic methods.
First of all, it is important to know that a-= b is semantically the same as a = a-murb. But also be aware that if you know in advance that you want to assign an object to a variable name, it may be more efficient than the blind operation of a-b.
For example, the minimum benefit is that you can avoid creating a new object: if you can modify an object in place, then returning self is more efficient than constructing a new object.
Therefore, Python provides a _ _ isub__ () method. If it is defined on the left side of the assignment operation (usually called lvalue), the value on the right side (usually called rvalue) is called. So for a-= b, an attempt is made to call a. Compare _ (b).
If the result of the call is NotImplemented, or if there is no result at all, Python returns to the regular binary arithmetic operation: a-b. (translation note: the author's article on binary operation, the translation is here)
In the end, no matter which method is used, the return value is assigned to a.
Here is a simple pseudo-code, a-= b is broken down into:
# implement pseudocode if hasattr (a, "_ _ isub__") of a-= b: _ value = a.roomisubcodes _ (b) if _ value is not NotImplemented: a = _ value else: a = a-b del _ value else: a = a-b
Sum up these methods
Because we have implemented the binary arithmetic operation, the inductive enhanced arithmetic operation is not too complicated.
By passing in binary arithmetic functions and doing some introspection (and dealing with possible TypeError), it can be beautifully summarized as follows:
Def _ create_binary_inplace_op (binary_op: _ BinaryOp)-> Callable [[Any, Any], Any]: binary_operation_name = binary_op.__name__ [2BinaryOp 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 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}: {and (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
This makes the defined-= support _ create_binary_inplace_op (_ _ sub__), and other things can be inferred: the name of the function, what function is called, and which callable object should be called if there is a problem with the binary arithmetic.
I find that few people use *.
While writing the code for this article, I encountered a strange test error of *. Of all the tests that ensure that _ _ pow__ is invoked properly, one test case fails for the operator module in the Python standard library.
My code is usually fine, and if there is a difference between the code and the CPython code, it usually means that there is something wrong with me.
However, no matter how carefully I examined the code, I couldn't figure out why my test passed and the standard library failed.
I decided to learn more about what was going on inside CPython. Start with disassembling bytecodes:
> 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
Through it, I found the INPLACE_POWER in the eval loop:
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 ();}
Source: https://github.com/python/cpython/blob/v3.8.3/Python/ceval.c#L1677
Then find PyNumber_InPlacePower ():
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), "* * =");}}
Sigh of relief ~ the code shows that it will be called if _ _ ipow__, is defined, but _ _ pow__ will only be called if there is no _ _ ipow__.
However, the right thing to do is that if there is a problem calling _ _ ipow__, NotImplemented is returned or there is no return at all, then _ _ pow__ and _ _ rpow__ should be called.
In other words, the above code accidentally skips the fallback semantics of a _ _ ipow__ when it exists!
In fact, about 11 months ago, the problem was partially discovered and submitted to bug. I fixed the problem and explained it on python-dev.
As of now, this seems to be fixed in Python 3.10, and we also need to add a notification of * * = bug in the documentation of 3.8and 3.9 (this problem may have been around for a long time, but older versions of Python are in security-only maintenance mode, so the documentation will not change).
The fixed code will probably not be migrated because it is a semantic change, and it is difficult to determine whether anyone has accidentally relied on problematic semantics. But the problem took a long time to notice, which shows that the use of * is not widespread, otherwise the problem would have been discovered long ago.
Thank you for your reading, the above is the "Python arithmetic assignment-= operation is how to achieve" content, after the study of this article, I believe you on the Python arithmetic assignment-= operation is how to achieve this problem has a deeper understanding, the specific use of the need for everyone to practice and verify. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.