Có gì mới trong Python 2.5

tác giả:

A.M. Kuchling

Bài viết này giải thích các tính năng mới trong Python 2.5. Bản phát hành cuối cùng của Python 2.5 được lên lịch vào tháng 8 năm 2006; PEP 356 mô tả lịch phát hành dự kiến. Python 2.5 được phát hành vào ngày 19 tháng 9 năm 2006.

Những thay đổi trong Python 2.5 là sự kết hợp thú vị giữa cải tiến ngôn ngữ và thư viện. Tôi nghĩ rằng những cải tiến về thư viện sẽ quan trọng hơn đối với cộng đồng người dùng Python vì một số gói hữu ích rộng rãi đã được thêm vào. Các mô-đun mới bao gồm ElementTree để xử lý XML (xml.etree), mô-đun cơ sở dữ liệu SQLite (sqlite) và mô-đun ctypes để gọi các hàm C.

Những thay đổi ngôn ngữ có ý nghĩa trung bình. Một số tính năng mới thú vị đã được thêm vào nhưng hầu hết chúng không phải là những tính năng mà bạn sẽ sử dụng hàng ngày. Các biểu thức có điều kiện cuối cùng đã được thêm vào ngôn ngữ bằng cú pháp mới; xem phần PEP 308: Biểu thức điều kiện. Câu lệnh 'with' mới sẽ giúp việc viết mã dọn dẹp dễ dàng hơn (phần PEP 343: Câu lệnh 'với'). Các giá trị hiện có thể được chuyển vào trình tạo (phần PEP 342: Tính năng máy phát điện mới). Nội dung nhập hiện được hiển thị dưới dạng tuyệt đối hoặc tương đối (phần PEP 328: Nhập khẩu tuyệt đối và tương đối). Một số trường hợp xử lý ngoại lệ ở góc được xử lý tốt hơn (phần PEP 341: Thống nhất thử/ngoại trừ/cuối cùng). Tất cả những cải tiến này đều đáng giá, nhưng chúng là những cải tiến đối với tính năng ngôn ngữ cụ thể này hay tính năng khác; không có cái nào trong số chúng là những sửa đổi rộng rãi đối với ngữ nghĩa của Python.

Cùng với việc bổ sung ngôn ngữ và thư viện, các cải tiến và sửa lỗi khác cũng được thực hiện trên cây nguồn. Tìm kiếm trong nhật ký thay đổi của SVN cho thấy đã có 353 bản vá được áp dụng và 458 lỗi đã được sửa giữa Python 2.4 và 2.5. (Cả hai con số đều có khả năng bị đánh giá thấp.)

Bài viết này không cố gắng mô tả đầy đủ các tính năng mới; thay vào đó những thay đổi được giới thiệu ngắn gọn bằng các ví dụ hữu ích. Để biết chi tiết đầy đủ, bạn phải luôn tham khảo tài liệu dành cho Python 2.5 tại https://python.go-mizu.dev.. Nếu bạn muốn hiểu cơ sở lý luận về thiết kế và triển khai đầy đủ, hãy tham khảo PEP để biết một tính năng mới cụ thể.

Mọi nhận xét, đề xuất và báo cáo lỗi cho tài liệu này đều được hoan nghênh; vui lòng gửi chúng qua email cho tác giả hoặc mở một lỗi trong trình theo dõi lỗi Python.

PEP 308: Biểu thức điều kiện

Trong một thời gian dài, mọi người đã yêu cầu cách viết các biểu thức điều kiện, đó là các biểu thức trả về giá trị A hoặc giá trị B tùy thuộc vào việc giá trị Boolean là đúng hay sai. Biểu thức điều kiện cho phép bạn viết một câu lệnh gán có tác dụng tương tự như sau:

nếu điều kiện:
    x = true_value
khác:
    x = false_value

Đã có vô số cuộc thảo luận tẻ nhạt về cú pháp trên cả python-dev và comp.lang.python. Một cuộc bỏ phiếu thậm chí đã được tổ chức cho thấy đa số cử tri muốn có các biểu thức có điều kiện dưới một số hình thức, nhưng không có cú pháp nào được đa số rõ ràng ưa thích. Các ứng cử viên bao gồm cond ? true_v : false_v, if cond then true_v else false_v của C và 16 biến thể khác.

Guido van Rossum cuối cùng đã chọn một cú pháp đáng ngạc nhiên

x = true_value nếu điều kiện khác false_value

Việc đánh giá vẫn còn lười biếng như trong các biểu thức Boolean hiện có, do đó thứ tự đánh giá sẽ thay đổi một chút. Biểu thức condition ở giữa được đánh giá đầu tiên và biểu thức true_value chỉ được đánh giá nếu điều kiện là đúng. Tương tự, biểu thức false_value chỉ được đánh giá khi điều kiện sai.

Cú pháp này có vẻ lạ và ngược; tại sao điều kiện lại nằm ở middle của biểu thức chứ không phải ở phía trước như trong c ? x : y của C? Quyết định này đã được kiểm tra bằng cách áp dụng cú pháp mới cho các mô-đun trong thư viện tiêu chuẩn và xem mã kết quả được đọc như thế nào. Trong nhiều trường hợp khi sử dụng biểu thức điều kiện, một giá trị dường như là 'trường hợp phổ biến' và một giá trị là 'trường hợp ngoại lệ', chỉ được sử dụng trong những trường hợp hiếm hoi hơn khi điều kiện không được đáp ứng. Cú pháp có điều kiện làm cho mẫu này rõ ràng hơn một chút:

nội dung = ((doc + '\n') if doc else '')

Tôi đọc câu trên có nghĩa là "ở đây contents thường được gán giá trị doc+'\n'; đôi khi doc trống, trong trường hợp đặc biệt, một chuỗi trống được trả về." Tôi nghi ngờ rằng tôi sẽ thường xuyên sử dụng các biểu thức có điều kiện khi không có trường hợp phổ biến và không phổ biến rõ ràng.

Đã có một số cuộc thảo luận về việc liệu ngôn ngữ có nên yêu cầu các biểu thức điều kiện xung quanh có dấu ngoặc đơn hay không. Quyết định được đưa ra là not yêu cầu dấu ngoặc đơn trong ngữ pháp của ngôn ngữ Python, nhưng về vấn đề văn phong, tôi nghĩ bạn nên luôn sử dụng chúng. Hãy xem xét hai tuyên bố sau:

phiên bản # First -- không có dấu ngoặc đơn
cấp độ = 1 nếu đăng nhập khác 0

phiên bản # Second -- có dấu ngoặc đơn
cấp độ = (1 nếu đăng nhập khác 0)

Trong phiên bản đầu tiên, tôi nghĩ mắt người đọc có thể nhóm câu lệnh thành 'level = 1', 'if ghi nhật ký', 'khác 0' và nghĩ rằng điều kiện sẽ quyết định liệu việc gán cho level có được thực hiện hay không. Theo tôi, phiên bản thứ hai đọc tốt hơn vì nó cho thấy rõ rằng nhiệm vụ luôn được thực hiện và sự lựa chọn đang được thực hiện giữa hai giá trị.

Một lý do khác để bao gồm dấu ngoặc: một số kết hợp kỳ lạ giữa khả năng hiểu danh sách và biểu thức lambda có thể trông giống như các biểu thức điều kiện không chính xác. Xem PEP 308 để biết một số ví dụ. Nếu bạn đặt dấu ngoặc đơn xung quanh biểu thức điều kiện, bạn sẽ không gặp phải trường hợp này.

Xem thêm

PEP 308 - Biểu thức có điều kiện

PEP được viết bởi Guido van Rossum và Raymond D. Hettinger; được thực hiện bởi Thomas Wouters.

PEP 309: Ứng dụng chức năng một phần

Mô-đun functools được thiết kế để chứa các công cụ lập trình kiểu chức năng.

Một công cụ hữu ích trong mô-đun này là chức năng partial(). Đối với các chương trình được viết theo kiểu hàm, đôi khi bạn sẽ muốn xây dựng các biến thể của hàm hiện có có điền một số tham số. Hãy xem xét hàm Python f(a, b, c); bạn có thể tạo một hàm mới g(b, c) tương đương với f(1, b, c). Đây được gọi là "ứng dụng chức năng một phần".

partial() lấy các đối số (function, arg1, arg2, ... kwarg1=value1, kwarg2=value2). Đối tượng kết quả có thể gọi được, vì vậy bạn chỉ cần gọi nó để gọi function với các đối số được điền đầy đủ.

Đây là một ví dụ nhỏ nhưng thực tế:

nhập khẩu funtools

nhật  def (tin nhắn, hệ thống con):
    "Viết nội dung của 'tin nhắn' tới hệ thống con được chỉ định."
    print '%s: %s' % (hệ thống con, tin nhắn)
    ...

server_log = functools.partial(log, subsystem='server')
server_log('Không thể mở socket')

Đây là một ví dụ khác, từ một chương trình sử dụng PyGTK. Ở đây, một menu bật lên theo ngữ cảnh đang được xây dựng một cách linh hoạt. Lệnh gọi lại được cung cấp cho tùy chọn menu là phiên bản được áp dụng một phần của phương thức open_item(), trong đó đối số đầu tiên đã được cung cấp.

...
Ứng dụng lớp:
    def open_item(tự, đường dẫn):
       ...
    def init (tự):
        open_func = functools.partial(self.open_item, item_path)
        Popup_menu.append( ("Mở", open_func, 1) )

Một chức năng khác trong mô-đun functools là chức năng update_wrapper(wrapper, wrapped) giúp bạn viết các trình trang trí hoạt động tốt. update_wrapper() sao chép thuộc tính tên, mô-đun và chuỗi tài liệu vào hàm bao bọc để việc theo dõi bên trong hàm được bao bọc dễ hiểu hơn. Ví dụ: bạn có thể viết:

def my_designator(f):
    trình bao bọc def(*args, **kwds):
        print 'Gọi hàm trang trí'
        trả về f(*args, **kwds)
    functools.update_wrapper(trình bao bọc, f)
    giấy gói trả lại

wraps() là một công cụ trang trí có thể được sử dụng bên trong các công cụ trang trí của riêng bạn để sao chép thông tin của hàm được bao bọc. Phiên bản thay thế của ví dụ trước sẽ là:

def my_designator(f):
    @functools.wraps(f)
    trình bao bọc def(*args, **kwds):
        print 'Gọi hàm trang trí'
        trả về f(*args, **kwds)
    giấy gói trả lại

Xem thêm

PEP 309 - Ứng dụng chức năng một phần

PEP do Peter Harris đề xuất và viết; do Hye-Shik Chang và Nick Coghlan thực hiện, với sự chuyển thể của Raymond Hettinger.

PEP 314: Siêu dữ liệu cho gói phần mềm Python v1.1

Một số hỗ trợ phụ thuộc đơn giản đã được thêm vào Distutils. Hàm setup() hiện có các tham số từ khóa requires, providesobsoletes. Khi bạn xây dựng bản phân phối nguồn bằng lệnh sdist, thông tin phụ thuộc sẽ được ghi trong tệp PKG-INFO.

Một tham số từ khóa mới khác là download_url, nên được đặt thành URL cho mã nguồn của gói. Điều này có nghĩa là giờ đây bạn có thể tra cứu mục nhập trong chỉ mục gói, xác định các mối quan hệ phụ thuộc của gói và tải xuống các gói được yêu cầu.

VERSION = '1.0'
thiết lập(name='PyPackage',
      phiên bản=VERSION,
      yêu cầu=['numarray', 'zlib (>=1.1.4)'],
      lỗi thời=['OldPackage']
      tải về_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
                    %VERSION),
     )

Một cải tiến mới khác đối với chỉ mục gói Python tại https://pypi.org là lưu trữ các kho lưu trữ nguồn và nhị phân cho một gói. Lệnh upload Distutils mới sẽ tải gói lên kho lưu trữ.

Trước khi có thể tải gói lên, bạn phải có khả năng xây dựng bản phân phối bằng lệnh sdist Distutils. Khi điều đó hoạt động, bạn có thể chạy python setup.py upload để thêm gói của mình vào kho lưu trữ PyPI. Tùy chọn, bạn có thể GPG-ký gói bằng cách cung cấp các tùy chọn --sign--identity.

Việc tải gói lên được thực hiện bởi Martin von Löwis và Richard Jones.

Xem thêm

PEP 314 - Siêu dữ liệu cho gói phần mềm Python v1.1

PEP được đề xuất và viết bởi A.M. Kuchling, Richard Jones và Fred Drake; được thực hiện bởi Richard Jones và Fred Drake.

PEP 328: Nhập khẩu tuyệt đối và tương đối

Phần đơn giản hơn của PEP 328 đã được triển khai trong Python 2.4: giờ đây có thể sử dụng dấu ngoặc đơn để đính kèm các tên được nhập từ một mô-đun bằng câu lệnh from ... import ..., giúp nhập nhiều tên khác nhau dễ dàng hơn.

Phần phức tạp hơn đã được triển khai trong Python 2.5: việc nhập mô-đun có thể được chỉ định để sử dụng nhập tuyệt đối hoặc tương đối gói. Kế hoạch là hướng tới việc đặt tính năng nhập tuyệt đối làm mặc định trong các phiên bản Python trong tương lai.

Giả sử bạn có một thư mục gói như thế này

pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py

Điều này xác định một gói có tên pkg chứa các mô-đun con pkg.mainpkg.string.

Hãy xem xét mã trong mô-đun main.py. Điều gì xảy ra nếu nó thực thi câu lệnh import string? Trong Python 2.4 trở về trước, trước tiên, nó sẽ tìm trong thư mục của gói để thực hiện nhập tương đối, tìm pkg/string.py, nhập nội dung của tệp đó dưới dạng mô-đun pkg.string và mô-đun đó được liên kết với tên string trong không gian tên của mô-đun pkg.main.

Sẽ ổn thôi nếu pkg.string là thứ bạn muốn. Nhưng nếu bạn muốn mô-đun string tiêu chuẩn của Python thì sao? Không có cách nào rõ ràng để bỏ qua pkg.string và tìm kiếm mô-đun tiêu chuẩn; nói chung bạn phải xem nội dung của sys.modules, nội dung này hơi ô uế. Gói py.std của Holger Krekel cung cấp một cách gọn gàng hơn để thực hiện nhập từ thư viện chuẩn, import py; py.std.string.join(), nhưng gói đó không có sẵn trên tất cả các bản cài đặt Python.

Việc đọc mã dựa trên việc nhập tương đối cũng kém rõ ràng hơn vì người đọc có thể nhầm lẫn về mô-đun nào, string hoặc pkg.string, sẽ được sử dụng. Người dùng Python sớm học được cách không trùng lặp tên của các mô-đun thư viện tiêu chuẩn với tên của các mô-đun con của gói của họ, nhưng bạn không thể tránh khỏi việc tên mô-đun con của mình bị sử dụng cho một mô-đun mới được thêm vào trong phiên bản Python trong tương lai.

Trong Python 2.5, bạn có thể chuyển hành vi của import sang nhập tuyệt đối bằng lệnh from __future__ import absolute_import. Hành vi nhập tuyệt đối này sẽ trở thành mặc định trong phiên bản tương lai (có thể là Python 2.7). Khi nhập tuyệt đối là mặc định, import string sẽ luôn tìm phiên bản của thư viện chuẩn. Chúng tôi khuyên người dùng nên bắt đầu sử dụng tính năng nhập tuyệt đối càng nhiều càng tốt, vì vậy tốt nhất bạn nên bắt đầu viết from pkg import string vào mã của mình.

Vẫn có thể nhập tương đối bằng cách thêm dấu chấm ở đầu tên mô-đun khi sử dụng biểu mẫu from ... import:

tên # Import từ pkg.string
từ nhập .string name1, name2
# Import pkg.string
từ . nhập chuỗi

Điều này nhập mô-đun string liên quan đến gói hiện tại, vì vậy trong pkg.main điều này sẽ nhập name1name2 từ pkg.string. Các giai đoạn đầu bổ sung thực hiện quá trình nhập tương đối bắt đầu từ gói gốc của gói hiện tại. Ví dụ: mã trong mô-đun A.B.C có thể thực hiện:

từ . nhập D # Imports A.B.D
từ .. nhập E # Imports A.E
từ ..F nhập G # Imports A.F.G

Không thể sử dụng dấu chấm ở đầu với biểu mẫu import modname của câu lệnh nhập mà chỉ có thể sử dụng biểu mẫu from ... import.

Xem thêm

PEP 328 - Nhập khẩu: Nhiều dòng và Tuyệt đối/Tương đối

PEP được viết bởi Aahz; được thực hiện bởi Thomas Wouters.

https://pylib.readthedocs.io/

Thư viện py của Holger Krekel, chứa gói py.std.

PEP 338: Thực thi các mô-đun dưới dạng tập lệnh

Công tắc -m được thêm vào Python 2.4 để thực thi một mô-đun dưới dạng tập lệnh có thêm một số khả năng. Thay vì được triển khai bằng mã C bên trong trình thông dịch Python, switch hiện sử dụng cách triển khai trong mô-đun mới, runpy.

Mô-đun runpy triển khai cơ chế nhập phức tạp hơn để giờ đây có thể chạy các mô-đun trong một gói như pychecker.checker. Mô-đun này cũng hỗ trợ các cơ chế nhập thay thế như mô-đun zipimport. Điều này có nghĩa là bạn có thể thêm đường dẫn của kho lưu trữ .zip vào sys.path, sau đó sử dụng khóa chuyển -m để thực thi mã từ kho lưu trữ.

Xem thêm

PEP 338 - Thực thi các mô-đun dưới dạng tập lệnh

PEP được viết và triển khai bởi Nick Coghlan.

PEP 341: Thống nhất thử/ngoại trừ/cuối cùng

Cho đến Python 2.5, câu lệnh try có hai loại. Bạn có thể sử dụng khối finally để đảm bảo mã đó luôn được thực thi hoặc một hoặc nhiều khối except để nắm bắt các ngoại lệ cụ thể. Bạn không thể kết hợp cả khối except và khối finally vì việc tạo mã byte phù hợp cho phiên bản kết hợp rất phức tạp và không rõ ngữ nghĩa của câu lệnh kết hợp là gì.

Guido van Rossum đã dành một chút thời gian làm việc với Java, Java hỗ trợ tương đương với việc kết hợp các khối except và khối finally, và điều này đã làm rõ ý nghĩa của câu lệnh. Trong Python 2.5, bây giờ bạn có thể viết:

thử:
    khối-1 ...
ngoại trừ Ngoại lệ1:
    xử -1 ...
ngoại trừ Ngoại lệ2:
    xử -2 ...
khác:
    khối khác
cuối cùng:
    khối cuối cùng

Mã trong block-1 được thực thi. Nếu mã đưa ra một ngoại lệ, các khối except khác nhau sẽ được kiểm tra: nếu ngoại lệ thuộc lớp Exception1, handler-1 sẽ được thực thi; mặt khác, nếu nó thuộc lớp Exception2, handler-2 sẽ được thực thi, v.v. Nếu không có ngoại lệ nào được đưa ra, else-block sẽ được thực thi.

Bất kể điều gì đã xảy ra trước đó, final-block vẫn được thực thi sau khi khối mã hoàn tất và mọi trường hợp ngoại lệ được xử lý. Ngay cả khi có lỗi trong trình xử lý ngoại lệ hoặc else-block và một ngoại lệ mới được đưa ra thì mã trong final-block vẫn chạy.

Xem thêm

PEP 341 - Thống nhất thử ngoại trừ và thử cuối cùng

PEP được viết bởi Georg Brandl; thực hiện bởi Thomas Lee.

PEP 342: Tính năng máy phát điện mới

Python 2.5 bổ sung một cách đơn giản để truyền các giá trị into vào trình tạo. Như đã giới thiệu trong Python 2.3, trình tạo chỉ tạo ra đầu ra; khi mã của trình tạo được gọi để tạo trình vòng lặp, sẽ không có cách nào chuyển bất kỳ thông tin mới nào vào hàm khi quá trình thực thi của nó được tiếp tục. Đôi khi khả năng chuyển một số thông tin sẽ hữu ích. Các giải pháp hackish cho vấn đề này bao gồm làm cho mã của trình tạo xem xét một biến toàn cục rồi thay đổi giá trị của biến toàn cục hoặc chuyển vào một số đối tượng có thể thay đổi mà người gọi sau đó sẽ sửa đổi.

Để làm mới bộ nhớ của bạn về các trình tạo cơ bản, đây là một ví dụ đơn giản:

bộ đếm def (tối đa):
    tôi = 0
    trong khi tôi < tối đa:
        nhường tôi
        tôi += 1

Khi bạn gọi counter(10), kết quả là một trình vòng lặp trả về các giá trị từ 0 đến 9. Khi gặp câu lệnh yield, trình vòng lặp trả về giá trị được cung cấp và tạm dừng việc thực thi hàm, bảo toàn các biến cục bộ. Quá trình thực thi sẽ tiếp tục với lệnh gọi sau tới phương thức next() của iterator, bắt đầu sau câu lệnh yield.

Trong Python 2.3, yield là một câu lệnh; nó không trả về bất kỳ giá trị nào. Trong 2.5, yield hiện là một biểu thức, trả về một giá trị có thể được gán cho một biến hoặc được vận hành trên

val = (sản lượng i)

Tôi khuyên bạn nên luôn đặt dấu ngoặc đơn xung quanh biểu thức yield khi bạn đang làm điều gì đó có giá trị được trả về, như trong ví dụ trên. Các dấu ngoặc đơn không phải lúc nào cũng cần thiết nhưng việc thêm chúng vào luôn sẽ dễ dàng hơn thay vì phải nhớ khi cần.

(PEP 342 giải thích các quy tắc chính xác, đó là biểu thức yield- phải luôn được đặt trong ngoặc đơn trừ khi nó xuất hiện ở biểu thức cấp cao nhất ở phía bên phải của phép gán. Điều này có nghĩa là bạn có thể viết val = yield i nhưng phải sử dụng dấu ngoặc đơn khi có một thao tác, như trong val = (yield i) + 12.)

Các giá trị được gửi vào trình tạo bằng cách gọi phương thức send(value) của nó. Sau đó, mã của trình tạo sẽ được tiếp tục và biểu thức yield trả về value đã chỉ định. Nếu phương thức next() thông thường được gọi, yield sẽ trả về None.

Đây là ví dụ trước, được sửa đổi để cho phép thay đổi giá trị của bộ đếm nội bộ.

bộ đếm def (tối đa):
    tôi = 0
    trong khi tôi < tối đa:
        val = (sản lượng i)
        giá trị # If được cung cấp, bộ đếm thay đổi
        nếu val không phải  Không:
            tôi = giá trị
        khác:
            tôi += 1

Và đây là một ví dụ về việc thay đổi bộ đếm:

>>> it = bộ đếm(10)
>>> in .next()
0
>>> in .next()
1
>>> in .send(8)
8
>>> in .next()
9
>>> in .next()
Traceback (cuộc gọi gần đây nhất):
  Tệp "t.py", dòng 15, ở định dạng ?
    in nó.next()
Dừng lại

yield thường sẽ trả về None, vì vậy bạn phải luôn kiểm tra trường hợp này. Đừng chỉ sử dụng giá trị của nó trong các biểu thức trừ khi bạn chắc chắn rằng phương thức send() sẽ là phương thức duy nhất được sử dụng để tiếp tục hàm tạo của bạn.

Ngoài send(), còn có hai phương pháp mới khác trên máy phát điện:

  • throw(type, value=None, traceback=None) được sử dụng để đưa ra một ngoại lệ bên trong trình tạo; ngoại lệ được đưa ra bởi biểu thức yield khi quá trình thực thi của trình tạo bị tạm dừng.

  • close() đưa ra một ngoại lệ GeneratorExit mới bên trong trình tạo để kết thúc quá trình lặp. Khi nhận được ngoại lệ này, mã của trình tạo phải tăng GeneratorExit hoặc StopIteration. Việc bắt ngoại lệ GeneratorExit và trả về một giá trị là bất hợp pháp và sẽ kích hoạt RuntimeError; nếu hàm đưa ra một số ngoại lệ khác, ngoại lệ đó sẽ được truyền tới người gọi. close() cũng sẽ được trình thu gom rác của Python gọi khi trình tạo được thu gom rác.

    Nếu bạn cần chạy mã dọn dẹp khi xảy ra GeneratorExit, tôi khuyên bạn nên sử dụng bộ try: ... finally: thay vì bắt GeneratorExit.

Tác động tích lũy của những thay đổi này là biến người tạo ra thông tin một chiều thành cả người sản xuất và người tiêu dùng.

Trình tạo cũng trở thành coroutines, một dạng chương trình con tổng quát hơn. Các chương trình con được nhập tại một điểm và thoát tại một điểm khác (đầu hàm và câu lệnh return), nhưng các coroutine có thể được nhập, thoát và tiếp tục ở nhiều điểm khác nhau (câu lệnh yield). Chúng ta sẽ phải tìm ra các mẫu để sử dụng coroutine một cách hiệu quả trong Python.

Việc bổ sung phương pháp close() có một tác dụng phụ không rõ ràng. close() được gọi khi trình tạo được thu gom rác, vì vậy điều này có nghĩa là mã của trình tạo có cơ hội cuối cùng để chạy trước khi trình tạo bị hủy. Cơ hội cuối cùng này có nghĩa là các câu lệnh try...finally trong trình tạo hiện có thể được đảm bảo hoạt động; mệnh đề finally bây giờ sẽ luôn có cơ hội chạy. Do đó, hạn chế về cú pháp mà bạn không thể kết hợp các câu lệnh yield với bộ try...finally đã bị xóa. Điều này có vẻ giống như một câu đố nhỏ về ngôn ngữ, nhưng việc sử dụng trình tạo và try...finally thực sự cần thiết để triển khai câu lệnh with được mô tả bởi PEP 343. Tôi sẽ xem xét tuyên bố mới này trong phần sau.

Một hiệu ứng bí truyền khác của sự thay đổi này: trước đây, thuộc tính gi_frame của trình tạo luôn là đối tượng khung. Giờ đây, gi_frame có thể trở thành None sau khi trình tạo đã cạn kiệt.

Xem thêm

PEP 342 - Coroutine thông qua Trình tạo nâng cao

PEP được viết bởi Guido van Rossum và Phillip J. Eby; được thực hiện bởi Phillip J. Eby. Bao gồm các ví dụ về một số cách sử dụng máy phát điện thú vị hơn làm coroutine.

Các phiên bản trước của những tính năng này đã được đề xuất trong PEP 288 bởi Raymond Hettinger và PEP 325 bởi Samuele Pedroni.

https://en.wikipedia.org/wiki/Coroutine

Mục nhập Wikipedia cho coroutine.

https://web.archive.org/web/20160321211320/http://www.sidhe.org/~dan/blog/archives/000178.html

Giải thích về coroutine theo quan điểm Perl, được viết bởi Dan Sugalski.

PEP 343: Câu lệnh 'với'

Câu lệnh 'with' làm rõ mã mà trước đây sẽ sử dụng các khối try...finally để đảm bảo rằng mã dọn dẹp được thực thi. Trong phần này, tôi sẽ thảo luận về tuyên bố vì nó thường được sử dụng. Trong phần tiếp theo, tôi sẽ xem xét chi tiết triển khai và chỉ ra cách viết các đối tượng để sử dụng với câu lệnh này.

Câu lệnh 'with' là cấu trúc luồng điều khiển mới có cấu trúc cơ bản là

với biểu thức [dưới dạng biến]:
     khối

Biểu thức được đánh giá và nó sẽ tạo ra một đối tượng hỗ trợ giao thức quản lý ngữ cảnh (nghĩa là có các phương thức __enter__()__exit__().

__enter__() của đối tượng được gọi trước khi with-block được thực thi và do đó có thể chạy mã thiết lập. Nó cũng có thể trả về một giá trị được gắn với tên variable, nếu được đưa ra. (Lưu ý cẩn thận rằng variablenot được gán kết quả của expression.)

Sau khi thực hiện xong with-block, phương thức __exit__() của đối tượng sẽ được gọi, ngay cả khi khối đưa ra một ngoại lệ và do đó có thể chạy mã dọn dẹp.

Để kích hoạt câu lệnh trong Python 2.5, bạn cần thêm lệnh sau vào mô-đun của mình

từ __future__ nhập bằng_statement

Câu lệnh sẽ luôn được bật trong Python 2.6.

Một số đối tượng Python tiêu chuẩn hiện hỗ trợ giao thức quản lý ngữ cảnh và có thể được sử dụng với câu lệnh 'with'. Các đối tượng tệp là một ví dụ:

với open('/etc/passwd', 'r')  f:
    cho dòng trong f:
        dòng in
        ... thêm  xử  ...

Sau khi câu lệnh này được thực thi, đối tượng tệp trong f sẽ tự động bị đóng, ngay cả khi vòng lặp for đưa ra một ngoại lệ giữa chừng trong khối.

Ghi chú

Trong trường hợp này, f chính là đối tượng được tạo bởi open(), vì __enter__() trả về self.

Các biến điều kiện và khóa của mô-đun threading cũng hỗ trợ câu lệnh 'with':

lock = threading.Lock()
 khóa:
    phần  # Critical
    ...

Khóa được lấy trước khi khối được thực thi và luôn được giải phóng sau khi khối hoàn tất.

Hàm localcontext() mới trong mô-đun decimal giúp dễ dàng lưu và khôi phục bối cảnh thập phân hiện tại, gói gọn các đặc tính làm tròn và độ chính xác mong muốn cho các phép tính:

từ nhập thập phân Thập phân, Ngữ cảnh, ngữ cảnh cục bộ

# Displays với độ chính xác mặc định là 28 chữ số
v = Số thập phân('578')
in v.sqrt()

với bối cảnh cục bộ(Ngữ cảnh(prec=16)):
     # All trong khối này sử dụng độ chính xác 16 chữ số.
    Ngữ cảnh ban đầu của # The được khôi phục khi thoát khỏi khối.
    in v.sqrt()

Viết trình quản lý bối cảnh

Nhìn sâu hơn, câu lệnh 'with' khá phức tạp. Hầu hết mọi người sẽ chỉ sử dụng 'with' cùng với các đối tượng hiện có và không cần biết những chi tiết này, vì vậy bạn có thể bỏ qua phần còn lại của phần này nếu muốn. Tác giả của các đối tượng mới sẽ cần hiểu chi tiết về cách triển khai cơ bản và nên tiếp tục đọc.

Giải thích cấp cao về giao thức quản lý bối cảnh là:

  • Biểu thức được đánh giá và sẽ tạo ra một đối tượng được gọi là "trình quản lý ngữ cảnh". Trình quản lý bối cảnh phải có các phương thức __enter__()__exit__().

  • Phương thức __enter__() của trình quản lý bối cảnh được gọi. Giá trị trả về được gán cho VAR. Nếu không có mệnh đề 'as VAR', giá trị sẽ bị loại bỏ.

  • Mã trong BLOCK được thực thi.

  • Nếu BLOCK đưa ra một ngoại lệ, __exit__(type, value, traceback) sẽ được gọi với các chi tiết ngoại lệ, các giá trị tương tự được trả về bởi sys.exc_info(). Giá trị trả về của phương thức sẽ kiểm soát xem ngoại lệ có được tái xuất hiện hay không: bất kỳ giá trị sai nào cũng sẽ tái xuất hiện ngoại lệ và True sẽ ngăn chặn ngoại lệ đó. Bạn sẽ hiếm khi muốn loại bỏ ngoại lệ, bởi vì nếu bạn làm như vậy thì tác giả của mã chứa câu lệnh 'with' sẽ không bao giờ nhận ra có điều gì sai.

  • Nếu BLOCK không đưa ra ngoại lệ thì phương thức __exit__() vẫn được gọi, nhưng type, valuetraceback đều là None.

Hãy suy nghĩ thông qua một ví dụ. Tôi sẽ không trình bày mã chi tiết mà chỉ phác thảo các phương thức cần thiết cho cơ sở dữ liệu hỗ trợ các giao dịch.

(Dành cho những người không quen với thuật ngữ cơ sở dữ liệu: một tập hợp các thay đổi đối với cơ sở dữ liệu được nhóm thành một giao dịch. Các giao dịch có thể được thực hiện, nghĩa là tất cả các thay đổi được ghi vào cơ sở dữ liệu hoặc được khôi phục, nghĩa là tất cả các thay đổi đều bị loại bỏ và cơ sở dữ liệu không thay đổi. Xem bất kỳ sách giáo khoa cơ sở dữ liệu nào để biết thêm thông tin.)

Giả sử có một đối tượng đại diện cho kết nối cơ sở dữ liệu. Mục tiêu của chúng tôi là cho phép người dùng viết mã như thế này

db_connection=Kết nối  sở dữ liệu()
với db_connection  con trỏ:
    con trỏ.execute('chèn vào ...')
    con trỏ.execute('xóa khỏi ...')
    # ... thêm hoạt động ...

Giao dịch phải được cam kết nếu mã trong khối chạy hoàn hảo hoặc được khôi phục nếu có ngoại lệ. Đây là giao diện cơ bản của DatabaseConnection mà tôi giả sử:

Kết nối  sở dữ liệu lớp:
    giao diện # Database
    con trỏ def (tự):
        "Trả về một đối tượng con trỏ và bắt đầu một giao dịch mới"
    def cam kết (tự):
        "Cam kết giao dịch hiện tại"
    khôi phục def (tự):
        "Quay lại giao dịch hiện tại"

Phương pháp __enter__() khá dễ dàng, chỉ cần bắt đầu một giao dịch mới. Đối với ứng dụng này, đối tượng con trỏ thu được sẽ là một kết quả hữu ích nên phương thức sẽ trả về nó. Sau đó, người dùng có thể thêm as cursor vào câu lệnh 'with' của họ để liên kết con trỏ với tên biến.

Kết nối  sở dữ liệu lớp:
    ...
    def __enter__ (tự):
        # Code để bắt đầu giao dịch mới
        con trỏ = self.cursor()
        con trỏ trở lại

Phương pháp __exit__() phức tạp nhất vì đó là nơi phải thực hiện hầu hết công việc. Phương pháp này phải kiểm tra xem có ngoại lệ xảy ra hay không. Nếu không có ngoại lệ, giao dịch được cam kết. Giao dịch được khôi phục nếu có ngoại lệ.

Trong đoạn mã bên dưới, quá trình thực thi sẽ nằm ở phần cuối của hàm, trả về giá trị mặc định là None. None là sai nên ngoại lệ sẽ tự động được đưa ra lại. Nếu muốn, bạn có thể nói rõ hơn và thêm câu lệnh return vào vị trí được đánh dấu.

Kết nối  sở dữ liệu lớp:
    ...
    def __exit__ (tự, loại, giá trị, tb):
        nếu tb  Không:
            ngoại lệ # No, vì vậy hãy cam kết
            tự.commit()
        khác:
            # Exception đã xảy ra nên hãy quay lại.
            self.rollback()
            # return Sai

Mô-đun ngữ cảnh

Mô-đun contextlib mới cung cấp một số chức năng và một trình trang trí hữu ích cho việc ghi các đối tượng để sử dụng với câu lệnh 'with'.

Trình trang trí được gọi là contextmanager() và cho phép bạn viết một hàm tạo duy nhất thay vì xác định một lớp mới. Trình tạo sẽ mang lại chính xác một giá trị. Mã lên tới yield sẽ được thực thi dưới dạng phương thức __enter__() và giá trị mang lại sẽ là giá trị trả về của phương thức sẽ được liên kết với biến trong mệnh đề as của câu lệnh 'with', nếu có. Mã sau yield sẽ được thực thi theo phương thức __exit__(). Bất kỳ ngoại lệ nào được đưa ra trong khối sẽ được đưa ra bởi câu lệnh yield.

Ví dụ về cơ sở dữ liệu của chúng tôi từ phần trước có thể được viết bằng cách sử dụng trình trang trí này như:

từ trình quản  bối cảnh nhập khẩu contextlib

@contextmanager
def db_transaction (kết nối):
    con trỏ = kết nối.cursor()
    thử:
        con trỏ năng suất
    ngoại trừ:
        kết nối.rollback()
        nâng cao
    khác:
        kết nối.commit()

db = Kết nối  sở dữ liệu()
với db_transaction(db) làm con trỏ:
    ...

Mô-đun contextlib cũng có chức năng nested(mgr1, mgr2, ...) kết hợp một số trình quản lý ngữ cảnh để bạn không cần phải viết các câu lệnh 'with' lồng nhau. Trong ví dụ này, câu lệnh 'with' vừa bắt đầu giao dịch cơ sở dữ liệu vừa thu được khóa luồng

lock = threading.Lock()
với (db_transaction(db), lock) lồng nhau  (con trỏ, đã khóa):
    ...

Cuối cùng, hàm closing(object) trả về object để nó có thể được liên kết với một biến và gọi object.close ở cuối khối.

nhập urllib, sys
từ việc đóng nhập ngữ cảnh

với việc đóng(urllib.urlopen('http://www.yahoo.com')) as f:
    cho dòng trong f:
        sys.stdout.write(dòng)

Xem thêm

PEP 343 - Câu lệnh "với"

PEP được viết bởi Guido van Rossum và Nick Coghlan; được thực hiện bởi Mike Bland, Guido van Rossum và Neal Norwitz. Zz002zz hiển thị mã được tạo cho câu lệnh 'with', mã này có thể hữu ích trong việc tìm hiểu cách hoạt động của câu lệnh.

Tài liệu dành cho mô-đun contextlib.

PEP 352: Ngoại lệ đối với các lớp kiểu mới

Các lớp ngoại lệ giờ đây có thể là các lớp kiểu mới, không chỉ là các lớp cổ điển và lớp Exception tích hợp sẵn cũng như tất cả các ngoại lệ tích hợp tiêu chuẩn (NameError, ValueError, v.v.) hiện là các lớp kiểu mới.

Hệ thống phân cấp kế thừa cho các ngoại lệ đã được sắp xếp lại một chút. Trong 2.5, các mối quan hệ kế thừa là:

BaseException # New trong Python 2.5
|- Bàn phímNgắt
|- SystemExit
|- Ngoại lệ
   |- (tất cả các ngoại lệ tích hợp hiện tại khác)

Việc sắp xếp lại này được thực hiện vì mọi người thường muốn nắm bắt tất cả các ngoại lệ cho thấy lỗi chương trình. Tuy nhiên, KeyboardInterruptSystemExit không phải là lỗi và thường thể hiện một hành động rõ ràng, chẳng hạn như người dùng nhấn Control-C hoặc gọi mã sys.exit(). Một except: trần sẽ bắt được tất cả các ngoại lệ, vì vậy bạn thường cần liệt kê KeyboardInterruptSystemExit để nâng cấp lại chúng. Mẫu thông thường là:

thử:
    ...
ngoại trừ (KeyboardInterrupt, SystemExit):
    nâng cao
ngoại trừ:
    lỗi # Log...
    # Continue chạy chương trình...

Trong Python 2.5, giờ đây bạn có thể viết except Exception để đạt được kết quả tương tự, nắm bắt tất cả các ngoại lệ thường chỉ ra lỗi nhưng chỉ để lại KeyboardInterruptSystemExit. Như những phiên bản trước, except: trần vẫn bắt được mọi ngoại lệ.

Mục tiêu của Python 3.0 là yêu cầu bất kỳ lớp nào được nêu ra như một ngoại lệ phải bắt nguồn từ BaseException hoặc một số hậu duệ của BaseException và các bản phát hành trong tương lai trong chuỗi Python 2.x có thể bắt đầu thực thi ràng buộc này. Vì vậy, tôi khuyên bạn nên bắt đầu tạo tất cả các lớp ngoại lệ bắt nguồn từ Exception ngay bây giờ. Có ý kiến ​​cho rằng nên xóa biểu mẫu except: trần trong Python 3.0, nhưng Guido van Rossum vẫn chưa quyết định có nên thực hiện việc này hay không.

Việc tăng chuỗi dưới dạng ngoại lệ, như trong câu lệnh raise "Error occurred", không được dùng nữa trong Python 2.5 và sẽ kích hoạt cảnh báo. Mục đích là có thể loại bỏ tính năng ngoại lệ chuỗi trong một số bản phát hành.

Xem thêm

PEP 352 - Siêu lớp bắt buộc cho các trường hợp ngoại lệ

PEP được viết bởi Brett Cannon và Guido van Rossum; được thực hiện bởi Brett Cannon.

PEP 353: Sử dụng ssize_t làm loại chỉ mục

Một thay đổi trên phạm vi rộng đối với C API của Python, sử dụng định nghĩa loại Py_ssize_t mới thay vì int, sẽ cho phép trình thông dịch xử lý nhiều dữ liệu hơn trên nền tảng 64-bit. Thay đổi này không ảnh hưởng đến dung lượng của Python trên nền tảng 32 bit.

Nhiều phần khác nhau của trình thông dịch Python đã sử dụng loại int của C để lưu trữ kích thước hoặc số lượng; ví dụ: số lượng mục trong danh sách hoặc bộ dữ liệu được lưu trữ trong int. Trình biên dịch C cho hầu hết các nền tảng 64 bit vẫn xác định int là loại 32 bit, do đó, điều đó có nghĩa là các danh sách chỉ có thể chứa tối đa 2**31 - 1 = 2147483647 mục. (Thực tế có một số mô hình lập trình khác nhau mà trình biên dịch C 64-bit có thể sử dụng -- xem https://unix.org/version2/whatsnew/lp64_wp.html để thảo luận -- nhưng mô hình phổ biến nhất có sẵn là int là 32 bit.)

Giới hạn 2147483647 mục không thực sự quan trọng trên nền tảng 32 bit vì bạn sẽ hết bộ nhớ trước khi đạt giới hạn độ dài. Mỗi mục danh sách yêu cầu không gian cho một con trỏ, có kích thước 4 byte, cộng với không gian cho PyObject đại diện cho mục đó. 2147483647*4 đã có nhiều byte hơn mức không gian địa chỉ 32 bit có thể chứa.

Tuy nhiên, có thể giải quyết nhiều bộ nhớ đó trên nền tảng 64 bit. Các con trỏ cho một danh sách có kích thước như vậy sẽ chỉ cần 16 GiB dung lượng, do đó, không có gì là vô lý khi các lập trình viên Python có thể xây dựng các danh sách lớn như vậy. Do đó, trình thông dịch Python phải được thay đổi để sử dụng một số loại khác ngoài int và đây sẽ là loại 64 bit trên nền tảng 64 bit. Thay đổi này sẽ gây ra sự không tương thích trên các máy 64-bit, do đó, việc chuyển đổi được coi là đáng giá ngay bây giờ, trong khi số lượng người dùng 64-bit vẫn còn tương đối ít. (Trong 5 hoặc 10 năm nữa, chúng tôi có thể sử dụng all trên các máy 64-bit và quá trình chuyển đổi khi đó sẽ khó khăn hơn.)

Sự thay đổi này ảnh hưởng mạnh mẽ nhất đến các tác giả của mô-đun mở rộng C. Các chuỗi và loại vùng chứa Python như danh sách và bộ dữ liệu hiện sử dụng Py_ssize_t để lưu trữ kích thước của chúng. Các hàm như PyList_Size() hiện trả về Py_ssize_t. Do đó, mã trong các mô-đun mở rộng có thể cần phải thay đổi một số biến thành Py_ssize_t.

Các hàm PyArg_ParseTuple()Py_BuildValue() có mã chuyển đổi mới, n, cho Py_ssize_t. Theo mặc định, s#t# của PyArg_ParseTuple() vẫn xuất ra int, nhưng bạn có thể xác định macro PY_SSIZE_T_CLEAN trước khi bao gồm Python.h để khiến chúng trả về Py_ssize_t.

PEP 353 có một phần về nguyên tắc chuyển đổi mà tác giả tiện ích mở rộng nên đọc để tìm hiểu về cách hỗ trợ nền tảng 64-bit.

Xem thêm

PEP 353 - Sử dụng ssize_t làm loại chỉ mục

PEP được viết và triển khai bởi Martin von Löwis.

PEP 357: Phương thức '__index__'

Các nhà phát triển NumPy gặp phải một vấn đề chỉ có thể giải quyết bằng cách thêm một phương thức đặc biệt mới, __index__(). Khi sử dụng ký hiệu lát cắt, như trong [start:stop:step], các giá trị của chỉ mục start, stopstep đều phải là số nguyên hoặc số nguyên dài. NumPy định nghĩa nhiều loại số nguyên chuyên dụng tương ứng với các số nguyên không dấu và có dấu gồm 8, 16, 32 và 64 bit, nhưng không có cách nào để báo hiệu rằng các loại này có thể được sử dụng làm chỉ mục lát cắt.

Việc cắt lát không thể chỉ sử dụng phương thức __int__() hiện có vì phương thức đó cũng được sử dụng để thực hiện ép buộc đối với các số nguyên. Nếu việc cắt được sử dụng __int__(), các số có dấu phẩy động cũng sẽ trở thành chỉ mục lát cắt hợp pháp và đó rõ ràng là một hành vi không mong muốn.

Thay vào đó, một phương thức đặc biệt mới gọi là __index__() đã được thêm vào. Nó không có đối số và trả về một số nguyên cho chỉ mục lát cắt để sử dụng. Ví dụ:

lớp C:
    def __index__ (tự):
        trả về self.value

Giá trị trả về phải là số nguyên Python hoặc số nguyên dài. Trình thông dịch sẽ kiểm tra xem loại được trả về có đúng không và đưa ra TypeError nếu yêu cầu này không được đáp ứng.

Một khe nb_index tương ứng đã được thêm vào cấu trúc PyNumberMethods cấp C để cho phép các tiện ích mở rộng C triển khai giao thức này. PyNumber_Index(obj) có thể được sử dụng trong mã mở rộng để gọi hàm __index__() và truy xuất kết quả của nó.

Xem thêm

PEP 357 - Cho phép sử dụng bất kỳ đối tượng nào để cắt lát

PEP được viết và triển khai bởi Travis Oliphant.

Những thay đổi ngôn ngữ khác

Dưới đây là tất cả những thay đổi mà Python 2.5 thực hiện đối với ngôn ngữ Python cốt lõi.

  • Loại dict có một hook mới để cho phép các lớp con cung cấp giá trị mặc định khi khóa không có trong từ điển. Khi không tìm thấy khóa, phương thức __missing__(key) của từ điển sẽ được gọi. Hook này được sử dụng để triển khai lớp defaultdict mới trong mô-đun collections. Ví dụ sau định nghĩa một từ điển trả về 0 cho bất kỳ khóa nào bị thiếu:

    lớp zerodict (dict):
        def __missing__ (tự, khóa):
            trở về 0
    
    d = zerodict({1:1, 2:2})
    in d[1], d[2] # Prints 1, 2
    in d[3], d[4] # Prints 0, 0
    
  • Cả chuỗi 8 bit và chuỗi Unicode đều có các phương thức partition(sep)rpartition(sep) mới giúp đơn giản hóa trường hợp sử dụng phổ biến.

    Phương thức find(S) thường được sử dụng để lấy chỉ mục, sau đó dùng để cắt chuỗi và lấy các phần nằm trước và sau dấu phân cách. partition(sep) cô đọng mẫu này thành một lệnh gọi phương thức duy nhất trả về 3 bộ chứa chuỗi con trước dấu phân cách, chính dấu phân cách và chuỗi con sau dấu phân cách. Nếu không tìm thấy dấu phân cách thì phần tử đầu tiên của bộ dữ liệu là toàn bộ chuỗi và hai phần tử còn lại trống. rpartition(sep) cũng trả về 3 bộ nhưng bắt đầu tìm kiếm từ cuối chuỗi; r là viết tắt của 'đảo ngược'.

    Một số ví dụ:

    >>> ('http://www.python.org').partition('://')
    ('http', '://', 'www.python.org')
    >>> ('file:/usr/share/doc/index.html').partition('://')
    ('file:/usr/share/doc/index.html', '', '')
    >>> (u'Chủ đề: một câu hỏi nhanh').partition(':')
    (u'Chủ đề', u':', u' một câu hỏi nhanh')
    >>> 'www.python.org'.rpartition('.')
    ('www.python', '.', 'org')
    >>> 'www.python.org'.rpartition(':')
    ('', '', 'www.python.org')
    

    (Được thực hiện bởi Fredrik Lundh theo gợi ý của Raymond Hettinger.)

  • Các phương thức startswith()endswith() của các loại chuỗi hiện chấp nhận các bộ chuỗi để kiểm tra.

    def is_image_file (tên tệp):
        trả về tên tệp.endswith(('.gif', '.jpg', '.tiff'))
    

    (Được thực hiện bởi Georg Brandl theo gợi ý của Tom Lynn.)

  • Các hàm dựng sẵn min()max() đã nhận được tham số từ khóa key tương tự với đối số key cho sort(). Tham số này cung cấp một hàm nhận một đối số duy nhất và được gọi cho mọi giá trị trong danh sách; min()/max() sẽ trả về phần tử có giá trị trả về nhỏ nhất/lớn nhất từ ​​hàm này. Ví dụ: để tìm chuỗi dài nhất trong danh sách, bạn có thể thực hiện

    L = ['trung bình', 'dài nhất', 'ngắn']
    # Prints 'dài nhất'
    in tối đa(L, key=len)
    # Prints 'ngắn', vì theo từ điển 'ngắn' có giá trị lớn nhất
    in tối đa (L)
    

    (Được đóng góp bởi Steven Bethard và Raymond Hettinger.)

  • Hai hàm dựng sẵn mới, any()all(), đánh giá xem một trình lặp có chứa bất kỳ giá trị đúng hay sai nào không. any() trả về True nếu bất kỳ giá trị nào được trình vòng lặp trả về là đúng; nếu không nó sẽ trả về False. all() chỉ trả về True nếu tất cả các giá trị được trình vòng lặp trả về đánh giá là đúng. (Được đề xuất bởi Guido van Rossum và được thực hiện bởi Raymond Hettinger.)

  • Kết quả của phương thức __hash__() của một lớp bây giờ có thể là số nguyên dài hoặc số nguyên thông thường. Nếu trả về một số nguyên dài thì hàm băm của giá trị đó sẽ được lấy. Trong các phiên bản trước, giá trị băm được yêu cầu phải là số nguyên thông thường, nhưng trong phiên bản 2.5, id() tích hợp đã được thay đổi để luôn trả về các số không âm và người dùng dường như thường sử dụng id(self) trong các phương thức __hash__() (mặc dù điều này không được khuyến khích).

  • ASCII hiện là mã hóa mặc định cho các mô-đun. Bây giờ, đây là lỗi cú pháp nếu một mô-đun chứa các chuỗi ký tự có ký tự 8 bit nhưng không có phần khai báo mã hóa. Trong Python 2.4, điều này gây ra cảnh báo chứ không phải lỗi cú pháp. Xem PEP 263 để biết cách khai báo mã hóa của mô-đun; ví dụ: bạn có thể thêm một dòng như thế này ở gần đầu tệp nguồn:

    # -zz000zz-
    
  • Một cảnh báo mới, UnicodeWarning, được kích hoạt khi bạn cố so sánh chuỗi Unicode và chuỗi 8 bit không thể chuyển đổi sang Unicode bằng cách sử dụng mã hóa ASCII mặc định. Kết quả so sánh là sai:

    >>> chr(128) == unichr(128) # Can không chuyển đổi chr(128) sang Unicode
    __main__:1: UnicodeCảnh báo: So sánh bằng nhau Unicode không thành công
      để chuyển đổi cả hai đối số sang Unicode - giải thích chúng
      như không bình đẳng
    sai
    >>> chr(127) == unichr(127) # chr(127) có thể được chuyển đổi
    đúng
    

    Trước đây, điều này sẽ gây ra ngoại lệ UnicodeDecodeError, nhưng ở phiên bản 2.5, điều này có thể dẫn đến các vấn đề khó hiểu khi truy cập từ điển. Nếu bạn tra cứu unichr(128)chr(128) đang được sử dụng làm khóa, bạn sẽ nhận được một ngoại lệ UnicodeDecodeError. Những thay đổi khác trong 2.5 dẫn đến ngoại lệ này được nêu ra thay vì bị loại bỏ bởi mã trong dictobject.c thực hiện từ điển.

    Việc đưa ra một ngoại lệ cho sự so sánh như vậy là hoàn toàn chính xác, nhưng thay đổi này có thể đã làm hỏng mã, vì vậy thay vào đó, UnicodeWarning đã được giới thiệu.

    (Được thực hiện bởi Marc-André Lemburg.)

  • Một lỗi mà các lập trình viên Python đôi khi mắc phải là quên đưa mô-đun __init__.py vào thư mục gói. Việc gỡ lỗi này có thể gây nhầm lẫn và thường yêu cầu chạy Python bằng khóa chuyển -v để ghi lại tất cả các đường dẫn được tìm kiếm. Trong Python 2.5, cảnh báo ImportWarning mới được kích hoạt khi quá trình nhập có thể chọn một thư mục dưới dạng gói nhưng không tìm thấy __init__.py. Cảnh báo này được âm thầm bỏ qua theo mặc định; cung cấp tùy chọn -Wd khi chạy tệp thực thi Python để hiển thị thông báo cảnh báo. (Được thực hiện bởi Thomas Wouters.)

  • Danh sách các lớp cơ sở trong định nghĩa lớp bây giờ có thể trống. Ví dụ: điều này hiện là hợp pháp:

    lớp C():
        vượt qua
    

    (Được thực hiện bởi Brett Cannon.)

Thay đổi thông dịch viên tương tác

Trong trình thông dịch tương tác, quitexit từ lâu đã là các chuỗi để người dùng mới nhận được thông báo hữu ích khi họ cố gắng thoát:

>>> bỏ cuộc
'Sử dụng Ctrl-D (tức là EOF) để thoát.'

Trong Python 2.5, quitexit hiện là các đối tượng vẫn tạo ra các biểu diễn chuỗi của chính chúng nhưng cũng có thể gọi được. Những người mới dùng thử quit() hoặc exit() giờ đây sẽ thoát khỏi trình thông dịch như họ mong đợi. (Được thực hiện bởi Georg Brandl.)

Tệp thực thi Python hiện chấp nhận các tùy chọn dài tiêu chuẩn --help--version; trên Windows, nó cũng chấp nhận tùy chọn /? để hiển thị thông báo trợ giúp. (Được thực hiện bởi Georg Brandl.)

Tối ưu hóa

Một số tính năng tối ưu hóa đã được phát triển tại cuộc chạy nước rút NeedForSpeed, một sự kiện được tổ chức tại Reykjavik, Iceland, từ ngày 21 đến ngày 28 tháng 5 năm 2006. Cuộc chạy nước rút tập trung vào cải tiến tốc độ triển khai CPython và được tài trợ bởi EWT LLC với sự hỗ trợ địa phương từ CCP Games. Những tối ưu hóa được thêm vào lần chạy nước rút này được đánh dấu đặc biệt trong danh sách sau.

  • Khi chúng được giới thiệu trong Python 2.4, các kiểu setfrozenset tích hợp sẵn được xây dựng dựa trên kiểu từ điển của Python. Trong 2.5, cấu trúc dữ liệu nội bộ đã được tùy chỉnh để triển khai các bộ và kết quả là các bộ sẽ sử dụng ít bộ nhớ thứ ba hơn và nhanh hơn một chút. (Được thực hiện bởi Raymond Hettinger.)

  • Tốc độ của một số thao tác Unicode, chẳng hạn như tìm chuỗi con, tách chuỗi, mã hóa và giải mã bản đồ ký tự, đã được cải thiện. (Các cải tiến về tìm kiếm và phân tách chuỗi con đã được Fredrik Lundh và Andrew Dalke thêm vào tại cuộc chạy nước rút NeedForSpeed. Bản đồ ký tự được cải tiến bởi Walter Dörwald và Martin von Löwis.)

  • Hàm long(str, base) hiện nhanh hơn trên các chuỗi chữ số dài vì tính toán được ít kết quả trung gian hơn. Đỉnh cao dành cho các chuỗi có khoảng 800--1000 chữ số trong đó hàm nhanh hơn 6 lần. (Được đóng góp bởi Alan McIntyre và cam kết tại cuộc chạy nước rút NeedForSpeed.)

  • Hiện tại, việc kết hợp việc lặp lại một tệp với for line in file và gọi các phương thức read()/readline()/readlines() của đối tượng tệp là bất hợp pháp. Lặp lại sử dụng bộ đệm bên trong và các phương thức read*() không sử dụng bộ đệm đó. Thay vào đó, chúng sẽ trả về dữ liệu theo bộ đệm, khiến dữ liệu xuất hiện không theo thứ tự. Việc kết hợp phép lặp và các phương thức này bây giờ sẽ kích hoạt ValueError từ phương thức read*(). (Được thực hiện bởi Thomas Wouters.)

  • Mô-đun struct hiện biên dịch các chuỗi định dạng cấu trúc thành một biểu diễn bên trong và lưu trữ biểu diễn này vào bộ nhớ đệm, giúp tăng tốc 20%. (Được đóng góp bởi Bob Ippolito tại cuộc chạy nước rút NeedForSpeed.)

  • Mô-đun re được tăng tốc 1 hoặc 2% bằng cách chuyển sang các hàm cấp phát của Python thay vì malloc()free() của hệ thống. (Được đóng góp bởi Jack Diederich tại cuộc chạy nước rút NeedForSpeed.)

  • Trình tối ưu hóa lỗ nhìn trộm của trình tạo mã hiện thực hiện việc gấp các biểu thức liên tục đơn giản. Nếu bạn viết một cái gì đó như a = 2+3, trình tạo mã sẽ thực hiện phép tính số học và tạo ra mã tương ứng với a = 5. (Được đề xuất và thực hiện bởi Raymond Hettinger.)

  • Giờ đây, lệnh gọi hàm nhanh hơn vì đối tượng mã hiện giữ khung được hoàn thành gần đây nhất ("khung zombie") trong trường bên trong của đối tượng mã, sử dụng lại khung đó vào lần tiếp theo đối tượng mã được gọi. (Bản vá gốc của Michael Hudson, được sửa đổi bởi Armin Rigo và Richard Jones; được cam kết tại cuộc chạy nước rút NeedForSpeed.) Các đối tượng khung cũng nhỏ hơn một chút, điều này có thể cải thiện vị trí bộ đệm và giảm mức sử dụng bộ nhớ một chút. (Được đóng góp bởi Neal Norwitz.)

  • Các ngoại lệ tích hợp sẵn của Python hiện là các lớp kiểu mới, một thay đổi giúp tăng tốc độ khởi tạo đáng kể. Do đó, việc xử lý ngoại lệ trong Python 2.5 nhanh hơn khoảng 30% so với 2.4. (Được đóng góp bởi Richard Jones, Georg Brandl và Sean Reifschneider tại cuộc chạy nước rút NeedForSpeed.)

  • Việc nhập bây giờ sẽ lưu vào bộ nhớ đệm các đường dẫn đã thử, ghi lại xem chúng có tồn tại hay không để trình thông dịch thực hiện ít lệnh gọi open()stat() hơn khi khởi động. (Được đóng góp bởi Martin von Löwis và Georg Brandl.)

Các mô-đun mới, cải tiến và loại bỏ

Thư viện chuẩn nhận được nhiều cải tiến và sửa lỗi trong Python 2.5. Đây là danh sách một phần những thay đổi đáng chú ý nhất, được sắp xếp theo thứ tự bảng chữ cái theo tên mô-đun. Tham khảo tệp Misc/NEWS trong cây nguồn để biết danh sách thay đổi đầy đủ hơn hoặc xem qua nhật ký SVN để biết tất cả chi tiết.

  • Mô-đun audioop hiện hỗ trợ mã hóa a-LAW và mã cho mã hóa u-LAW đã được cải thiện. (Được đóng góp bởi Lars Immisch.)

  • Mô-đun codecs đã được hỗ trợ cho các codec gia tăng. Hàm codec.lookup() hiện trả về một phiên bản CodecInfo thay vì một bộ dữ liệu. Các phiên bản CodecInfo hoạt động giống như một bộ 4 để duy trì khả năng tương thích ngược nhưng cũng có các thuộc tính encode, decode, incrementalencoder, incrementaldecoder, streamwriterstreamreader. Các codec gia tăng có thể nhận đầu vào và tạo đầu ra theo nhiều khối; đầu ra giống như khi toàn bộ đầu vào được đưa vào codec không tăng dần. Xem tài liệu mô-đun codecs để biết chi tiết. (Được thiết kế và thực hiện bởi Walter Dörwald.)

  • Mô-đun collections có một loại mới, defaultdict, phân lớp loại dict tiêu chuẩn. Loại mới chủ yếu hoạt động giống như một từ điển nhưng tạo ra một giá trị mặc định khi không có khóa, tự động thêm nó vào từ điển cho giá trị khóa được yêu cầu.

    Đối số đầu tiên cho hàm tạo của defaultdict là một hàm xuất xưởng được gọi bất cứ khi nào một khóa được yêu cầu nhưng không tìm thấy. Hàm xuất xưởng này không nhận đối số, vì vậy bạn có thể sử dụng các hàm tạo kiểu tích hợp sẵn như list() hoặc int(). Ví dụ: bạn có thể tạo chỉ mục các từ dựa trên chữ cái đầu tiên của chúng như sau:

    từ = """Nel mezzo del cammin di nostra vita
    mi ritrowai per una selva oscura
    che la diritta qua era smarrita""".low().split()
    
    chỉ mục = defaultdict(list)
    
    cho w trong từ:
        init_letter = w[0]
        chỉ mục[init_letter].append(w)
    

    Việc in index sẽ cho kết quả đầu ra sau:

    defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'],
            'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'],
            'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'],
            'p': ['per'], 's': ['selva', 'smarrita'],
            'r': ['ritroai'], 'u': ['una'], 'v': ['vita', 'via']}
    

    (Được đóng góp bởi Guido van Rossum.)

  • Loại hàng đợi hai đầu deque do mô-đun collections cung cấp hiện có phương thức remove(value) loại bỏ lần xuất hiện đầu tiên của value trong hàng đợi, tăng ValueError nếu không tìm thấy giá trị. (Được đóng góp bởi Raymond Hettinger.)

  • Mô-đun mới: Mô-đun contextlib chứa các hàm trợ giúp để sử dụng với câu lệnh 'with' mới. Xem phần Mô-đun ngữ cảnh để biết thêm về mô-đun này.

  • Mô-đun mới: Mô-đun cProfile là một triển khai C của mô-đun profile hiện có với chi phí hoạt động thấp hơn nhiều. Giao diện của mô-đun này giống như profile: bạn chạy cProfile.run('main()') để lập cấu hình một chức năng, có thể lưu dữ liệu cấu hình vào một tệp, v.v. Vẫn chưa biết liệu trình cấu hình Hotshot, cũng được viết bằng C nhưng không khớp với giao diện của mô-đun profile, có tiếp tục được duy trì trong các phiên bản Python sau này hay không. (Được đóng góp bởi Armin Rigo.)

    Ngoài ra, mô-đun pstats để phân tích dữ liệu được đo bằng trình lược tả hiện hỗ trợ chuyển hướng đầu ra tới bất kỳ đối tượng tệp nào bằng cách cung cấp đối số stream cho hàm tạo Stats. (Đóng góp bởi Skip Montanaro.)

  • Mô-đun csv, phân tích các tệp ở định dạng giá trị được phân tách bằng dấu phẩy, đã nhận được một số cải tiến và một số bản sửa lỗi. Bây giờ bạn có thể đặt kích thước tối đa tính bằng byte của một trường bằng cách gọi hàm csv.field_size_limit(new_limit); bỏ qua đối số new_limit sẽ trả về giới hạn hiện được đặt. Lớp reader hiện có thuộc tính line_num đếm số dòng vật lý được đọc từ nguồn; các bản ghi có thể trải dài trên nhiều dòng vật lý, vì vậy line_num không giống với số lượng bản ghi được đọc.

    Trình phân tích cú pháp CSV hiện nghiêm ngặt hơn về các trường được trích dẫn nhiều dòng. Trước đây, nếu một dòng kết thúc trong trường được trích dẫn mà không có ký tự dòng mới kết thúc thì một dòng mới sẽ được chèn vào trường được trả về. Hành vi này gây ra sự cố khi đọc các tệp chứa ký tự trả về đầu dòng trong các trường, do đó mã đã được thay đổi để trả về trường mà không chèn dòng mới. Kết quả là, nếu các dòng mới được nhúng trong các trường là quan trọng thì dữ liệu đầu vào phải được chia thành các dòng theo cách giữ nguyên các ký tự dòng mới.

    (Được đóng góp bởi Skip Montanaro và Andrew McNamara.)

  • Lớp datetime trong mô-đun datetime hiện có phương thức strptime(string, format) để phân tích chuỗi ngày tháng do Josh Spoerri đóng góp. Nó sử dụng các ký tự định dạng giống như time.strptime()time.strftime():

    nhập ngày giờ dưới dạng dt
    
    ts = dt.datetime.strptime('10:13:15 2006-03-07',
                              '%H:%M:%S %Y-%m-%d')
    
  • Phương thức SequenceMatcher.get_matching_blocks() trong mô-đun difflib hiện đảm bảo trả về danh sách tối thiểu các khối mô tả các chuỗi con phù hợp. Trước đây, thuật toán đôi khi sẽ chia một khối phần tử phù hợp thành hai mục trong danh sách. (Cải tiến bởi Tim Peters.)

  • Mô-đun doctest có tùy chọn SKIP để giữ cho một ví dụ không được thực thi. Điều này dành cho các đoạn mã là ví dụ sử dụng dành cho người đọc và không thực sự là trường hợp thử nghiệm.

    Tham số encoding đã được thêm vào hàm testfile() và lớp DocFileSuite để chỉ định mã hóa của tệp. Điều này giúp việc sử dụng các ký tự không phải ASCII dễ dàng hơn trong các thử nghiệm có trong chuỗi tài liệu. (Được đóng góp bởi Bjorn Tillenius.)

  • Gói email đã được cập nhật lên phiên bản 4.0. (Được đóng góp bởi Barry Warsaw.)

  • Mô-đun fileinput được thiết kế linh hoạt hơn. Tên tệp Unicode hiện đã được hỗ trợ và tham số mode mặc định là "r" đã được thêm vào hàm input() để cho phép mở tệp ở chế độ nhị phân hoặc universal newlines. Một tham số mới khác, openhook, cho phép bạn sử dụng một chức năng khác ngoài open() để mở các tệp đầu vào. Khi bạn lặp lại tập hợp các tệp, fileno() mới của đối tượng FileInput sẽ trả về bộ mô tả tệp cho tệp hiện đang mở. (Được đóng góp bởi Georg Brandl.)

  • Trong mô-đun gc, hàm get_count() mới trả về 3 bộ chứa số lượng bộ sưu tập hiện tại cho ba thế hệ GC. Đây là thông tin kế toán dành cho người thu gom rác; khi số lượng này đạt đến ngưỡng quy định, quá trình quét thu gom rác sẽ được thực hiện. Hàm gc.collect() hiện tại có đối số generation tùy chọn là 0, 1 hoặc 2 để chỉ định thế hệ nào sẽ thu thập. (Được đóng góp bởi Barry Warsaw.)

  • Các hàm nsmallest()nlargest() trong mô-đun heapq hiện hỗ trợ tham số từ khóa key tương tự như tham số được cung cấp bởi các hàm min()/max() và các phương thức sort(). Ví dụ:

    >>> nhập heapq
    >>> L = ["ngắn", 'trung bình', 'dài nhất', 'còn dài hơn']
    >>> heapq.nsmallest(2, L) # Return hai phần tử thấp nhất, theo từ điển
    ['còn dài hơn', 'dài nhất']
    >>> heapq.nsmallest(2, L, key=len) # Return hai phần tử ngắn nhất
    ['ngắn', 'trung bình']
    

    (Được đóng góp bởi Raymond Hettinger.)

  • Hàm itertools.islice() hiện chấp nhận None cho đối số bắt đầu và bước. Điều này làm cho nó tương thích hơn với các thuộc tính của các đối tượng lát cắt, do đó bây giờ bạn có thể viết như sau:

    s = slice(5) đối tượng lát cắt # Create
    itertools.islice(iterable, s.start, s.stop, s.step)
    

    (Được đóng góp bởi Raymond Hettinger.)

  • Chức năng format() trong mô-đun locale đã được sửa đổi và thêm hai chức năng mới là format_string()currency().

    Tham số val của hàm format() trước đây có thể là một chuỗi miễn là không xuất hiện nhiều hơn một mã xác định %char; bây giờ tham số phải có chính xác một ký hiệu %char và không có văn bản xung quanh. Một tham số monetary tùy chọn cũng được thêm vào, nếu là True, sẽ sử dụng các quy tắc của ngôn ngữ để định dạng tiền tệ khi đặt dấu phân cách giữa các nhóm ba chữ số.

    Để định dạng chuỗi có nhiều chỉ định %char, hãy sử dụng hàm format_string() mới hoạt động giống như format() nhưng cũng hỗ trợ trộn các chỉ định %char với văn bản tùy ý.

    Một chức năng currency() mới cũng được thêm vào để định dạng một số theo cài đặt của ngôn ngữ hiện tại.

    (Được đóng góp bởi Georg Brandl.)

  • Mô-đun mailbox đã được viết lại rất nhiều để bổ sung khả năng sửa đổi hộp thư ngoài việc đọc chúng. Một nhóm lớp mới bao gồm mbox, MHMaildir được sử dụng để đọc hộp thư và có phương thức add(message) để thêm thư, remove(key) để xóa thư và lock()/unlock() để khóa/mở khóa hộp thư. Ví dụ sau chuyển đổi hộp thư có định dạng maildir thành hộp thư có định dạng mbox:

    nhập hộp thư
    
    # 'factory=None' sử dụng email.Message.Message làm lớp đại diện
    tin nhắn # individual.
    src = hộp thư.Maildir('maildir', Factory=None)
    dest = inbox.mbox('/tmp/mbox')
    
    cho tin nhắn trong src:
        đích.add(tin nhắn)
    

    (Được đóng góp bởi Gregory K. Johnson. Nguồn tài trợ được cung cấp bởi Summer of Code năm 2005 của Google.)

  • Mô-đun mới: mô-đun msilib cho phép tạo tệp .msi và tệp CAB của Microsoft Installer. Một số hỗ trợ để đọc cơ sở dữ liệu .msi cũng được bao gồm. (Được đóng góp bởi Martin von Löwis.)

  • Mô-đun nis hiện hỗ trợ truy cập các miền khác với miền mặc định của hệ thống bằng cách cung cấp đối số domain cho các hàm nis.match()nis.maps(). (Được đóng góp bởi Ben Bell.)

  • Các chức năng itemgetter()attrgetter() của mô-đun operator hiện hỗ trợ nhiều trường. Một lệnh gọi như operator.attrgetter('a', 'b') sẽ trả về một hàm truy xuất các thuộc tính ab. Việc kết hợp tính năng mới này với tham số key của phương thức sort() cho phép bạn dễ dàng sắp xếp danh sách bằng nhiều trường. (Được đóng góp bởi Raymond Hettinger.)

  • Mô-đun optparse đã được cập nhật lên phiên bản 1.5.1 của thư viện Optik. Lớp OptionParser có thuộc tính epilog, một chuỗi sẽ được in sau thông báo trợ giúp và phương thức destroy() để phá vỡ các chu trình tham chiếu do đối tượng tạo ra. (Được đóng góp bởi Greg Ward.)

  • Mô-đun os đã trải qua một số thay đổi. Biến stat_float_times hiện được mặc định là true, nghĩa là os.stat() bây giờ sẽ trả về các giá trị thời gian dưới dạng số float. (Điều này không nhất thiết có nghĩa là os.stat() sẽ trả về thời gian chính xác đến từng phần của giây; không phải tất cả hệ thống đều hỗ trợ độ chính xác như vậy.)

    Các hằng số có tên os.SEEK_SET, os.SEEK_CURos.SEEK_END đã được thêm vào; đây là các tham số của hàm os.lseek(). Hai hằng số mới để khóa là os.O_SHLOCKos.O_EXLOCK.

    Hai chức năng mới, wait3()wait4(), đã được thêm vào. Chúng tương tự như hàm waitpid() chờ một tiến trình con thoát ra và trả về một bộ ID tiến trình cũng như trạng thái thoát của nó, nhưng wait3()wait4() trả về thông tin bổ sung. wait3() không lấy ID tiến trình làm đầu vào, vì vậy nó đợi bất kỳ tiến trình con nào thoát ra và trả về 3 bộ process-id, exit-status, resource-usage như được trả về từ hàm resource.getrusage(). wait4(pid) có ID tiến trình. (Được đóng góp bởi Chad J. Schroeder.)

    Trên FreeBSD, hàm os.stat() hiện trả về thời gian với độ phân giải nano giây và đối tượng được trả về hiện có st_genst_birthtime. Thuộc tính st_flags cũng có sẵn nếu nền tảng hỗ trợ nó. (Được đóng góp bởi Antti Louko và Diego Pettenò.)

  • Trình gỡ lỗi Python do mô-đun pdb cung cấp hiện có thể lưu trữ danh sách các lệnh để thực thi khi đạt đến điểm ngắt và quá trình thực thi dừng lại. Khi điểm dừng #1 đã được tạo, hãy nhập commands 1 và nhập một loạt lệnh sẽ được thực thi, kết thúc danh sách bằng end. Danh sách lệnh có thể bao gồm các lệnh tiếp tục thực thi, chẳng hạn như continue hoặc next. (Được đóng góp bởi Grégoire Dooms.)

  • Các mô-đun picklecPickle không còn chấp nhận giá trị trả về là None từ phương thức __reduce__(); thay vào đó, phương thức này phải trả về một bộ đối số. Khả năng trả về None không được dùng nữa trong Python 2.4, vì vậy việc này hoàn tất việc xóa tính năng này.

  • Mô-đun pkgutil, chứa nhiều chức năng tiện ích khác nhau để tìm gói, đã được cải tiến để hỗ trợ móc nhập của PEP 302 và hiện cũng hoạt động với các gói được lưu trữ trong kho lưu trữ định dạng ZIP. (Đóng góp bởi Phillip J. Eby.)

  • Bộ điểm chuẩn pybench của Marc-André Lemburg hiện được đưa vào thư mục Tools/pybench. Bộ pybench là một cải tiến của chương trình pystone.py thường được sử dụng vì pybench cung cấp số đo chi tiết hơn về tốc độ của trình thông dịch. Nó tính thời gian cho các hoạt động cụ thể như gọi hàm, cắt bộ dữ liệu, tra cứu phương thức và hoạt động số, thay vì thực hiện nhiều thao tác khác nhau và giảm kết quả xuống một số duy nhất như pystone.py.

  • Mô-đun pyexpat hiện sử dụng phiên bản 2.0 của trình phân tích cú pháp người nước ngoài. (Được đóng góp bởi Trent Mick.)

  • Lớp Queue do mô-đun Queue cung cấp có hai phương thức mới. join() chặn cho đến khi tất cả các mục trong hàng đợi được truy xuất và mọi công việc xử lý trên các mục đó đã được hoàn thành. Các luồng công nhân gọi phương thức mới khác, task_done(), để báo hiệu rằng quá trình xử lý một mục đã hoàn tất. (Được đóng góp bởi Raymond Hettinger.)

  • Các mô-đun regexregsub cũ không còn được dùng nữa kể từ Python 2.0, cuối cùng đã bị xóa. Các mô-đun đã xóa khác: statcache, tzparse, whrandom.

  • Cũng bị xóa: thư mục lib-old, bao gồm các mô-đun cổ như dircmpni, đã bị xóa. lib-old không có trên sys.path mặc định, vì vậy trừ khi chương trình của bạn thêm thư mục vào sys.path một cách rõ ràng, việc xóa này sẽ không ảnh hưởng đến mã của bạn.

  • Mô-đun rlcompleter không còn phụ thuộc vào việc nhập mô-đun readline và do đó hiện hoạt động trên các nền tảng không phải Unix. (Bản vá từ Robert Kiendl.)

  • Các lớp SimpleXMLRPCServerDocXMLRPCServer hiện có thuộc tính rpc_paths hạn chế các hoạt động XML-RPC trong một tập hợp giới hạn các đường dẫn URL; mặc định là chỉ cho phép '/''/RPC2'. Đặt rpc_paths thành None hoặc một bộ trống sẽ vô hiệu hóa việc kiểm tra đường dẫn này.

  • Mô-đun socket hiện hỗ trợ ổ cắm AF_NETLINK trên Linux nhờ bản vá của Philippe Biondi. Ổ cắm Netlink là một cơ chế dành riêng cho Linux để liên lạc giữa quy trình không gian người dùng và mã hạt nhân; một bài viết giới thiệu về chúng có tại https://www.linuxjournal.com/article/7356. Trong mã Python, các địa chỉ liên kết mạng được biểu diễn dưới dạng một bộ gồm 2 số nguyên, (pid, group_mask).

    Hai phương thức mới trên các đối tượng socket, recv_into(buffer)recvfrom_into(buffer), lưu trữ dữ liệu nhận được trong một đối tượng hỗ trợ giao thức bộ đệm thay vì trả về dữ liệu dưới dạng chuỗi. Điều này có nghĩa là bạn có thể đặt dữ liệu trực tiếp vào một mảng hoặc tệp ánh xạ bộ nhớ.

    Các đối tượng socket cũng có được các phương thức truy cập getfamily(), gettype()getproto() để truy xuất các giá trị họ, loại và giao thức cho socket.

  • Mô-đun mới: mô-đun spwd cung cấp các chức năng truy cập cơ sở dữ liệu mật khẩu bóng trên các hệ thống hỗ trợ mật khẩu bóng.

  • struct hiện nhanh hơn vì nó biên dịch các chuỗi định dạng thành các đối tượng Struct bằng các phương thức pack()unpack(). Điều này tương tự như cách mô-đun re cho phép bạn tạo các đối tượng biểu thức chính quy được biên dịch. Bạn vẫn có thể sử dụng các hàm pack()unpack() ở cấp độ mô-đun; họ sẽ tạo các đối tượng Struct và lưu chúng vào bộ nhớ đệm. Hoặc bạn có thể sử dụng trực tiếp các phiên bản Struct

    s = struct.Struct('ih3s')
    
    dữ liệu = s.pack(1972, 187, 'abc')
    năm, số, tên = s.unpack(data)
    

    Bạn cũng có thể đóng gói và giải nén dữ liệu đến và từ các đối tượng bộ đệm trực tiếp bằng các phương thức pack_into(buffer, offset, v1, v2, ...)unpack_from(buffer, offset). Điều này cho phép bạn lưu trữ dữ liệu trực tiếp vào một mảng hoặc một tệp ánh xạ bộ nhớ.

    (Các đối tượng Struct được Bob Ippolito triển khai tại cuộc chạy nước rút NeedForSpeed. Martin Blais đã thêm hỗ trợ cho các đối tượng đệm, cũng tại cuộc chạy nước rút NeedForSpeed.)

  • Các nhà phát triển Python đã chuyển từ CVS sang Subversion trong quá trình phát triển 2.5. Thông tin về phiên bản xây dựng chính xác có sẵn dưới dạng biến sys.subversion, bộ 3 của (interpreter-name, branch-name, revision-range). Ví dụ: tại thời điểm viết bài, bản sao 2.5 của tôi đang báo cáo ('CPython', 'trunk', '45313:45315').

    Thông tin này cũng có sẵn cho các tiện ích mở rộng C thông qua hàm Py_GetBuildInfo() trả về một chuỗi thông tin bản dựng như sau: "trunk:45355:45356M, Apr 13 2006, 07:42:19". (Được đóng góp bởi Barry Warsaw.)

  • Một hàm mới khác, sys._current_frames(), trả về các khung ngăn xếp hiện tại cho tất cả các luồng đang chạy dưới dạng từ điển ánh xạ các mã định danh luồng tới khung ngăn xếp trên cùng hiện đang hoạt động trong luồng đó tại thời điểm hàm được gọi. (Được đóng góp bởi Tim Peters.)

  • Lớp TarFile trong mô-đun tarfile hiện có phương thức extractall() trích xuất tất cả các thành viên từ kho lưu trữ vào thư mục làm việc hiện tại. Cũng có thể đặt một thư mục khác làm mục tiêu trích xuất và chỉ giải nén một tập hợp con các thành viên của kho lưu trữ.

    Giờ đây, quá trình nén được sử dụng cho tệp tarfile được mở ở chế độ luồng hiện có thể được tự động phát hiện bằng chế độ 'r|*'. (Được đóng góp bởi Lars Gustäbel.)

  • Mô-đun threading hiện cho phép bạn đặt kích thước ngăn xếp được sử dụng khi tạo chuỗi mới. Hàm stack_size([*size*]) trả về kích thước ngăn xếp hiện được cấu hình và việc cung cấp tham số size tùy chọn sẽ đặt một giá trị mới. Không phải tất cả các nền tảng đều hỗ trợ thay đổi kích thước ngăn xếp, nhưng Windows, luồng POSIX và OS/2 đều hỗ trợ. (Được đóng góp bởi Andrew MacIntyre.)

  • Mô-đun unicodedata đã được cập nhật để sử dụng phiên bản 4.1.0 của cơ sở dữ liệu ký tự Unicode. Phiên bản 3.2.0 được yêu cầu bởi một số thông số kỹ thuật, vì vậy nó vẫn có sẵn dưới dạng unicodedata.ucd_3_2_0.

  • Mô-đun mới: mô-đun uuid tạo ra các mã định danh duy nhất trên toàn cầu (UUID) theo RFC 4122. RFC xác định một số phiên bản UUID khác nhau được tạo từ chuỗi bắt đầu, từ thuộc tính hệ thống hoặc hoàn toàn ngẫu nhiên. Mô-đun này chứa lớp UUID và các hàm có tên uuid1(), uuid3(), uuid4()uuid5() để tạo các phiên bản khác nhau của UUID. (UUID phiên bản 2 không được chỉ định trong RFC 4122 và không được mô-đun này hỗ trợ.)

    >>> nhập uuid
    >>> # make a UUID dựa trên ID máy chủ và thời gian hiện tại
    >>> uuid.uuid1()
    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
    
    >>> # make a UUID sử dụng hàm băm MD5 của không gian tên UUID và một tên
    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
    
    >>> # make một UUID ngẫu nhiên
    >>> uuid.uuid4()
    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
    
    >>> # make a UUID sử dụng hàm băm SHA-1 của không gian tên UUID và một tên
    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
    

    (Được đóng góp bởi Ka-Ping Yee.)

  • Các loại WeakKeyDictionaryWeakValueDictionary của mô-đun weakref đã có được các phương pháp mới để lặp lại các tham chiếu yếu có trong từ điển. Các phương thức iterkeyrefs()keyrefs() đã được thêm vào WeakKeyDictionary, đồng thời itervaluerefs()valuerefs() đã được thêm vào WeakValueDictionary. (Đóng góp bởi Fred L. Drake, Jr.)

  • Mô-đun webbrowser đã nhận được một số cải tiến. Bây giờ nó có thể được sử dụng dưới dạng tập lệnh với python -m webbrowser, lấy URL làm đối số; có một số công tắc để kiểm soát hành vi (-n cho cửa sổ trình duyệt mới, -t cho tab mới). Các hàm cấp mô-đun mới, open_new()open_new_tab(), đã được thêm vào để hỗ trợ việc này. Chức năng open() của mô-đun hỗ trợ một tính năng bổ sung, tham số autoraise báo hiệu xem có nâng cửa sổ đang mở lên hay không khi có thể. Một số trình duyệt bổ sung đã được thêm vào danh sách hỗ trợ như Firefox, Opera, Konqueror và elinks. (Được đóng góp bởi Oleg Broytmann và Georg Brandl.)

  • Mô-đun xmlrpclib hiện hỗ trợ trả về các đối tượng datetime cho loại ngày XML-RPC. Cung cấp use_datetime=True cho hàm loads() hoặc lớp Unmarshaller để kích hoạt tính năng này. (Đóng góp bởi Skip Montanaro.)

  • Mô-đun zipfile hiện hỗ trợ phiên bản ZIP64 của định dạng, nghĩa là kho lưu trữ .zip hiện có thể lớn hơn 4 GiB và có thể chứa các tệp riêng lẻ lớn hơn 4 GiB. (Được đóng góp bởi Ronald Oussoren.)

  • Các đối tượng CompressDecompress của mô-đun zlib hiện hỗ trợ phương thức copy() tạo bản sao trạng thái bên trong của đối tượng và trả về một đối tượng Compress hoặc Decompress mới. (Đóng góp bởi Chris AtLee.)

Gói ctypes

Gói ctypes do Thomas Heller viết đã được thêm vào thư viện tiêu chuẩn. ctypes cho phép bạn gọi các hàm tùy ý trong thư viện dùng chung hoặc DLL. Người dùng lâu năm có thể nhớ đến mô-đun dl, mô-đun này cung cấp các chức năng tải các thư viện dùng chung và gọi các chức năng trong đó. Gói ctypes thú vị hơn nhiều.

Để tải thư viện dùng chung hoặc DLL, bạn phải tạo một phiên bản của lớp CDLL và cung cấp tên hoặc đường dẫn của thư viện dùng chung hoặc DLL. Khi đã xong, bạn có thể gọi các hàm tùy ý bằng cách truy cập chúng dưới dạng thuộc tính của đối tượng CDLL.

nhập ctypes

libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Dòng đầu ra\n")

Các hàm tạo kiểu cho các loại C khác nhau được cung cấp: c_int(), c_float(), c_double(), c_char_p() (tương đương với char*), v.v. Không giống như các loại của Python, các phiên bản C đều có thể thay đổi được; bạn có thể gán cho thuộc tính value của chúng để thay đổi giá trị được bao bọc. Các số nguyên và chuỗi trong Python sẽ được tự động chuyển đổi sang các kiểu C tương ứng, tuy nhiên đối với các kiểu khác bạn phải gọi đúng hàm tạo kiểu. (Và ý tôi là must; hiểu sai thường sẽ dẫn đến việc trình thông dịch gặp sự cố do lỗi phân đoạn.)

Bạn không nên sử dụng c_char_p() với chuỗi Python khi hàm C sẽ sửa đổi vùng bộ nhớ, vì chuỗi Python được cho là không thay đổi; vi phạm quy tắc này sẽ gây ra lỗi khó hiểu. Khi bạn cần một vùng bộ nhớ có thể sửa đổi, hãy sử dụng create_string_buffer():

s = "đây là một chuỗi"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)

Các hàm C được giả định trả về số nguyên, nhưng bạn có thể đặt thuộc tính restype của đối tượng hàm để thay đổi điều này

>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828

ctypes cũng cung cấp một trình bao bọc cho C API của Python dưới dạng đối tượng ctypes.pythonapi. Đối tượng này not giải phóng khóa trình thông dịch toàn cầu trước khi gọi một hàm, vì khóa phải được giữ khi gọi vào mã của trình thông dịch. Có một hàm tạo kiểu py_object sẽ tạo ra một con trỏ PyObject*. Cách sử dụng đơn giản:

nhập ctypes

d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
          ctypes.py_object("abc"), ctypes.py_object(1))
# d bây giờ là {'abc', 1}.

Đừng quên sử dụng py_object(); nếu nó bị bỏ qua, bạn sẽ gặp phải lỗi phân đoạn.

ctypes đã xuất hiện được một thời gian nhưng mọi người vẫn viết và phân phối các mô-đun mở rộng được mã hóa bằng tay vì bạn không thể tin tưởng vào sự hiện diện của ctypes. Có lẽ các nhà phát triển sẽ bắt đầu viết các trình bao bọc Python trên một thư viện được truy cập thông qua ctypes thay vì các mô-đun mở rộng, giờ đây ctypes đã được bao gồm trong Python lõi.

Xem thêm

https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/

Trang web ctypes pre-stdlib, có hướng dẫn, tài liệu tham khảo và FAQ.

Tài liệu dành cho mô-đun ctypes.

Gói ElementTree

Một tập hợp con thư viện ElementTree của Fredrik Lundh để xử lý XML đã được thêm vào thư viện chuẩn dưới dạng xml.etree. Các mô-đun có sẵn là ElementTree, ElementPathElementInclude từ ElementTree 1.2.6. Mô-đun tăng tốc cElementTree cũng được bao gồm.

Phần còn lại của phần này sẽ cung cấp tổng quan ngắn gọn về cách sử dụng ElementTree. Tài liệu đầy đủ về ElementTree có sẵn tại https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm.

ElementTree biểu thị tài liệu XML dưới dạng cây gồm các nút phần tử. Nội dung văn bản của tài liệu được lưu trữ dưới dạng thuộc tính texttail của (Đây là một trong những khác biệt chính giữa ElementTree và Mô hình đối tượng tài liệu; trong DOM có nhiều loại nút khác nhau, bao gồm cả TextNode.)

Hàm phân tích cú pháp được sử dụng phổ biến nhất là parse(), hàm này nhận một chuỗi (được giả sử chứa tên tệp) hoặc một đối tượng giống tệp và trả về một phiên bản ElementTree:

từ xml.etree nhập ElementTree dưới dạng ET

cây = ET.parse('ex-1.xml')

nguồn cấp dữ liệu = urllib.urlopen(
          'http://planet.python.org/rss10.xml')
cây = ET.parse(nguồn cấp dữ liệu)

Sau khi có phiên bản ElementTree, bạn có thể gọi phương thức getroot() của nó để lấy nút Element gốc.

Ngoài ra còn có một hàm XML() lấy một chuỗi ký tự và trả về nút Element (không phải ElementTree). Hàm này cung cấp một cách gọn gàng để kết hợp các đoạn XML, tiếp cận sự tiện lợi của một chữ XML:

svg = ET.XML("""<svg width="10px" version="1.0">
             </svg>""")
svg.set('chiều cao', '320px')
svg.append(elem1)

Mỗi phần tử XML hỗ trợ một số phương thức truy cập giống từ điển và một số phương thức truy cập giống danh sách. Các hoạt động giống như từ điển được sử dụng để truy cập các giá trị thuộc tính và các hoạt động giống như danh sách được sử dụng để truy cập các nút con.

hoạt động

kết quả

elem[n]

Trả về phần tử con thứ n.

elem[m:n]

Trả về danh sách các phần tử con thứ m đến thứ n.

len(elem)

Trả về số phần tử con.

list(elem)

Trả về danh sách các phần tử con.

elem.append(elem2)

Thêm elem2 khi còn nhỏ.

elem.insert(index, elem2)

Chèn elem2 vào vị trí đã chỉ định.

del elem[n]

Xóa phần tử con thứ n.

elem.keys()

Trả về danh sách tên thuộc tính.

elem.get(name)

Trả về giá trị của thuộc tính name.

elem.set(name, value)

Đặt giá trị mới cho thuộc tính name.

elem.attrib

Truy xuất từ điển chứa các thuộc tính.

del elem.attrib[name]

Xóa thuộc tính name.

Nhận xét và hướng dẫn xử lý cũng được biểu diễn dưới dạng nút Element. Để kiểm tra xem một nút có phải là một nhận xét hay hướng dẫn xử lý hay không:

nếu elem.tag  ET.Nhận xét:
    ...
elif elem.tag  ET.ProcessingHướng dẫn:
    ...

Để tạo đầu ra XML, bạn nên gọi phương thức ElementTree.write(). Giống như parse(), nó có thể nhận một chuỗi hoặc một đối tượng giống như tệp

# Encoding là US-ASCII
tree.write('output.xml')

# Encoding là UTF-8
f = open('output.xml', 'w')
tree.write(f,  hóa='utf-8')

(Chú ý: mã hóa mặc định được sử dụng cho đầu ra là ASCII. Đối với công việc XML nói chung, trong đó tên của một phần tử có thể chứa các ký tự Unicode tùy ý, ASCII không phải là một mã hóa hữu ích lắm vì nó sẽ đưa ra một ngoại lệ nếu tên của một phần tử chứa bất kỳ ký tự nào có giá trị lớn hơn 127. Do đó, tốt nhất là chỉ định một mã hóa khác, chẳng hạn như UTF-8 có thể xử lý bất kỳ ký tự Unicode nào.)

Phần này chỉ mô tả một phần giao diện ElementTree. Vui lòng đọc tài liệu chính thức của gói để biết thêm chi tiết.

Gói hashlib

Một mô-đun hashlib mới, được viết bởi Gregory P. Smith, đã được thêm vào để thay thế các mô-đun md5sha. hashlib bổ sung hỗ trợ cho các hàm băm an toàn bổ sung (SHA-224, SHA-256, SHA-384 và SHA-512). Khi có sẵn, mô-đun này sử dụng OpenSSL để triển khai thuật toán được tối ưu hóa nền tảng nhanh chóng.

Các mô-đun md5sha cũ vẫn tồn tại dưới dạng trình bao bọc xung quanh hashlib để duy trì khả năng tương thích ngược. Giao diện của mô-đun mới rất giống với mô-đun cũ nhưng không giống hệt nhau. Sự khác biệt đáng kể nhất là các hàm tạo để tạo các đối tượng băm mới được đặt tên khác nhau.

các phiên bản # Old
h = md5.md5()
h = md5.new()

phiên bản # New
h = hashlib.md5()

phiên bản # Old
h = sha.sha()
h = sha.new()

phiên bản # New
h = hashlib.sha1()

# Hash mà trước đây chưa có
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()

dạng # Alternative
h = thuật toán hashlib.new('md5') # Provide dưới dạng một chuỗi

Khi một đối tượng băm đã được tạo, các phương thức của nó vẫn giống như trước: update(string) băm chuỗi đã chỉ định vào trạng thái phân loại hiện tại, digest()hexdigest() trả về giá trị phân loại dưới dạng chuỗi nhị phân hoặc một chuỗi chữ số thập lục phân và copy() trả về một đối tượng băm mới có cùng trạng thái phân loại.

Xem thêm

Tài liệu dành cho mô-đun hashlib.

Gói sqlite3

Mô-đun pysqlite (https://www.pysqlite.org), một trình bao bọc cho cơ sở dữ liệu nhúng SQLite, đã được thêm vào thư viện chuẩn dưới tên gói sqlite3.

SQLite là thư viện C cung cấp cơ sở dữ liệu dựa trên đĩa nhẹ, không yêu cầu quy trình máy chủ riêng và cho phép truy cập cơ sở dữ liệu bằng biến thể không chuẩn của ngôn ngữ truy vấn SQL. Một số ứng dụng có thể sử dụng SQLite để lưu trữ dữ liệu nội bộ. Cũng có thể tạo nguyên mẫu một ứng dụng bằng SQLite và sau đó chuyển mã sang cơ sở dữ liệu lớn hơn như PostgreSQL hoặc Oracle.

pysqlite được viết bởi Gerhard Häring và cung cấp giao diện SQL tuân thủ thông số kỹ thuật DB-API 2.0 được mô tả bởi PEP 249.

Nếu bạn đang tự mình biên dịch nguồn Python, hãy lưu ý rằng cây nguồn không bao gồm mã SQLite mà chỉ bao gồm mô-đun trình bao bọc. Bạn sẽ cần cài đặt các thư viện và tiêu đề SQLite trước khi biên dịch Python và quá trình xây dựng sẽ biên dịch mô-đun khi có sẵn các tiêu đề cần thiết.

Để sử dụng mô-đun, trước tiên bạn phải tạo đối tượng Connection đại diện cho cơ sở dữ liệu. Tại đây dữ liệu sẽ được lưu trữ trong file /tmp/example:

conn = sqlite3.connect('/tmp/example')

Bạn cũng có thể cung cấp tên đặc biệt :memory: để tạo cơ sở dữ liệu trong RAM.

Khi bạn có Connection, bạn có thể tạo một đối tượng Cursor và gọi phương thức execute() của nó để thực hiện các lệnh SQL:

c = conn.cursor()

bảng # Create
c.execute('''tạo bảng cổ phiếu
(văn bản ngày tháng, văn bản chuyển đổi, văn bản ký hiệu,
 số lượng thực, giá thực)''')

# Insert một hàng dữ liệu
c.execute("""chèn vào kho
          các giá trị ('2006-01-05','BUY','RHAT',100,35.14)""")

Thông thường, các thao tác SQL của bạn sẽ cần sử dụng các giá trị từ các biến Python. Bạn không nên tập hợp truy vấn của mình bằng các thao tác chuỗi của Python vì làm như vậy là không an toàn; nó làm cho chương trình của bạn dễ bị tấn công bằng phương pháp tiêm nhiễm SQL.

Thay vào đó, hãy sử dụng thay thế tham số của DB-API. Đặt ? làm phần giữ chỗ ở bất cứ nơi nào bạn muốn sử dụng một giá trị, sau đó cung cấp một bộ giá trị làm đối số thứ hai cho phương thức execute() của con trỏ. (Các mô-đun cơ sở dữ liệu khác có thể sử dụng trình giữ chỗ khác, chẳng hạn như %s hoặc :1.) Ví dụ:

# Never làm điều này -- không an toàn!
 hiệu = 'IBM'
c.execute("... trong đó ký hiệu = '%s'" %  hiệu)

# Do thay vào đó là cái này
t = ( hiệu,)
c.execute('chọn * từ kho có ký hiệu=?', t)

 dụ về # Larger
cho t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
          ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
          ('2006-04-06', 'SELL', 'IBM', 500, 53.00),
         ):
    c.execute('chèn vào giá trị cổ phiếu (?,?,?,?,?)', t)

Để truy xuất dữ liệu sau khi thực hiện câu lệnh SELECT, bạn có thể coi con trỏ như một trình vòng lặp, gọi phương thức fetchone() của con trỏ để truy xuất một hàng khớp hoặc gọi fetchall() để nhận danh sách các hàng khớp.

Ví dụ này sử dụng dạng lặp:

>>> c = conn.cursor()
>>> c.execute('select * from stock order by price')
>>> cho hàng trong c:
... hàng in
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>

Để biết thêm thông tin về phương ngữ SQL được SQLite hỗ trợ, hãy xem https://www.sqlite.org.

Xem thêm

https://www.pysqlite.org

Trang web pysqlite.

https://www.sqlite.org

Trang web SQLite; tài liệu mô tả cú pháp và các kiểu dữ liệu có sẵn cho phương ngữ SQL được hỗ trợ.

Tài liệu dành cho mô-đun sqlite3.

PEP 249 - Cơ sở dữ liệu API Đặc tả 2.0

PEP được viết bởi Marc-André Lemburg.

Gói wsgiref

Giao diện cổng máy chủ web (WSGI) v1.0 xác định giao diện tiêu chuẩn giữa máy chủ web và ứng dụng web Python và được mô tả trong PEP 333. Gói wsgiref là bản triển khai tham chiếu của đặc tả WSGI.

Gói này bao gồm một máy chủ HTTP cơ bản sẽ chạy ứng dụng WSGI; máy chủ này hữu ích cho việc gỡ lỗi nhưng không dành cho mục đích sử dụng sản xuất. Việc thiết lập máy chủ chỉ mất vài dòng mã:

từ wsgiref nhập simple_server

wsgi_app = ...

chủ nhà = ''
cổng = 8000
httpd = simple_server.make_server(máy chủ, cổng, wsgi_app)
httpd.serve_forever()

Xem thêm

https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/

Một trang web trung tâm về các tài nguyên liên quan đến WSGI.

PEP 333 - Giao diện cổng máy chủ web Python v1.0

PEP được viết bởi Phillip J. Eby.

Xây dựng và thay đổi C API

Những thay đổi trong quá trình xây dựng của Python và C API bao gồm:

  • Cây nguồn Python đã được chuyển đổi từ CVS sang Subversion, trong một quy trình di chuyển phức tạp được Martin von Löwis giám sát và thực hiện một cách hoàn hảo. Quy trình được phát triển dưới dạng PEP 347.

  • Coverity, một công ty tiếp thị công cụ phân tích mã nguồn có tên Prevent, đã cung cấp kết quả kiểm tra mã nguồn Python của họ. Phân tích tìm thấy khoảng 60 lỗi đã được sửa nhanh chóng. Nhiều lỗi liên quan đến vấn đề đếm lại, thường xảy ra trong mã xử lý lỗi. Xem https://scan.coverity.com để biết số liệu thống kê.

  • Thay đổi lớn nhất đối với C API đến từ PEP 353, sửa đổi trình thông dịch để sử dụng định nghĩa loại Py_ssize_t thay vì int. Xem phần PEP 353: Sử dụng ssize_t làm loại chỉ mục trước đó để thảo luận về thay đổi này.

  • Thiết kế của trình biên dịch mã byte đã thay đổi rất nhiều, không còn tạo mã byte bằng cách duyệt qua cây phân tích nữa. Thay vào đó, cây phân tích cú pháp được chuyển đổi thành cây cú pháp trừu tượng (hoặc AST) và chính cây cú pháp trừu tượng được duyệt qua để tạo ra mã byte.

    Mã Python có thể lấy các đối tượng AST bằng cách sử dụng compile() tích hợp và chỉ định _ast.PyCF_ONLY_AST làm giá trị của tham số flags:

    từ _ast nhập PyCF_ONLY_AST
    ast = biên dịch ("""a=0
    cho tôi trong phạm vi (10):
        một += tôi
    """, "<string>", 'exec', PyCF_ONLY_AST)
    
    bài tập = ast.body[0]
    for_loop = ast.body[1]
    

    Chưa có tài liệu chính thức nào được viết cho mã AST, nhưng PEP 339 thảo luận về thiết kế. Để bắt đầu tìm hiểu về mã, hãy đọc định nghĩa của các nút AST khác nhau trong Parser/Python.asdl. Tập lệnh Python đọc tệp này và tạo ra một tập hợp các định nghĩa cấu trúc C trong Include/Python-ast.h. PyParser_ASTFromString()PyParser_ASTFromFile(), được xác định trong Include/pythonrun.h, lấy nguồn Python làm đầu vào và trả về gốc của AST đại diện cho nội dung. Sau đó, AST này có thể được PyAST_Compile() biến thành một đối tượng mã. Để biết thêm thông tin, hãy đọc mã nguồn và sau đó đặt câu hỏi về python-dev.

    Mã AST được phát triển dưới sự quản lý của Jeremy Hylton và được triển khai bởi (theo thứ tự bảng chữ cái) Brett Cannon, Nick Coghlan, Grant Edwards, John Ehresman, Kurt Kaiser, Neal Norwitz, Tim Peters, Armin Rigo và Neil Schenauer, cùng với những người tham gia một số cuộc chạy nước rút AST tại các hội nghị như PyCon.

  • Bản vá của Evan Jones cho obmalloc, lần đầu tiên được mô tả trong bài nói chuyện tại PyCon DC 2005, đã được áp dụng. Python 2.4 phân bổ các đối tượng nhỏ trong các đấu trường có kích thước 256K, nhưng không bao giờ giải phóng các đấu trường. Với bản vá này, Python sẽ giải phóng các đấu trường khi chúng trống. Hiệu quả thực sự là trên một số nền tảng, khi bạn phân bổ nhiều đối tượng, mức sử dụng bộ nhớ của Python thực sự có thể giảm khi bạn xóa chúng và bộ nhớ có thể được trả lại cho hệ điều hành. (Được thực hiện bởi Evan Jones và được làm lại bởi Tim Peters.)

    Lưu ý rằng thay đổi này có nghĩa là các mô-đun mở rộng phải cẩn thận hơn khi cấp phát bộ nhớ. Zz006zz của Python có nhiều chức năng khác nhau để phân bổ bộ nhớ được nhóm thành các họ. Ví dụ: PyMem_Malloc(), PyMem_Realloc()PyMem_Free() là một họ phân bổ bộ nhớ thô, trong khi PyObject_Malloc(), PyObject_Realloc()PyObject_Free() là một họ khác được sử dụng để tạo các đối tượng Python.

    Trước đây, các họ khác nhau này đều giảm xuống các chức năng malloc()free() của nền tảng. Điều này có nghĩa là sẽ không có vấn đề gì nếu bạn gặp sự cố và cấp phát bộ nhớ bằng hàm PyMem nhưng giải phóng nó bằng hàm PyObject. Với những thay đổi của phiên bản 2.5 đối với obmalloc, những dòng này hiện thực hiện những việc khác nhau và sự không khớp có thể sẽ dẫn đến lỗi phân tách. Bạn nên kiểm tra cẩn thận các mô-đun mở rộng C của mình bằng Python 2.5.

  • Các loại bộ tích hợp hiện có C API chính thức. Gọi PySet_New()PyFrozenSet_New() để tạo tập hợp mới, PySet_Add()PySet_Discard() để thêm và xóa các phần tử, gọi PySet_Contains()PySet_Size() để kiểm tra trạng thái của tập hợp. (Được đóng góp bởi Raymond Hettinger.)

  • Giờ đây, mã C có thể lấy thông tin về bản sửa đổi chính xác của trình thông dịch Python bằng cách gọi hàm Py_GetBuildInfo() trả về một chuỗi thông tin bản dựng như sau: "trunk:45355:45356M, Apr 13 2006, 07:42:19". (Được đóng góp bởi Barry Warsaw.)

  • Hai macro mới có thể được sử dụng để chỉ ra các hàm C cục bộ trong tệp hiện tại để có thể sử dụng quy ước gọi nhanh hơn. Py_LOCAL khai báo hàm trả về giá trị của type đã chỉ định và sử dụng vòng loại gọi nhanh. Py_LOCAL_INLINE thực hiện điều tương tự và cũng yêu cầu nội tuyến hàm. Nếu macro PY_LOCAL_AGGRESSIVE được xác định trước khi đưa vào python.h, một bộ tối ưu hóa mạnh mẽ hơn sẽ được bật cho mô-đun; bạn nên so sánh kết quả để tìm hiểu xem những tối ưu hóa này có thực sự làm cho mã nhanh hơn hay không. (Được đóng góp bởi Fredrik Lundh tại cuộc chạy nước rút NeedForSpeed.)

  • PyErr_NewException(name, base, dict) hiện có thể chấp nhận một bộ lớp cơ sở làm đối số base của nó. (Được đóng góp bởi Georg Brandl.)

  • Hàm PyErr_Warn() để đưa ra cảnh báo hiện không còn được dùng nữa, thay vào đó là PyErr_WarnEx(category, message, stacklevel), hàm này cho phép bạn chỉ định số khung ngăn xếp ngăn cách hàm này và hàm gọi. stacklevel bằng 1 là hàm gọi PyErr_WarnEx(), 2 là hàm ở trên đó, v.v. (Được thêm bởi Neal Norwitz.)

  • Trình thông dịch CPython vẫn được viết bằng C, nhưng mã hiện có thể được biên dịch bằng trình biên dịch C++ mà không gặp lỗi. (Được thực hiện bởi Anthony Baxter, Martin von Löwis, Skip Montanaro.)

  • Chức năng PyRange_New() đã bị xóa. Nó chưa bao giờ được ghi lại, chưa bao giờ được sử dụng trong mã lõi và việc kiểm tra lỗi lỏng lẻo một cách nguy hiểm. Trong trường hợp không chắc các tiện ích mở rộng của bạn đang sử dụng nó, bạn có thể thay thế nó bằng một cái gì đó như sau:

    phạm vi = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll",
                                  bắt đầu, dừng lại, bước);
    

Những thay đổi dành riêng cho từng cổng

  • MacOS X (10.3 trở lên): tải động các mô-đun hiện sử dụng chức năng dlopen() thay vì các chức năng dành riêng cho MacOS.

  • MacOS X: một công tắc --enable-universalsdk đã được thêm vào tập lệnh configure để biên dịch trình thông dịch dưới dạng nhị phân phổ quát có thể chạy trên cả bộ xử lý PowerPC và Intel. (Được đóng góp bởi Ronald Oussoren; bpo-2573.)

  • Windows: .dll không còn được hỗ trợ dưới dạng phần mở rộng tên tệp cho các mô-đun mở rộng. .pyd hiện là phần mở rộng tên tệp duy nhất được tìm kiếm.

Chuyển sang Python 2.5

Phần này liệt kê những thay đổi được mô tả trước đây có thể yêu cầu thay đổi mã của bạn:

  • ASCII hiện là mã hóa mặc định cho các mô-đun. Bây giờ, đây là lỗi cú pháp nếu một mô-đun chứa các chuỗi ký tự có ký tự 8 bit nhưng không có phần khai báo mã hóa. Trong Python 2.4, điều này gây ra cảnh báo chứ không phải lỗi cú pháp.

  • Trước đây, thuộc tính gi_frame của trình tạo luôn là đối tượng khung. Do những thay đổi về PEP 342 được mô tả trong phần PEP 342: Tính năng máy phát điện mới, nên giờ đây gi_frame có thể trở thành None.

  • Một cảnh báo mới, UnicodeWarning, được kích hoạt khi bạn cố so sánh chuỗi Unicode và chuỗi 8 bit không thể chuyển đổi sang Unicode bằng cách sử dụng mã hóa ASCII mặc định. Trước đây những so sánh như vậy sẽ gây ra ngoại lệ UnicodeDecodeError.

  • Thư viện: mô-đun csv hiện nghiêm ngặt hơn về các trường được trích dẫn nhiều dòng. Nếu tệp của bạn chứa các dòng mới được nhúng trong các trường thì dữ liệu đầu vào phải được chia thành các dòng theo cách giữ nguyên các ký tự dòng mới.

  • Thư viện: trước đây, hàm format() của mô-đun locale sẽ chấp nhận bất kỳ chuỗi nào miễn là không xuất hiện nhiều hơn một mã xác định %char. Trong Python 2.5, đối số phải chính xác là một ký tự %char không có văn bản xung quanh.

  • Thư viện: Các mô-đun picklecPickle không còn chấp nhận giá trị trả về là None từ phương thức __reduce__(); thay vào đó, phương thức này phải trả về một bộ đối số. Các mô-đun cũng không còn chấp nhận tham số từ khóa bin không được dùng nữa.

  • Thư viện: Các lớp SimpleXMLRPCServerDocXMLRPCServer hiện có thuộc tính rpc_paths hạn chế các hoạt động XML-RPC trong một tập hợp giới hạn các đường dẫn URL; mặc định là chỉ cho phép '/''/RPC2'. Đặt rpc_paths thành None hoặc một bộ trống sẽ vô hiệu hóa việc kiểm tra đường dẫn này.

  • C API: Nhiều chức năng hiện nay sử dụng Py_ssize_t thay vì int để cho phép xử lý nhiều dữ liệu hơn trên máy 64-bit. Mã mở rộng có thể cần thực hiện thay đổi tương tự để tránh cảnh báo và hỗ trợ máy 64-bit. Xem phần PEP 353: Sử dụng ssize_t làm loại chỉ mục trước đó để thảo luận về thay đổi này.

  • C API: Những thay đổi obmalloc có nghĩa là bạn phải cẩn thận để không sử dụng lẫn lộn các nhóm chức năng PyMem_*PyObject_*. Bộ nhớ được phân bổ bằng *_Malloc của một họ phải được giải phóng bằng chức năng *_Free của họ tương ứng.

Lời cảm ơn

Tác giả xin cảm ơn những người sau đây đã đưa ra gợi ý, chỉnh sửa và hỗ trợ các bản thảo khác nhau của bài viết này: Georg Brandl, Nick Coghlan, Phillip J. Eby, Lars Gustäbel, Raymond Hettinger, Ralf W. Grosse-Kunstleve, Kent Johnson, Iain Lowe, Martin von Löwis, Fredrik Lundh, Andrew McNamara, Skip Montanaro, Gustavo Niemeyer, Paul Prescod, James Pryor, Mike Rovner, Scott Weikart, Barry Warsaw, Thomas Wouters.