มีอะไรใหม่ใน Python 3.11
Python 3.11 เร็วกว่า Python 3.10 โดยเฉลี่ยอยู่ที่ ระหว่าง 10-60%
- CPython 3.11 นั้นเร็วกว่า CPython 3.10 โดยเฉลี่ย 25% ซึ่งวัดด้วย ชุดมาตรฐาน pyperformance และคอมไพล์ด้วย GCC บน Ubuntu Linux การเพิ่มความเร็วซึ่ง อาจเร็วขึ้นถึง 10-60% ทั้งนี้ขึ้นอยู่กับปริมาณงานของคุณด้วย โดยทั่วไปแล้วหากคุณใช้งานโมดูลที่มีการโหลด IO หนักๆ คุณก็แทบจะไม่เห็นประโยชน์มากนัก
- ฟังค์ชัน sum() ตอนนี้เร็วขึ้นเกือบ 30% สำหรับจำนวนเต็มที่น้อยกว่า
2**30
หรือ1073741824
- ตอนนี้คอมไพเลอร์ปรับ printf-style % formatting แบบง่ายให้เหมาะสมที่สุดบนตัวอักษรสตริงที่มีรูปแบบโค้ดเฉพาะอย่าง
%s
,%r
และ%a
และทำให้ความเร็วสอดคล้องเท่ากันกับ f-string - การหารเป็นจำนวนเต็ม (
//
) ได้รับการปรับแต่งให้ดีขึ้นสำหรับการเพิ่มประสิทธิภาพจากคอมไพเลอร์ ตอนนี้ x86 และ x64 เร็วขึ้นประมาณ 20% เมื่อหารเป็นint
โดยค่าต้องน้อยกว่า2**30
หรือ1073741824
- การปรับขนาดของ
list
ให้มีความคล่องตัวสำหรับการใช้งานทั่วไป โดยlist.append()
เร็วขึ้น 15% และlist comprehension เร็วขึ้น 20-30% - การใช้
asyncio.DatagramProtocol
งานจะเร็วขึ้นเมื่อถ่ายโอนไฟล์ขนาดใหญ่ผ่าน UDP ด้วยความเร็วสูงกว่า 100 เท่า สำหรับไฟล์ประมาณ 60 MiB - [
math
](https://docs.python.org/3.11/library/math.html#module-math “คณิตศาสตร์: ฟังก์ชันทางคณิตศาสตร์ (sin() เป็นต้น) ฟังก์ชันcomb()
และperm()
ตอนนี้เร็วขึ้นประมาณ 10 เท่า สำหรับอาร์กิวเมนต์ที่มีขนาดใหญ่ (ด้วยการเพิ่มความเร็วที่มากขึ้นและค่า k ที่ใหญ่ขึ้น ) statistics
ฟังก์ชันmean()
และvariance()
และstdev()
ตอนนี้ใช้ตัววนซ้ำรอบเดียวและแปลงเป็นฟังก์ชันlist
ก่อน ซึ่งเร็วกว่าสองเท่าและสามารถประหยัดการใช้หน่วยความจำไปได้มากunicodedata.normalize()
ตอนนี้ทำให้สตริง pure-ASCII เป็นปกติในเวลาคงที่
คุณสมบัติ syntax และ built-in ใหม่
- PEP 654: Exception Groups และ except* คุณสมบัติที่จะช่วยให้โปรแกรมสามารถ raise และจัดการ Exception ที่ไม่เกี่ยวข้องในหลายๆรายการพร้อมกันได้ บิวด์อินประเภท
ExceptionGroup
และBaseExceptionGroup
ทำให้สามารถจัดกลุ่ม Exception และรวมกันได้ และexcept*
ไวยากรณ์ใหม่จะสรุปexcept
ให้ตรงกับกลุ่มย่อยของกลุ่ม Exception
>>> eg = ExceptionGroup(
... "one",
... [
... TypeError(1),
... ExceptionGroup(
... "two",
... [TypeError(2), ValueError(3)]
... ),
... ExceptionGroup(
... "three",
... [OSError(4)]
... )
... ]
... )
>>> import traceback
>>> traceback.print_exception(eg)
| ExceptionGroup: one (3 sub-exceptions)
+-+---------------- 1 ----------------
| TypeError: 1
+---------------- 2 ----------------
| ExceptionGroup: two (2 sub-exceptions)
+-+---------------- 1 ----------------
| TypeError: 2
+---------------- 2 ----------------
| ValueError: 3
+------------------------------------
+---------------- 3 ----------------
| ExceptionGroup: three (1 sub-exception)
+-+---------------- 1 ----------------
| OSError: 4
+------------------------------------
>>> type_errors = eg.subgroup(lambda e: isinstance(e, TypeError))
>>> traceback.print_exception(type_errors)
| ExceptionGroup: one (2 sub-exceptions)
+-+---------------- 1 ----------------
| TypeError: 1
+---------------- 2 ----------------
| ExceptionGroup: two (1 sub-exception)
+-+---------------- 1 ----------------
| TypeError: 2
+------------------------------------
>>>
- PEP 678: Exceptions สามารถเสริมโน้ตลงไปได้ เมธอด
add_note()
ถูกเพิ่มเข้าไปในBaseException
สามารถใช้เพื่อเพิ่มข้อ Exception ด้วยข้อมูล context ที่ไม่พร้อมใช้งานในขณะที่ raise Exception ออกมาแล้ว โน้ตที่เพิ่มเข้ามาจะปรากฏใน traceback เริ่มต้น
>>> try:
... raise TypeError('bad type')
... except Exception as e:
... e.add_note('เพิ่มข้อมูลบางอย่าง')
... raise
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: bad type
เพิ่มข้อมูลบางอย่าง
>>>
โมดูลไลบรารีมาตรฐานใหม่
PEP 680 :
tomllib
— รองรับการแยกวิเคราะห์ TOML ในไลบรารีมาตรฐาน โมดูลนี้มีอินเทอร์เฟซสำหรับการแยกวิเคราะห์ TOML (Tom’s Obvious Minimal Language, https://toml.io ) โมดูลนี้ไม่รองรับการเขียนแบบ TOMLการแยกวิเคราะห์ด้วยไฟล์ .TOML
import tomllib
with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
- การแยกวิเคราะห์ด้วยสตริง TOML:
import tomllib
toml_str = """
python-version = "3.11.0"
python-implementation = "CPython"
"""
data = tomllib.loads(toml_str)
ปรับปรุงตัวแปลคำสั่งหรืออินเทอร์พรีเตอร์ (Interpreter)
- PEP 657: ตำแหน่งของข้อผิดพลาดที่ละเอียดจากการ traceback เมื่อแสดงข้อมูล traceback ตอนนี้ตัวแปลคำสั่งจะชี้ไปยังนิพจน์หรือ expression ที่แน่นอนขึ้นบริเวณที่ทำให้เกิดข้อผิดพลาด แทนที่จะระบุเป็นเพียงบรรทัด ตัวอย่างเช่น:
Traceback (most recent call last):
File "distance.py", line 11, in <module>
print(manhattan_distance(p1, p2))
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "distance.py", line 6, in manhattan_distance
return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'x'
*ให้สังเกตุที่เครื่องหมาย ^^^^^^^^^
ที่แสดงอยูในโค้ดตัวอย่าง
-P
ตัวเลือกบรรทัดคำสั่งใหม่เพิ่มเติม และตัวแปร environmentPYTHONSAFEPATH
เพื่อปิดใช้งานการเติมsys.path
หน้าไดเร็กทอรีของสคริปต์โดยอัตโนมัติเมื่อเรียกใช้งานสคริปต์ หรือไดเร็กทอรีปัจจุบันเมื่อใช้-c
และ-m
สิ่งนี้ทำให้แน่ใจว่าเฉพาะโมดูล stdlib และโมดูลที่ติดตั้งเท่านั้นที่จะถูกเลือกจากการimport
เข้ามาเพื่อหลีกเลี่ยงการ shadowing modules โดยไม่ได้ตั้งใจหรือมุ่งร้ายกับโมดูลที่อยู่ในไดเร็กทอรีท้องถิ่น
คุณสมบัติใหม่ที่เกี่ยวข้องกับคำแนะนำประเภท
- PEP 646: Variadic generics โดย
TypeVarTuple
เปิดใช้งานการกำหนดพารามิเตอร์ด้วยจำนวนประเภทได้ตามอำเภอใจ ช่วยให้ใช้งานได้หลากหลายขึ้น โดยเฉพาะอย่างยิ่ง อนุญาตให้กำหนดประเภทของโครงสร้างที่เหมือนอาร์เรย์ในไลบรารีการคำนวณเชิงตัวเลข เช่น NumPy และ TensorFlow สามารถArray ใช้เพื่อสนับสนุนคำอธิบายประกอบเกี่ยวกับ shape ได้หลายประเภท ตัวอย่างเช่น เราสามารถเพิ่มป้ายกำกับที่อธิบายความหมายเชิงความหมายของแต่ละแกน
from typing import NewType
Height = NewType('Height', int)
Width = NewType('Width', int)
x: Array[float, Height, Width] = Array()
- PEP 655: การทำเครื่องหมายแต่ละ
TypedDict
รายการว่าจำเป็นหรือไม่จำเป็นRequired
กับNotRequired
ให้วิธีการที่ตรงไปตรงมาในการทำเครื่องหมายว่าต้องมีรายการแต่ละ รายการใน TypedDict หรือไม่ ซึ่งก่อนหน้านี้ทำได้โดยใช้การสืบทอดเพียงอย่างเดียวเท่านั้น ฟิลด์ทั้งหมดค่าเริ่มต้นจะเป็น required เว้นแต่ว่าหากพารามิเตอร์ total เป็น False ซึ่งในกรณีนี้ฟิลด์ทั้งหมดค่าเริ่มต้นจะเป็น not-required ตัวอย่างเช่น ข้อมูลต่อไปนี้ระบุ TypedDict ด้วยหนึ่งคีย์เป็น required
class Movie(TypedDict):
title: str
year: NotRequired[int]
m1: Movie = {"title": "Black Panther", "year": 2018} # OK
m2: Movie = {"title": "Star Wars"} # OK (year is not required)
m3: Movie = {"year": 2022} # ERROR (missing required field title)
และหนึ่งคีย์ not-required
class Movie(TypedDict, total=False):
title: Required[str]
year: int
- PEP 673: Self type คำอธิบายประกอบ
Self
ใหม่ เป็นวิธีที่ง่ายและใช้งานง่ายในการใส่คำอธิบายประกอบของเมธอด ที่ return อินสแตนซ์ของ class สิ่งนี้ทำงานเหมือนกับแนวทางที่ใช้กับ TypeVar แต่กระชับและง่ายในทางปฏิบัติตามมาก กรณีการใช้งานทั่วไปรวมถึงตัวสร้างที่เป็นทางเลือกที่จัดไว้ให้คือ @classmethod และเมธอด__enter__()
และส่งค่า self กลับ
class MyLock:
def __enter__(self) -> Self:
self.lock()
return self
...
class MyInt:
@classmethod
def fromhex(cls, s: str) -> Self:
return cls(int(s, 16))
...
- PEP 675: ประเภทสตริงตามอำเภอใจ อาจใช้เพื่อระบุว่าพารามิเตอร์ของฟังก์ชันสามารถเป็นประเภทสตริงตามตัวอักษรใดก็ได้ ซึ่งช่วยให้ฟังก์ชันยอมรับประเภทสตริงตามตัวอักษรได้ เช่นเดียวกับสตริงที่สร้างจากสตริงตามตัวอักษรอื่นๆ ตัวตรวจสอบประเภทสามารถบังคับใช้ฟังก์ชันที่ละเอียดอ่อนได้ เช่น ฟังก์ชันที่ดำเนินการคำสั่ง SQL หรือคำสั่งเชลล์ จะถูกเรียกด้วยอาร์กิวเมนต์แบบคงที่เท่านั้น ซึ่งให้การป้องกันการโจมตีแบบ injection ตัวอย่างเช่น ฟังก์ชันSQL query สามารถใส่คำอธิบายประกอบได้ดังนี้:
def run_query(sql: LiteralString) -> ...
...
def caller(
arbitrary_string: str,
query_string: LiteralString,
table_name: LiteralString,
) -> None:
run_query("SELECT * FROM students") # ok
run_query(query_string) # ok
run_query("SELECT * FROM " + table_name) # ok
run_query(arbitrary_string) # type checker error
run_query( # type checker error
f"SELECT * FROM students WHERE name = {arbitrary_string}"
)
- PEP 681: Data class transforms อาจใช้ตกแต่งคลาส เมตาคลาส หรือฟังก์ชันที่เป็น decorator การมีอยู่ของ
@dataclass_transform()
บอกตัวตรวจสอบประเภทสแตติกว่าอ็อบเจ็กต์ที่ตกแต่งแล้วเท่านั้นถึงจะดำเนินการ “magic” รันไทม์ที่เปลี่ยนคลาสทำให้มีdataclass
พฤติกรรมเหมือนมัน
# decorator create_model ถูกกำหนดโดย library
@typing.dataclass_transform()
def create_model(cls: Type[T]) -> Type[T]:
cls.__init__ = ...
cls.__eq__ = ...
cls.__ne__ = ...
return cls
# decorator create_model ตอนนี้สามารถใช้เพื่อสร้างคลาสโมเดลใหม่ได้เลยทันที
@create_model
class CustomerModel:
id: int
name: str
c = CustomerModel(id=327, name="Eric Idle")