Có gì mới trong Python 3.0¶
- tác giả:
Guido van Rossum
Bài viết này giải thích các tính năng mới trong Python 3.0, so với 2.6. Python 3.0, còn được gọi là "Python 3000" hoặc "Py3K", là bản phát hành Python intentionally backwards incompatible đầu tiên. Python 3.0 được phát hành vào ngày 3 tháng 12 năm 2008. Có nhiều thay đổi hơn so với phiên bản thông thường và còn nhiều thay đổi quan trọng đối với tất cả người dùng Python. Tuy nhiên, sau khi tìm hiểu các thay đổi, bạn sẽ thấy rằng Python thực sự không thay đổi nhiều -- nhìn chung, chúng tôi chủ yếu sửa chữa các vấn đề khó chịu và mụn cóc phổ biến cũng như loại bỏ nhiều lỗi cũ.
Bài viết này không cố gắng cung cấp thông số kỹ thuật đầy đủ của tất cả các tính năng mới mà thay vào đó cố gắng cung cấp một cái nhìn tổng quan thuận tiện. Để biết chi tiết đầy đủ, bạn nên tham khảo tài liệu dành cho Python 3.0 và/hoặc nhiều PEP được tham chiếu trong văn bản. Nếu bạn muốn hiểu cơ sở lý luận về thiết kế và triển khai đầy đủ cho một tính năng cụ thể, PEP thường có nhiều chi tiết hơn tài liệu thông thường; nhưng lưu ý rằng PEP thường không được cập nhật khi một tính năng đã được triển khai đầy đủ.
Do hạn chế về thời gian nên tài liệu này chưa hoàn chỉnh như mong đợi. Như thường lệ đối với một bản phát hành mới, tệp Misc/NEWS trong bản phân phối nguồn chứa rất nhiều thông tin chi tiết về mọi điều nhỏ nhặt đã được thay đổi.
Những trở ngại thường gặp¶
Phần này liệt kê một số thay đổi có nhiều khả năng khiến bạn gặp khó khăn nhất nếu bạn đã quen với Python 2.5.
In là một chức năng¶
Câu lệnh print đã được thay thế bằng hàm print(), với các đối số từ khóa để thay thế hầu hết cú pháp đặc biệt của câu lệnh print cũ (PEP 3105). Ví dụ:
Cũ: in "Câu trả lời là", 2*2
Mới: print("Câu trả lời là", 2*2)
Cũ: print x, # Trailing dấu phẩy chặn dòng mới
Mới: print(x, end=" ") # Appends một khoảng trắng thay vì một dòng mới
Cũ: in # Prints một dòng mới
Mới: print() # You phải gọi hàm!
Cũ: print >>sys.stderr, "lỗi nghiêm trọng"
Mới: print("lỗi nghiêm trọng", file=sys.stderr)
Cũ: print (x, y) # prints repr((x, y))
Mới: print((x, y)) # Not giống như print(x, y)!
Bạn cũng có thể tùy chỉnh dấu phân cách giữa các mục, ví dụ::
print("Có <", 2**32, "> khả năng!", sep="")
sản xuất:
Có <4294967296> khả năng!
Lưu ý:
Hàm
print()không hỗ trợ tính năng "softspace" của câu lệnhprintcũ. Ví dụ: trong Python 2.x,print "A\n", "B"sẽ viết"A\nB\n"; nhưng trong Python 3.0,print("A\n", "B")viết"A\n B\n".Ban đầu, bạn sẽ thấy mình gõ
print xcũ rất nhiều trong chế độ tương tác. Đã đến lúc luyện tập lại ngón tay của bạn để gõprint(x)!Khi sử dụng công cụ chuyển đổi nguồn sang nguồn
2to3, tất cả các câu lệnhprintsẽ tự động được chuyển đổi thành lệnh gọi hàmprint(), vì vậy đây hầu như không phải là vấn đề đối với các dự án lớn hơn.
Lượt xem và vòng lặp thay vì danh sách¶
Một số API nổi tiếng không còn trả về danh sách:
Các phương thức
dictdict.keys(),dict.items()vàdict.values()trả về "lượt xem" thay vì danh sách. Ví dụ: điều này không còn hoạt động nữa:k = d.keys(); k.sort(). Thay vào đó, hãy sử dụngk = sorted(d)(điều này cũng hoạt động trong Python 2.5 và hiệu quả tương đương).Ngoài ra, các phương thức
dict.iterkeys(),dict.iteritems()vàdict.itervalues()không còn được hỗ trợ.map()vàfilter()trả về các trình vòng lặp. Nếu bạn thực sự cần một danh sách và các chuỗi đầu vào đều có độ dài bằng nhau, cách khắc phục nhanh là bọcmap()tronglist(), ví dụ:list(map(...)), nhưng cách khắc phục tốt hơn thường là sử dụng tính năng hiểu danh sách (đặc biệt khi mã gốc sử dụnglambda) hoặc viết lại mã để không cần danh sách nào cả. Đặc biệt khó khăn làmap()được gọi vì các tác dụng phụ của hàm; cách chuyển đổi đúng là sử dụng vòng lặpforthông thường (vì việc tạo danh sách sẽ rất lãng phí).Nếu các chuỗi đầu vào không có độ dài bằng nhau,
map()sẽ dừng ở điểm cuối của chuỗi ngắn nhất. Để tương thích hoàn toàn vớimap()từ Python 2.x, hãy gói cả các chuỗi trongitertools.zip_longest(), ví dụ:map(func, *sequences)trở thànhlist(map(func, itertools.zip_longest(*sequences))).range()hiện hoạt động giống nhưxrange()trước đây, ngoại trừ việc nó hoạt động với các giá trị có kích thước tùy ý. Cái sau không còn tồn tại.zip()hiện trả về một trình vòng lặp.
So sánh thứ tự¶
Python 3.0 đã đơn giản hóa các quy tắc so sánh thứ tự:
Các toán tử so sánh thứ tự (
<,<=,>=,>) đưa ra ngoại lệ TypeError khi các toán hạng không có thứ tự tự nhiên có ý nghĩa. Do đó, các biểu thức như1 < '',0 > Nonehoặclen <= lenkhông còn hợp lệ và ví dụ:None < NonetăngTypeErrorthay vì trả vềFalse. Một hệ quả tất yếu là việc sắp xếp một danh sách không đồng nhất không còn ý nghĩa nữa -- tất cả các phần tử phải có thể so sánh được với nhau. Lưu ý rằng điều này không áp dụng cho toán tử==và!=: các đối tượng thuộc các loại không thể so sánh được khác nhau luôn so sánh không bằng nhau.sorted()vàlist.sort()không còn chấp nhận đối số cmp cung cấp chức năng so sánh. Thay vào đó hãy sử dụng đối số key. N.B. các đối số key và reverse hiện là "chỉ từ khóa".Chức năng
cmp()sẽ được coi là không còn nữa và phương thức đặc biệt__cmp__()không còn được hỗ trợ. Sử dụng__lt__()để sắp xếp,__eq__()với__hash__()và các so sánh phong phú khác nếu cần. (Nếu bạn thực sự cần chức năngcmp(), bạn có thể sử dụng biểu thức(a > b) - (a < b)tương đương vớicmp(a, b).)
số nguyên¶
PEP 237: Về cơ bản,
longđược đổi tên thànhint. Tức là chỉ có một loại tích phân tích hợp có tên làint; nhưng nó hoạt động giống như loạilongcũ.PEP 238: Một biểu thức như
1/2trả về một float. Sử dụng1//2để thực hiện hành vi cắt ngắn. (Cú pháp sau đã tồn tại trong nhiều năm, ít nhất là kể từ Python 2.2.)Hằng số
sys.maxintđã bị xóa vì không còn giới hạn đối với giá trị của số nguyên. Tuy nhiên,sys.maxsizecó thể được sử dụng như một số nguyên lớn hơn bất kỳ danh sách hoặc chỉ mục chuỗi thực tế nào. Nó phù hợp với kích thước số nguyên "tự nhiên" của quá trình triển khai và thường giống vớisys.maxinttrong các bản phát hành trước trên cùng một nền tảng (giả sử có cùng các tùy chọn xây dựng).repr()của một số nguyên dài không còn bao gồmLở cuối nữa, do đó, mã loại bỏ ký tự đó một cách vô điều kiện sẽ cắt bỏ chữ số cuối cùng. (Thay vào đó hãy sử dụngstr().)Chữ bát phân không còn ở dạng
0720nữa; thay vào đó hãy sử dụng0o720.
Văn bản Vs. Dữ liệu thay vì Unicode Vs. 8-bit¶
Mọi thứ bạn nghĩ bạn biết về dữ liệu nhị phân và Unicode đã thay đổi.
Python 3.0 sử dụng các khái niệm text và (nhị phân) data thay vì chuỗi Unicode và chuỗi 8 bit. Tất cả văn bản đều là Unicode; tuy nhiên encoded Unicode được biểu diễn dưới dạng dữ liệu nhị phân. Loại dùng để chứa văn bản là
str, loại dùng để chứa dữ liệu làbytes. Sự khác biệt lớn nhất với tình huống 2.x là mọi nỗ lực trộn văn bản và dữ liệu trong Python 3.0 đều làm tăngTypeError, trong khi nếu bạn trộn chuỗi Unicode và chuỗi 8 bit trong Python 2.x, nó sẽ hoạt động nếu chuỗi 8 bit tình cờ chỉ chứa byte 7 bit (ASCII), nhưng bạn sẽ nhận đượcUnicodeDecodeErrornếu nó chứa các giá trị không phải là ASCII. Hành vi có giá trị cụ thể này đã gây ra nhiều gương mặt đau buồn trong nhiều năm qua.Do hậu quả của sự thay đổi về triết lý này, hầu như tất cả các mã sử dụng Unicode, mã hóa hoặc dữ liệu nhị phân rất có thể phải thay đổi. Sự thay đổi này là tốt hơn, vì trong thế giới 2.x có rất nhiều lỗi liên quan đến việc trộn lẫn văn bản được mã hóa và không được mã hóa. Để chuẩn bị bằng Python 2.x, hãy bắt đầu sử dụng
unicodecho tất cả văn bản chưa được mã hóa vàstrchỉ cho dữ liệu nhị phân hoặc được mã hóa. Sau đó, công cụ2to3sẽ thực hiện hầu hết công việc cho bạn.Bạn không thể sử dụng chữ
u"..."cho văn bản Unicode nữa. Tuy nhiên, bạn phải sử dụng hằng sốb"..."cho dữ liệu nhị phân.Vì loại
strvàbyteskhông thể trộn lẫn nên bạn phải luôn chuyển đổi rõ ràng giữa chúng. Sử dụngstr.encode()để chuyển từstrsangbytesvàbytes.decode()để chuyển từbytessangstr. Bạn cũng có thể sử dụngbytes(s, encoding=...)vàstr(b, encoding=...)tương ứng.Giống như
str, loạibyteslà bất biến. Có một loại mutable riêng để chứa dữ liệu nhị phân được đệm,bytearray. Gần như tất cả các API chấp nhậnbytescũng chấp nhậnbytearray. Zz007zz có thể thay đổi được dựa trêncollections.MutableSequence.Tất cả các dấu gạch chéo ngược trong chuỗi ký tự thô được hiểu theo nghĩa đen. Điều này có nghĩa là các ký tự thoát
'\U'và'\u'trong chuỗi thô không được xử lý đặc biệt. Ví dụ:r'\u20ac'là một chuỗi gồm 6 ký tự trong Python 3.0, trong khi ở 2.6,ur'\u20ac'là một ký tự "euro". (Tất nhiên, thay đổi này chỉ ảnh hưởng đến các chuỗi ký tự thô; ký tự euro là'\u20ac'trong Python 3.0.)Loại trừu tượng
basestringtích hợp đã bị xóa. Thay vào đó hãy sử dụngstr. Các loạistrvàbyteskhông có đủ chức năng chung để đảm bảo một lớp cơ sở dùng chung. Công cụ2to3(xem bên dưới) thay thế mọi lần xuất hiện củabasestringbằngstr.Các tệp được mở dưới dạng tệp văn bản (vẫn là chế độ mặc định cho
open()) luôn sử dụng mã hóa để ánh xạ giữa các chuỗi (trong bộ nhớ) và byte (trên đĩa). Các tệp nhị phân (được mở bằngbtrong đối số chế độ) luôn sử dụng byte trong bộ nhớ. Điều này có nghĩa là nếu một tệp được mở bằng chế độ hoặc mã hóa không chính xác, I/O có thể sẽ bị lỗi nghiêm trọng, thay vì âm thầm tạo ra dữ liệu không chính xác. Điều đó cũng có nghĩa là ngay cả người dùng Unix cũng sẽ phải chỉ định chế độ chính xác (văn bản hoặc nhị phân) khi mở tệp. Có một mã hóa mặc định phụ thuộc vào nền tảng, trên nền tảng Unixy có thể được đặt bằng biến môi trườngLANG(và đôi khi cũng có một số biến môi trường liên quan đến ngôn ngữ cụ thể theo nền tảng khác). Trong nhiều trường hợp, nhưng không phải tất cả, mặc định của hệ thống là UTF-8; bạn không bao giờ nên tin tưởng vào sự mặc định này. Bất kỳ ứng dụng nào đọc hoặc viết nhiều hơn văn bản ASCII thuần túy đều có thể có cách ghi đè mã hóa. Không còn nhu cầu sử dụng các luồng nhận biết mã hóa trong mô-đuncodecsnữa.Các giá trị ban đầu của
sys.stdin,sys.stdoutvàsys.stderrhiện là các tệp văn bản chỉ unicode (tức là chúng là các phiên bản củaio.TextIOBase). Để đọc và ghi dữ liệu byte với các luồng này, bạn cần sử dụng thuộc tínhio.TextIOBase.buffercủa chúng.Tên tệp được chuyển đến và trả về từ API dưới dạng chuỗi (Unicode). Điều này có thể gây ra các vấn đề dành riêng cho nền tảng vì trên một số tên tệp nền tảng là các chuỗi byte tùy ý. (Mặt khác, trên Windows, tên tệp được lưu trữ nguyên bản dưới dạng Unicode.) Để giải quyết, hầu hết các API (ví dụ:
open()và nhiều hàm trong mô-đunos) lấy tên tệp chấp nhận các đối tượngbytescũng như các chuỗi và một số API có cách yêu cầu giá trị trả vềbytes. Do đó,os.listdir()trả về danh sách các phiên bảnbytesnếu đối số là phiên bảnbytesvàos.getcwdb()trả về thư mục làm việc hiện tại dưới dạng phiên bảnbytes. Lưu ý rằng khios.listdir()trả về danh sách các chuỗi, tên tệp không thể giải mã chính xác sẽ bị bỏ qua thay vì tăngUnicodeError.Một số API hệ thống như
os.environvàsys.argvcũng có thể gây ra sự cố khi các byte do hệ thống cung cấp không thể hiểu được bằng cách sử dụng mã hóa mặc định. Đặt biếnLANGvà chạy lại chương trình có lẽ là cách tiếp cận tốt nhất.PEP 3138:
repr()của chuỗi không còn thoát khỏi các ký tự không phải ASCII. Tuy nhiên, nó vẫn thoát khỏi các ký tự điều khiển và điểm mã với trạng thái không in được trong tiêu chuẩn Unicode.PEP 3120: Mã hóa nguồn mặc định hiện là UTF-8.
PEP 3131: Các chữ cái không phải ASCII hiện được phép sử dụng trong mã định danh. (Tuy nhiên, thư viện tiêu chuẩn vẫn chỉ có ASCII ngoại trừ tên người đóng góp trong nhận xét.)
Các mô-đun
StringIOvàcStringIOđã biến mất. Thay vào đó, hãy nhập mô-đuniovà sử dụngio.StringIOhoặcio.BytesIOcho văn bản và dữ liệu tương ứng.Xem thêm Unicode HOWTO, được cập nhật cho Python 3.0.
Tổng quan về các thay đổi cú pháp¶
Phần này cung cấp thông tin tổng quan ngắn gọn về mọi thay đổi syntactic trong Python 3.0.
Cú pháp mới¶
PEP 3107: Chú thích đối số hàm và giá trị trả về. Điều này cung cấp một cách chuẩn hóa để chú thích các tham số và giá trị trả về của hàm. Không có ngữ nghĩa nào được đính kèm với các chú thích như vậy ngoại trừ việc chúng có thể được xem xét nội tâm trong thời gian chạy bằng thuộc tính
__annotations__. Mục đích là khuyến khích thử nghiệm thông qua siêu lớp, trang trí hoặc khung.PEP 3102: Đối số chỉ có từ khóa. Các tham số được đặt tên xảy ra sau
*argstrong danh sách tham số must được chỉ định bằng cú pháp từ khóa trong lệnh gọi. Bạn cũng có thể sử dụng*trần trong danh sách tham số để cho biết rằng bạn không chấp nhận danh sách đối số có độ dài thay đổi, nhưng bạn có các đối số chỉ từ khóa.Đối số từ khóa được cho phép sau danh sách các lớp cơ sở trong định nghĩa lớp. Điều này được quy ước mới sử dụng để chỉ định siêu dữ liệu (xem phần tiếp theo), nhưng cũng có thể được sử dụng cho các mục đích khác, miễn là siêu dữ liệu hỗ trợ nó.
PEP 3104: câu lệnh
nonlocal. Bằng cách sử dụngnonlocal x, giờ đây bạn có thể gán trực tiếp cho một biến ở phạm vi bên ngoài (nhưng không phải toàn cục).nonlocallà một từ dành riêng mới.PEP 3132: Giải nén lặp lại mở rộng. Bây giờ bạn có thể viết những thứ như
a, b, *rest = some_sequence. Và thậm chí cả*rest, a = stuff. Đối tượngrestluôn là một danh sách (có thể trống); phía bên phải có thể là bất kỳ lần lặp nào. Ví dụ:(a, *phần còn lại, b) = phạm vi (5)
Điều này đặt a thành
0, b thành4và rest thành[1, 2, 3].Hiểu từ điển:
{k: v for k, v in stuff}có nghĩa tương tự nhưdict(stuff)nhưng linh hoạt hơn. (Đây là PEP 274 được minh oan. :-)Đặt chữ, ví dụ:
{1, 2}. Lưu ý rằng{}là một từ điển trống; sử dụngset()cho một bộ trống. Việc hiểu tập hợp cũng được hỗ trợ; ví dụ:{x for x in stuff}có nghĩa tương tự nhưset(stuff)nhưng linh hoạt hơn.Chữ bát phân mới, ví dụ:
0o720(đã có trong 2.6). Các chữ bát phân cũ (0720) đã biến mất.Chữ nhị phân mới, ví dụ:
0b1010(đã có trong 2.6) và có một chức năng tích hợp tương ứng mới,bin().Các ký tự byte được giới thiệu với
bhoặcBđứng đầu và có một hàm tích hợp tương ứng mới,bytes().
Cú pháp đã thay đổi¶
PEP 3109 và PEP 3134: cú pháp câu lệnh
raisemới:raise [expr [from expr]]. Xem bên dưới.asvàwithhiện là những từ dành riêng. (Thực tế là kể từ 2.6.)True,FalsevàNonelà những từ dành riêng. (2.6 đã thực thi một phần các hạn chế trênNone.)Thay đổi từ
exceptexc, var thànhexceptexcasvar. Xem PEP 3110.PEP 3115: Cú pháp siêu dữ liệu mới. Thay vì:
lớp C: __siêu lớp__ = M ...
bây giờ bạn phải sử dụng:
lớp C (siêu lớp=M): ...
Biến
__metaclass__toàn cầu của mô-đun không còn được hỗ trợ. (Đó là một chiếc nạng để giúp việc mặc định các lớp kiểu mới dễ dàng hơn mà không cần lấy mọi lớp từobject.)Tính năng hiểu danh sách không còn hỗ trợ dạng cú pháp
[... for var in item1, item2, ...]nữa. Thay vào đó hãy sử dụng[... for var in (item1, item2, ...)]. Cũng lưu ý rằng việc hiểu danh sách có ngữ nghĩa khác nhau: chúng gần với cú pháp hơn đối với biểu thức trình tạo bên trong hàm tạolist()và đặc biệt là các biến điều khiển vòng lặp không còn bị rò rỉ vào phạm vi xung quanh.ellipsis (
...) có thể được sử dụng làm biểu thức nguyên tử ở bất cứ đâu. (Trước đây nó chỉ được phép ở dạng lát.) Ngoài ra, must bây giờ được đánh vần là.... (Trước đây nó cũng có thể được đánh vần là. . ., chỉ do sự ngẫu nhiên về ngữ pháp.)
Cú pháp đã xóa¶
PEP 3113: Đã xóa giải nén tham số Tuple. Bạn không thể viết
def foo(a, (b, c)): ...nữa. Thay vào đó hãy sử dụngdef foo(a, b_c): b, c = b_c.Đã xóa backticks (thay vào đó hãy sử dụng
repr()).Đã xóa
<>(thay vào đó hãy sử dụng!=).Từ khóa đã xóa:
exec()không còn là từ khóa; nó vẫn còn như một chức năng. (May mắn thay, cú pháp hàm cũng được chấp nhận trong 2.x.) Cũng lưu ý rằngexec()không còn nhận đối số luồng nữa; thay vìexec(f)bạn có thể sử dụngexec(f.read()).Chữ nguyên không còn hỗ trợ
lhoặcLở cuối.Chuỗi ký tự không còn hỗ trợ
uhoặcUhàng đầu nữa.Cú pháp
frommoduleimport*chỉ được phép ở cấp mô-đun, không còn bên trong các hàm.Cú pháp duy nhất được chấp nhận để nhập tương đối là
from .[module] import name. Tất cả các dạngimportkhông bắt đầu bằng.đều được hiểu là nhập tuyệt đối. (PEP 328)Các lớp học cổ điển đã biến mất.
Những thay đổi đã có trong Python 2.6¶
Vì nhiều người dùng có lẽ đã chuyển thẳng từ Python 2.5 sang Python 3.0, nên phần này nhắc nhở người đọc về các tính năng mới ban đầu được thiết kế cho Python 3.0 nhưng đã được chuyển ngược sang Python 2.6. Nên tham khảo các phần tương ứng trong Có gì mới trong Python 2.6 để có mô tả dài hơn.
PEP 343: Câu lệnh 'với'. Câu lệnh
withhiện là một tính năng tiêu chuẩn và không cần phải nhập từ__future__nữa. Ngoài ra, hãy kiểm tra Viết trình quản lý bối cảnh và Mô-đun ngữ cảnh.PEP 366: Nhập tương đối rõ ràng từ mô-đun chính. Điều này nâng cao tính hữu ích của tùy chọn
-mkhi mô-đun được tham chiếu nằm trong một gói.PEP 3101: Định dạng chuỗi nâng cao. Lưu ý: mô tả 2.6 đề cập đến phương thức
format()cho cả chuỗi 8 bit và chuỗi Unicode. Trong phiên bản 3.0, chỉ có loạistr(chuỗi văn bản có hỗ trợ Unicode) hỗ trợ phương thức này; loạibytesthì không. Kế hoạch cuối cùng là biến đây thành API duy nhất để định dạng chuỗi và bắt đầu ngừng sử dụng toán tử%trong Python 3.1.PEP 3105: print Là một chức năng. Đây hiện là tính năng tiêu chuẩn và không cần phải nhập từ
__future__nữa. Thông tin chi tiết đã được đưa ra ở trên.PEP 3110: Thay đổi xử lý ngoại lệ. Cú pháp
exceptexcasvar hiện là cú pháp tiêu chuẩn vàexceptexc, var không còn được hỗ trợ nữa. (Tất nhiên, phầnasvar vẫn là tùy chọn.)PEP 3112: Chữ Byte. Ký hiệu chữ của chuỗi
b"..."(và các biến thể của nó nhưb'...',b"""..."""vàbr"...") hiện tạo ra một chữ kiểubytes.PEP 3116: Thư viện I/O mới. Mô-đun
iohiện là cách thực hiện I/O tệp tiêu chuẩn. Hàmopen()tích hợp hiện là bí danh choio.open()và có các đối số từ khóa bổ sung encoding, errors, newline và closefd. Cũng lưu ý rằng đối số mode không hợp lệ hiện tăngValueErrorchứ không phảiIOError. Đối tượng tệp nhị phân bên dưới đối tượng tệp văn bản có thể được truy cập dưới dạngf.buffer(nhưng hãy cẩn thận rằng đối tượng văn bản duy trì bộ đệm của chính nó để tăng tốc các hoạt động mã hóa và giải mã).PEP 3118: Giao thức bộ đệm được sửa đổi.
buffer()tích hợp sẵn hiện đã thực sự không còn nữa;memoryview()tích hợp mới cung cấp (hầu hết) chức năng tương tự.PEP 3119: Lớp cơ sở trừu tượng. Mô-đun
abcvà các ABC được xác định trong mô-đuncollectionshiện đóng một vai trò nổi bật hơn trong ngôn ngữ và các loại bộ sưu tập tích hợp nhưdictvàlistlần lượt tuân theo các ABCcollections.MutableMappingvàcollections.MutableSequence.PEP 3127: Cú pháp và hỗ trợ chữ số nguyên. Như đã đề cập ở trên, ký hiệu chữ bát phân mới là ký hiệu duy nhất được hỗ trợ và các ký tự nhị phân đã được thêm vào.
PEP 3141: Hệ thống phân cấp loại cho số. Mô-đun
numberslà một cách sử dụng ABC mới khác, xác định "tháp số" của Python. Cũng lưu ý mô-đunfractionsmới triển khainumbers.Rational.
Thay đổi thư viện¶
Do hạn chế về thời gian, tài liệu này không đề cập đầy đủ những thay đổi sâu rộng đối với thư viện chuẩn. PEP 3108 là tài liệu tham khảo cho những thay đổi lớn đối với thư viện. Đây là một đánh giá viên nang:
Nhiều mô-đun cũ đã bị loại bỏ. Một số, như
gopherlib(không còn được sử dụng) vàmd5(được thay thế bằnghashlib), đã không còn được dùng nữa bởi PEP 4. Một số khác đã bị xóa do không còn hỗ trợ cho nhiều nền tảng khác nhau như Irix, BeOS và Mac OS 9 (xem PEP 11). Một số mô-đun cũng đã được chọn để xóa trong Python 3.0 do không được sử dụng hoặc do có sự thay thế tốt hơn. Xem PEP 3108 để biết danh sách đầy đủ.Gói
bsddb3đã bị xóa vì sự hiện diện của nó trong thư viện tiêu chuẩn cốt lõi theo thời gian đã chứng tỏ là gánh nặng đặc biệt đối với các nhà phát triển cốt lõi do tính không ổn định của quá trình kiểm tra và lịch phát hành của Berkeley DB. Tuy nhiên, gói hàng vẫn hoạt động tốt, được bảo trì bên ngoài tại https://www.jcea.es/programacion/pybsddb.htm.Một số mô-đun đã được đổi tên vì tên cũ của chúng không tuân theo PEP 8 hoặc vì nhiều lý do khác. Đây là danh sách:
Tên cũ
Tên mới
_winreg
winreg
Trình phân tích cú pháp cấu hình
trình phân tích cú pháp cấu hình
sao chép_reg
sao chép
Hàng đợi
xếp hàng
Máy chủ ổ cắm
máy chủ ổ cắm
cơ sở đánh dấu
_markupbase
đại diện
viết lại
kiểm tra.test_support
kiểm tra.support
Mẫu phổ biến trong Python 2.x là có một phiên bản mô-đun được triển khai bằng Python thuần túy, với phiên bản tăng tốc tùy chọn được triển khai dưới dạng phần mở rộng C; ví dụ:
picklevàcPickle. Điều này đặt gánh nặng nhập phiên bản tăng tốc và quay lại phiên bản Python thuần túy cho mỗi người dùng của các mô-đun này. Trong Python 3.0, các phiên bản tăng tốc được coi là chi tiết triển khai của các phiên bản Python thuần túy. Người dùng phải luôn nhập phiên bản tiêu chuẩn, phiên bản này sẽ cố gắng nhập phiên bản tăng tốc và quay lại phiên bản Python thuần túy. Cặppickle/cPicklenhận được cách xử lý này. Mô-đunprofilenằm trong danh sách dành cho phiên bản 3.1. Mô-đunStringIOđã được chuyển thành một lớp trong mô-đunio.Một số mô-đun liên quan đã được nhóm thành các gói và thông thường tên mô-đun con đã được đơn giản hóa. Các gói mới kết quả là:
dbm(anydbm,dbhash,dbm,dumbdbm,gdbm,whichdb).html(HTMLParser,htmlentitydefs).http(httplib,BaseHTTPServer,CGIHTTPServer,SimpleHTTPServer,Cookie,cookielib).tkinter(tất cả các mô-đun liên quan đếnTkinterngoại trừturtle). Đối tượng mục tiêu củaturtlekhông thực sự quan tâm đếntkinter. Cũng lưu ý rằng kể từ Python 2.6, chức năng củaturtleđã được nâng cao đáng kể.urllib(urllib,urllib2,urlparse,robotparse).xmlrpc(xmlrpclib,DocXMLRPCServer,SimpleXMLRPCServer).
Một số thay đổi khác đối với mô-đun thư viện tiêu chuẩn, không được PEP 3108 đề cập:
Đã giết
sets. Sử dụng lớpset()tích hợp.Dọn dẹp mô-đun
sys: đã xóasys.exitfunc(),sys.exc_clear(),sys.exc_type,sys.exc_value,sys.exc_traceback. (Lưu ý rằngsys.last_type, v.v. vẫn còn.)Dọn dẹp loại
array.array: các phương thứcread()vàwrite()không còn nữa; thay vào đó hãy sử dụngfromfile()vàtofile(). Ngoài ra, mã kiểu'c'cho mảng không còn nữa -- hãy sử dụng'b'cho byte hoặc'u'cho ký tự Unicode.Dọn dẹp mô-đun
operator: loại bỏsequenceIncludes()vàisCallable().Dọn dẹp mô-đun
thread:acquire_lock()vàrelease_lock()không còn nữa; thay vào đó hãy sử dụngacquire()vàrelease().Dọn dẹp mô-đun
random: đã xóajumpahead()API.Mô-đun
newđã biến mất.Các chức năng
os.tmpnam(),os.tempnam()vàos.tmpfile()đã bị loại bỏ để thay thế cho mô-đuntempfile.Mô-đun
tokenizeđã được thay đổi để hoạt động với byte. Điểm vào chính bây giờ làtokenize.tokenize(), thay vì generate_tokens.string.lettersvà những người bạn của nó (string.lowercasevàstring.uppercase) đã biến mất. Thay vào đó hãy sử dụngstring.ascii_letters, v.v. (Lý do xóa làstring.lettersvà bạn bè có hành vi cụ thể theo địa phương, đây là một ý tưởng tồi đối với các "hằng số" toàn cầu được đặt tên hấp dẫn như vậy.)Đã đổi tên mô-đun
__builtin__thànhbuiltins(xóa dấu gạch dưới, thêm 's'). Biến__builtins__được tìm thấy trong hầu hết các không gian tên chung không thay đổi. Để sửa đổi nội dung, bạn nên sử dụngbuiltins, không phải__builtins__!
PEP 3101: Một cách tiếp cận mới để định dạng chuỗi¶
Một hệ thống mới dành cho các hoạt động định dạng chuỗi tích hợp sẽ thay thế toán tử định dạng chuỗi
%. (Tuy nhiên, toán tử%vẫn được hỗ trợ; nó sẽ không được dùng nữa trong Python 3.1 và bị xóa khỏi ngôn ngữ sau này.) Đọc PEP 3101 để biết thông tin đầy đủ.
Thay đổi ngoại lệ¶
Các API để phát hiện và bắt ngoại lệ đã được cải tiến và bổ sung các tính năng mạnh mẽ mới:
PEP 352: Tất cả các ngoại lệ phải được bắt nguồn (trực tiếp hoặc gián tiếp) từ
BaseException. Đây là gốc của hệ thống phân cấp ngoại lệ. Đây không phải là một đề xuất mới, nhưng requirement kế thừa từBaseExceptionlà mới. (Python 2.6 vẫn cho phép nâng cấp các lớp cổ điển và không đặt ra hạn chế nào đối với những gì bạn có thể bắt được.) Kết quả là, các ngoại lệ chuỗi cuối cùng đã thực sự bị loại bỏ.Hầu như tất cả các trường hợp ngoại lệ thực sự đều bắt nguồn từ
Exception;BaseExceptionchỉ nên được sử dụng làm lớp cơ sở cho các trường hợp ngoại lệ chỉ nên được xử lý ở cấp cao nhất, chẳng hạn nhưSystemExithoặcKeyboardInterrupt. Thành ngữ được đề xuất để xử lý tất cả các trường hợp ngoại lệ ngoại trừ danh mục sau này là sử dụngexceptException.StandardErrorđã bị xóa.Các ngoại lệ không còn hoạt động như một chuỗi nữa. Thay vào đó hãy sử dụng thuộc tính
args.PEP 3109: Đưa ra ngoại lệ. Bây giờ bạn phải sử dụng
raise Exception(args)thay vìraise Exception, args. Ngoài ra, bạn không còn có thể chỉ định rõ ràng truy nguyên; thay vào đó, nếu bạn have thực hiện việc này, bạn có thể gán trực tiếp cho thuộc tính__traceback__(xem bên dưới).PEP 3110: Bắt ngoại lệ. Bây giờ bạn phải sử dụng
except SomeException as variablethay vìexcept SomeException, variable. Hơn nữa, variable bị xóa rõ ràng khi còn lại khốiexcept.PEP 3134: Chuỗi ngoại lệ. Có hai trường hợp: chuỗi ngầm và chuỗi rõ ràng. Chuỗi ngầm định xảy ra khi một ngoại lệ được đưa ra trong khối xử lý
excepthoặcfinally. Điều này thường xảy ra do lỗi trong khối xử lý; chúng tôi gọi đây là ngoại lệ secondary. Trong trường hợp này, ngoại lệ ban đầu (đang được xử lý) được lưu dưới dạng thuộc tính__context__của ngoại lệ phụ. Chuỗi rõ ràng được gọi bằng cú pháp nàynâng cao Ngoại lệ phụ() từ ngoại lệ chính
(trong đó primary_exception là bất kỳ biểu thức nào tạo ra một đối tượng ngoại lệ, có thể là một ngoại lệ đã được phát hiện trước đó). Trong trường hợp này, ngoại lệ chính được lưu trữ trên thuộc tính
__cause__của ngoại lệ phụ. Truy nguyên được in khi xảy ra một ngoại lệ chưa được xử lý sẽ đi theo chuỗi thuộc tính__cause__và__context__và in một truy nguyên riêng cho từng thành phần của chuỗi, với ngoại lệ chính ở trên cùng. (Người dùng Java có thể nhận ra hành vi này.)PEP 3134: Các đối tượng ngoại lệ hiện lưu trữ dấu vết của chúng dưới dạng thuộc tính
__traceback__. Điều này có nghĩa là một đối tượng ngoại lệ hiện chứa tất cả thông tin liên quan đến một ngoại lệ và có ít lý do hơn để sử dụngsys.exc_info()(mặc dù lý do sau không bị xóa).Một số thông báo ngoại lệ được cải thiện khi Windows không tải được mô-đun mở rộng. Ví dụ:
error code 193bây giờ là%1 is not a valid Win32 application. Các chuỗi hiện xử lý các ngôn ngữ không phải tiếng Anh.
Những thay đổi khác¶
Toán tử và phương pháp đặc biệt¶
!=hiện trả về kết quả ngược lại với==, trừ khi==trả vềNotImplemented.Khái niệm "phương pháp không liên kết" đã bị xóa khỏi ngôn ngữ. Khi tham chiếu một phương thức dưới dạng thuộc tính lớp, bây giờ bạn sẽ có được một đối tượng hàm đơn giản.
__getslice__(),__setslice__()và__delslice__()đã bị giết. Cú phápa[i:j]hiện được dịch thànha.__getitem__(slice(i, j))(hoặc__setitem__()hoặc__delitem__(), khi được sử dụng làm mục tiêu gán hoặc xóa tương ứng).PEP 3114: phương thức
next()tiêu chuẩn đã được đổi tên thành__next__().Các phương thức đặc biệt
__oct__()và__hex__()bị loại bỏ --oct()vàhex()sử dụng__index__()ngay bây giờ để chuyển đổi đối số thành số nguyên.Đã xóa hỗ trợ cho
__members__và__methods__.Các thuộc tính hàm có tên
func_Xđã được đổi tên để sử dụng dạng__X__, giải phóng các tên này trong không gian tên thuộc tính hàm cho các thuộc tính do người dùng xác định. Nói một cách ngắn gọn,func_closure,func_code,func_defaults,func_dict,func_doc,func_globals,func_namelần lượt được đổi tên thành__closure__,__code__,__defaults__,__dict__,__doc__,__globals__,__name__.__nonzero__()bây giờ là__bool__().
Nội dung¶
PEP 3135:
super()mới. Bây giờ bạn có thể gọisuper()mà không cần đối số và (giả sử đây là một phương thức phiên bản thông thường được xác định bên trong câu lệnhclass), lớp và phiên bản phù hợp sẽ tự động được chọn. Với các đối số, hành vi củasuper()không thay đổi.PEP 3111:
raw_input()được đổi tên thànhinput(). Tức là, hàminput()mới đọc một dòng từsys.stdinvà trả về dòng đó với dòng mới ở cuối đã bị loại bỏ. Nó tăngEOFErrornếu đầu vào bị chấm dứt sớm. Để có được hành vi cũ củainput(), hãy sử dụngeval(input()).Một hàm tích hợp mới
next()đã được thêm vào để gọi phương thức__next__()trên một đối tượng.Chiến lược làm tròn hàm
round()và kiểu trả về đã thay đổi. Các trường hợp chính xác ở giữa giờ đây được làm tròn đến kết quả chẵn gần nhất thay vì cách xa 0. (Ví dụ:round(2.5)hiện trả về2thay vì3.)round(x[, n])hiện ủy quyền chox.__round__([n])thay vì luôn trả về một float. Nó thường trả về một số nguyên khi được gọi với một đối số duy nhất và một giá trị cùng loại vớixkhi được gọi với hai đối số.Đã chuyển
intern()sangsys.intern().Đã xóa:
apply(). Thay vìapply(f, args)hãy sử dụngf(*args).Đã xóa
callable(). Thay vìcallable(f)bạn có thể sử dụngisinstance(f, collections.Callable). Chức năngoperator.isCallable()cũng không còn nữa.Đã xóa
coerce(). Chức năng này không còn phục vụ mục đích nữa khi các lớp cổ điển không còn nữa.Đã xóa
execfile(). Thay vìexecfile(fn)hãy sử dụngexec(open(fn).read()).Đã xóa loại
file. Sử dụngopen(). Hiện có một số loại luồng khác nhau có thể mở trong mô-đunio.Đã xóa
reduce(). Sử dụngfunctools.reduce()nếu bạn thực sự cần nó; tuy nhiên, 99% trường hợp, vòng lặpforrõ ràng sẽ dễ đọc hơn.Đã xóa
reload(). Sử dụngimp.reload().Đã xóa.
dict.has_key()-- thay vào đó hãy sử dụng toán tửin.
Xây dựng và thay đổi C API¶
Do hạn chế về thời gian, đây là danh sách không đầy đủ các thay đổi của very đối với C API.
Hỗ trợ cho một số nền tảng đã bị loại bỏ, bao gồm nhưng không giới hạn ở Mac OS 9, BeOS, RISCOS, Irix và Tru64.
PEP 3118: Bộ đệm mới API.
PEP 3121: Khởi tạo và hoàn thiện mô-đun mở rộng.
PEP 3123: Làm cho
PyObject_HEADphù hợp với tiêu chuẩn C.Không còn hỗ trợ C API cho việc thực thi bị hạn chế.
Các API
PyNumber_Coerce(),PyNumber_CoerceEx(),PyMember_Get()vàPyMember_Set()C bị xóa.C API
PyImport_ImportModuleNoBlock()mới, hoạt động giống nhưPyImport_ImportModule()nhưng không chặn khóa nhập (thay vào đó trả về lỗi).Đã đổi tên khe và phương thức cấp C chuyển đổi boolean:
nb_nonzerohiện lànb_bool.Đã xóa
METH_OLDARGSvàWITH_CYCLE_GCkhỏi C API.
Hiệu suất¶
Kết quả cuối cùng của việc khái quát hóa 3.0 là Python 3.0 chạy điểm chuẩn pystone chậm hơn khoảng 10% so với Python 2.5. Rất có thể nguyên nhân lớn nhất là việc loại bỏ lớp vỏ đặc biệt dành cho số nguyên nhỏ. Vẫn còn chỗ để cải thiện, nhưng điều đó sẽ xảy ra sau khi phiên bản 3.0 được phát hành!
Chuyển sang Python 3.0¶
Để chuyển mã nguồn Python 2.5 hoặc 2.6 hiện có sang Python 3.0, chiến lược tốt nhất là như sau:
(Điều kiện tiên quyết:) Bắt đầu với phạm vi kiểm tra xuất sắc.
Chuyển sang Python 2.6. Điều này sẽ không hiệu quả hơn cổng trung bình từ Python 2.x đến Python 2.(x+1). Hãy chắc chắn rằng tất cả các bài kiểm tra của bạn vượt qua.
(Vẫn đang sử dụng 2.6 :) Bật công tắc dòng lệnh
-3. Điều này cho phép cảnh báo về các tính năng sẽ bị xóa (hoặc thay đổi) trong phiên bản 3.0. Chạy lại bộ thử nghiệm của bạn và sửa mã mà bạn nhận được cảnh báo cho đến khi không còn cảnh báo nào và tất cả các thử nghiệm của bạn vẫn vượt qua.Chạy trình dịch nguồn sang nguồn
2to3trên cây mã nguồn của bạn. Chạy kết quả dịch trong Python 3.0. Khắc phục thủ công mọi vấn đề còn lại, khắc phục sự cố cho đến khi tất cả các bài kiểm tra đều vượt qua.
Bạn không nên thử viết mã nguồn chạy không thay đổi trong cả Python 2.6 và 3.0; bạn sẽ phải sử dụng một phong cách mã hóa rất méo mó, ví dụ: tránh các câu lệnh print, siêu dữ liệu, v.v. Nếu bạn đang duy trì một thư viện cần hỗ trợ cả Python 2.6 và Python 3.0, cách tiếp cận tốt nhất là sửa đổi bước 3 ở trên bằng cách chỉnh sửa phiên bản 2.6 của mã nguồn và chạy lại trình dịch 2to3, thay vì chỉnh sửa phiên bản 3.0 của mã nguồn.
Để chuyển các tiện ích mở rộng C sang Python 3.0, vui lòng xem Chuyển các mô-đun mở rộng sang Python 3.