Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”. This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
Just today (6/10/2021), Python officially released Python 3.10.0 and Python 3.11.0A1 Alpha. I’ve gone through tens of thousands of words of Python documentation and PEPs to boil it down to this article.
Hello, I am a sheep in Wolf’s skin. Today I will introduce you to the new features in Python 3.10 and Python 3.11.
More intuitive error messages
A small arrow that identifies the error
In the new version of Python, the indicator arrows are now more accurate at locating errors:
Python 3.9 | Python 3.10 |
---|---|
>>> foo(x, z for z in range(10), t, w)
|
>>> foo(x, z for z in range(10), t, w)
|
SyntaxError
SyntaxError can also give more detailed error information depending on the cause of the problem, rather than just invalid syntax.
Python 3.9 | Python 3.10 |
---|---|
>>> if True
|
>>> if True
|
>>> while a = b:
|
>>> while a = b:
|
>>> {x, y for x, y in zip('abcd', '1234')}
|
>>> {x, y for x, y in zip('abcd', '1234')}
|
NameError
和 AttributeError
When the property/variable is not found, PyErr_Display() prints suggestions for similar property/variable names:
Python 3.9 | Python 3.10 |
---|---|
>>> import collections
|
>>> import collections
|
This is a useful feature for Notepad programmers (as long as the words aren’t spelled too badly).
Postscript:
Take a look at the error message above:
f'module {__name__! r} has no attribute {name! r} Copy the code
It took so long to use the F-string, but! R this is the first time I’ve seen it. I looked it up on the Internet and it turns out it stands for repr(__name__).
This is a syntax candy in Python, which is useless.
For more f-string tips, see this Medium post.
New feature on Type Hints
To annotate a parameter that can be an int or float, we did this earlier:
from typing import Union
def add_one(num: Union[int.float]) - >Union[int.float] :
return num + 1
Copy the code
Python 3.10 introduced a set of new type and operator (type the union operator), the syntax for X | Y:
def add_one(num: int | float) - >int | float:
return num + 1
Copy the code
Typing.Union is expected to be phased out in some future version…
This syntax also applies to isinstace() and issubclass() :
>>> isinstance(1.int | str)
True
Copy the code
Structured pattern matching – match-case statement
Big update! Python supports switch-case match-case.
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
Copy the code
The match statement compares the Subject expression to each pattern in the case statement from top to bottom until a matching pattern is found. If no matching expression is found, match the wildcard (if any), which is actually the default keyword in other languages.
Example:
def http_error(status) :
match status:
case 400:
print("Bad request")
case 404:
print("Not found")
case 418:
print("I'm a teapot")
case _:
print("Something's wrong with the internet")
Copy the code
In my opinion, Python’s match-case has several features compared to switch-case in other languages:
-
The break keyword is not required
Since Python stops after a match, we can’t (which would throw a SyntaxError) nor do we have to write a break at the end of each case block. Does this mean we can’t stack multiple cases like other languages do?
switch(status) { case 401: case 403: case 404: System.out.println("Not allowed"); break; default: System.out.println("Something's wrong with the internet")}Copy the code
It’s not. | we can use to combine multiple mode (this is the only support in pattern matching operator) :
match status: case 401 | 403 | 404: print("Not allowed") case _: print("Something's wrong with the internet")}Copy the code
Straightforward, very Pythonic!
-
A variety of patterns
The following modes are supported:
-
Literal constants pattern
Such as int, float, string, bool, and None, but not f-string, which is not a literal constant.
Note that we cannot treat values in variables as matching patterns:
FULL_SCORE = 100 my_score = 20 match my_score: case FULL_SCORE: print("Congratulations!") print(FULL_SCORE) The value of # FULL_SCORE has been changed to 20 Copy the code
Match-case treats this as capture mode (mentioned below) and assigns my_score to FULL_SCORE.
-
Capture pattern, as the assignment target of the matching expression, example:
match greeting: case "": print("Hello!") case name: print(f"Hi {name}!") if name == "Santa": # <-- UnboundLocalError may be thrown.This is ok when greeting is not empty Copy the code
A name can be bound at most once when matching each case clause, and it is an error to have two capture patterns with overlapping names:
match data: case [x, x]: # SyntaxError: multiple assignments to name 'x' in pattern.Copy the code
-
Wildcard mode
_ is not used as a variable name here, but as a special pattern. It always matches but never binds values:
match data: case [_, _]: print("Some pair") print(_) # NameError: name '_' is not defined Copy the code
Note: if you use a variable named _ above it, no error will be thrown, but the value you get is the same as the value you set earlier, so don’t confuse it with ~
-
Constant value pattern
Properties and enumeration classes (enum.Enum) can also be used as schemas, which is not explained here.
-
Sequence pattern sum
-
Mapping mode
Lists, tuples, dict, etc. can all be used as patterns and can be used with * or ** and wildcards, such as:
[* _]
Matches any lengthlist
;* _) (_, _,
Matches at least length 2tuple
.
-
Class model
Without further ado, here are some examples:
class Point: x: int y: int def location(point) : match point: case Point(x=0, y=0) :print("Origin is the point's location.") case Point(x=0, y=y): print(f"Y={y} and the point is on the y-axis.") case Point(x=x, y=0) :print(f"X={x} and the point is on the x-axis.") case Point(): print("The point is located somewhere else on the plane.") case _: print("Not a point") Copy the code
This pattern can also be used with wildcards, for example:
Sandwich(cheese=_)
Checks whether the matched object has attributescheese
.
-
-
If clause in case block
We can add an if clause to the pattern called guard. Even if the pattern matches, if Guard is False, match will continue to attempt to match the next case block.
match point: case Point(x, y) if x == y: print(f"The point is located on the diagonal Y=X at {x}.") case Point(x, y): print(f"Point is not on the diagonal.") Copy the code
New/optimized functions and modules
newint.bit_count
A new method in int that returns the number of 1’s in the binary expansion of a given integer. Example:
>>> n = 19
>>> bin(n)
'0b10011'
>>> n.bit_count()
3
>>> (-n).bit_count()
3
Copy the code
zip()
Added optional arguments to built-in functionsstrict
The strict argument (default False) is used to ask the zip() function to check whether the lengths of iterables are the same and raise ValueError if they are not:
>>> list(zip(range(3),'fee'.'fi'.'fo'.'fum'], strict=True))
Traceback (most recent call last):
...
ValueError: zip() argument 2 is longer than argument 1
Copy the code
New built-in functionsaiter()
和 anext()
Corresponding to iter() and next() for asynchronous programming. Aiter () returns an asynchronous iterator, equivalent to calling x.__aiter__(). When await, anext() calls __anext__(), returning the next item of the asynchronous iterator. Raise StopAsyncIteration when an asynchronous iterator is exhausted.
New in Python 3.11math.cbrt
Similar to math.sqrt, returns the cube root of x. This method maps to double CBRT (double ARG) in the C standard library. .
You might say, well, if x ** (1/3) is enough, isn’t this function optional?
In fact, the answer is very simple – pit prevention.
If you were to implement this function you would probably do something like this:
def cbrt(x) :
return x ** (1/3)
Copy the code
But when x is less than 0, the problem arises:
>>> cbrt(-27) The result should be: -3
(1.5000000000000004+2.598076211353316 j.)
Copy the code
To return the result correctly, write:
def cbrt(x) :
if x < 0:
return -(-x) ** (1/3)
else:
return x ** (1/3)
Copy the code
Such a detailed thing, I believe you will not notice. You can’t see, you can’t find the bug arises. Here’s what Python contributor Mark Dickinson had to say about this stuff:
Of course, even with
math.cbrt
in the standard library people will still fall into thex**(1/3)
trap, but at least we then have a decent replacement to point them to.
In addition, x ** (1/3) may have some accuracy problems. As for speed, I haven’t seen an answer yet, but MY guess is that math.cbrt is faster because it takes less time to reload the operator. Of course, it’s too early to tell, and we’ll have to wait until Python 3.11 is released.
[Python 3.11] Removed@asyncio.coroutine
A decorator
In Python 3.5 with the new async def syntax, the @asyncio.coroutine decorator is not needed. This function has been deprecated since Python 3.8 and was originally planned to be removed in Python 3.10.
There are many new features listed in the official documentation, but if you are interested, you can go to the official website.
See here you still don’t like, leave a message, follow?
That was it. I said goodbye.