Pay attention to WeChat public account: K brother crawler, QQ exchange group: 808574309, continue to share advanced crawler, JS/Android reverse engineering and other technical dry goods!
A few days ago, on October 4th, Python released version 3.10.0. What? Isn't 4.0 after 3.9? (Manual dog head) In fact, Guido van Rossum (Guido van Rossum, father of Python) said as early as September last year:
- The version after 3.9 is 3.10; in fact, it already exists (in the Github Master master branch).
- If there is version 4, the transition from 3 to 4 is more like from 1 to 2, rather than from 2 to 3.
Compared to Python 3.9, the main new features of Python 3.10 are as follows:
PEP 634-PEP 636: Structural pattern matching
Among the many updates this time, Structural Pattern Matching, the match-case
statement is undoubtedly the most exciting feature, which is similar to the switch-case
statement in Java, C, Go and other languages. For specific usage, please refer to: PEP 636
Let's look at a simple 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")
http_error(418) # I'm a teapot
http_error(500) # Something's wrong with the internet
Above, the last case
in _
not as a variable name, and represents a special mode, in front of the case
case in none hit the case
will be the last safeguard, to ensure a hit, it is quite default
branch in Java, C, Go and other languages:
public class HttpError {
public static void main(String args[]){
int status = 500;
switch(status){
case 400:
System.out.println("Bad request");
case 404:
System.out.println("Not found");
case 418:
System.out.println("I'm a teapot");
default:
System.out.println("Something's wrong with the internet");
}
}
}
// Something's wrong with the internet
match-case
syntax supports variable parameters *args
and **rest
.
*args
the same as the variable parameter in Python function, allowing multiple parameters to be passed in:
def create_user(command):
match command.split():
case ["quit"]:
quit()
case ["create", user]:
print("create", user)
case ["create", *user]:
for u in user:
print("create", u)
case _:
print("command '{command}' not understood")
create_user("create user1")
create_user("create user2 user3 user4")
# create user1
# create user2
# create user3
# create user4
**rest
will match all key
and value
:
def get_dict(dic):
match dic:
case {**rest}:
print("get dict:", rest)
case _:
print("parameter not understood")
get_dict({"400": "Bad request", "404": "Not found", "418": "I'm a teapot"})
# get dict: {'400': 'Bad request', '404': 'Not found', '418': "I'm a teapot"}
should be noted that when structural pattern matching faces different objects, the matching rules are also different.
When the matching object is a list or a tuple, both the length and the element value must match to be hit:
def create_user(param):
match param:
case ("quit"):
quit()
case ("create", user):
print("create", user)
case ("create", *user):
for u in user:
print("create", u)
case _:
print("command '{command}' not understood")
create_user(("create", "user1", "user2"))
# create user1
# create user2
When the matching object is a dictionary (dict), as long as the key in the case expression exists in the dictionary object, it can be hit. In the following example, it is likely that the second case will be executed, but it is actually executed The first case:
def if_action(dic):
match dic:
case {"action": action}:
print("action: %s, no object" % action)
case {"action": action, "object": _}:
print("action: %s, have object" % action)
if_action({"action": "create", "object": "user1"})
# action: create, no object
When the matching object is a class object (class), the matching rule is similar to a dictionary (dict), as long as the object type and object attributes meet the conditions, it can hit. In the following example, it is likely that the second case will be executed. But the first case is actually executed:
class Info:
def __init__(self, name, age):
self.name, self.age = name, age
def get_info(people):
match people:
case Info(name="Bob"):
print("case 1")
case Info(name="Bob", age="20"):
print("case 2")
people = Info(name="Bob", age="20")
get_info(people)
# case 1
PEP 604: New Union Types (Union Types)
Python is a weakly typed language, but in Python 3 it supports the way of defining parameter passing and return types:
def test(a: int) -> int:
return a**2
Usually a parameter and return value can only be of one type. In static languages such as C/C++, Java, and Go, it is impossible to return two types, or to pass parameters using two types, but in Python it is possible:
def test(a: str or int) -> str or int:
return a**2
The or writing method here looks very uncomfortable, so the typing module was introduced in Python 3.5. It is recommended to use Uinon's writing method:
from typing import Union
def test(a: Union[str, int]) -> Union[str, int]:
return a**2
In this Python 3.10.0 update, PEP 604 allows Union Types to be written as X | Y:
def test(a: str | int) -> str | int:
return a**2
The new operator can also be used as the second parameter of isinstance()
and issubclass()
print(isinstance(5, int | str)) # True
print(isinstance(None, int | None)) # True
print(issubclass(bool, int | float)) # True
print(isinstance(42, None | str)) # False
PEP 626: Error debugging is accurate to the line
In PEP 626 , the error prompt can be accurate to the specific line, and the prompt is more detailed. In previous versions, the error message generally points to the next line instead of the actual error location. Now it can point to the exact location of the error code. .
Error code example 1:
li = [1, 2, 3
The previous version reported an error:
File "D:\python3Project\test.py", line 5
^
SyntaxError: unexpected EOF while parsing
Python 3.10 version reports an error:
File "D:\python310Project\test.py", line 4
li = [1, 2, 3
^
SyntaxError: '[' was never closed
Error code example 2:
expected = {"name": "Bob", "age": 20
some_other_code = foo()
The previous version reported an error:
File "D:\python3Project\test.py", line 2
some_other_code = foo()
^
SyntaxError: invalid syntax
Python 3.10 version reports an error:
File "D:\python310Project\test.py", line 1
expected = {"name": "Bob", "age": 20
^
SyntaxError: '{' was never closed
PEP 618: zip() optional length check
zip()
is a built-in function in Python that takes an iterable object as a parameter, packs the corresponding elements in the object into tuples, and then returns a list of these tuples.
In the previous version, if the number of elements in each iterator is inconsistent, the length of the returned list is the same as the shortest object. The example is as follows:
a = [1, 2, 3]
b = [4, 5, 6]
c = [4, 5, 6, 7, 8]
zipped1 = zip(a, b)
zipped2 = zip(a, c) # 元素个数与最短的列表一致
print([z for z in zipped1]) # [(1, 4), (2, 5), (3, 6)]
print([z for z in zipped2]) # [(1, 4), (2, 5), (3, 6)]
In PEP 618 , a new strict parameter is added. When set to True, the zip()
of the two iterable items ValueError
a = [1, 2, 3]
b = [4, 5, 6]
c = [4, 5, 6, 7, 8]
zipped1 = zip(a, b, strict=True)
zipped2 = zip(a, c, strict=True)
print([z for z in zipped1])
print([z for z in zipped2])
Error:
[(1, 4), (2, 5), (3, 6)]
Traceback (most recent call last):
File "D:\python310Project\test.py", line 8, in <module>
print([z for z in zipped2])
File "D:\python310Project\test.py", line 8, in <listcomp>
print([z for z in zipped2])
ValueError: zip() argument 2 is longer than argument 1
BPO-12782: Allow context managers with brackets
Python context managers are very useful for opening/closing files, handling database connections, and many other things. In Python 3.10.0, their syntax will have a little high-quality improvement. In BPO-12782 officially allowed In the context manager, you can now create multiple lines with a with statement. An example is as follows:
with(
open("text1.txt", encoding="utf-8") as f1,
open("text2.txt", encoding="utf-8") as f2
):
print(f1.read(), f2.read())
PEP 613: Explicit Type Aliases
PEP 613 Use TypeAlias to explicitly label type aliases to improve readability.
In the previous version, you can see that x is easily confused:
x = int
def plus_int(a: x, b: x) -> x:
return a+b
In Python 3.10, TypeAlias is used to indicate that this is an alias to eliminate ambiguity:
from typing import TypeAlias
x: TypeAlias = int
def plus_int(a: x, b: x) -> x:
return a+b
Performance improvement
Like all the latest versions of Python, Python 3.10 also brings some performance improvements. The first is to optimize the str()
, bytes()
and bytearray()
constructors. Their speed is increased by about 30%. The code is taken from BOP-41334 :
$ ./python -m pyperf timeit -q --compare-to=../cpython-release2/python "str()"
Mean +- std dev: [/home/serhiy/py/cpython-release2/python] 81.9 ns +- 4.5 ns -> [/home/serhiy/py/cpython-release/python] 60.0 ns +- 1.9 ns: 1.36x faster (-27%)
$ ./python -m pyperf timeit -q --compare-to=../cpython-release2/python "bytes()"
Mean +- std dev: [/home/serhiy/py/cpython-release2/python] 85.1 ns +- 2.2 ns -> [/home/serhiy/py/cpython-release/python] 60.2 ns +- 2.3 ns: 1.41x faster (-29%)
$ ./python -m pyperf timeit -q --compare-to=../cpython-release2/python "bytearray()"
Mean +- std dev: [/home/serhiy/py/cpython-release2/python] 93.5 ns +- 2.1 ns -> [/home/serhiy/py/cpython-release/python] 73.1 ns +- 1.8 ns: 1.28x faster (-22%)
Another more noteworthy optimization (if you use type annotations) is that function parameters and their annotations are no longer calculated at runtime, but at compile time, which makes it faster to create a function with parameter annotations Improved by about 2 times.
In addition, there are more optimizations in various parts of the Python core. You can find more details in the following questions on the Python bug tracker: BPO-41718 , BPO-42927 BPO .
Other changes
- PEP 623 : Deprecated and prepare to delete the wstr member in PyUnicodeObject.
- PEP 612 : Parameter specification variable.
- PEP 632 : The distutils module is deprecated, and setuptools is recommended.
- PEP 644 : The standard library of CPython only supports OpenSSL 1.1.1 or later.
- PEP 624 : Delete the Py_UNICODE encoder API.
- PEP 597 : Add optional EncodingWarning.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。