__ CMP __ trăn là gì?

Bạn cũng có thể muốn đọc chương về , trong đó có nhiều cải tiến khác mà bạn có thể áp dụng cho mã của mình

Chạy bằng Python 2. 7

Bước đầu tiên trong quy trình là chạy mã của bạn bằng Python 2. 6 hoặc 2. 7. Việc bạn sử dụng phiên bản nào ở đây không quan trọng lắm, nhưng rõ ràng phiên bản Python 2 cuối cùng có ý nghĩa nhất, vì vậy nếu bạn có thể sử dụng Python 2. 7, làm như vậy

Hầu hết mã sẽ chạy trực tiếp mà không cần sửa đổi, nhưng có một số điều thay đổi so với Python 2. 5 đến 2. 6. Trong Python 2. 6 aswith là từ khóa, vì vậy nếu bạn sử dụng chúng làm biến . Đơn giản nhất là thêm dấu gạch dưới vào cuối các biến.

>>> with_ = True
>>> as_ = False

Bạn cũng cần loại bỏ các ngoại lệ chuỗi. Việc sử dụng các chuỗi cho các ngoại lệ đã được khuyến nghị trong một thời gian rất dài, chủ yếu là do chúng rất không linh hoạt, chẳng hạn như bạn không thể phân lớp chúng

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!

Trong Python 3 ngoại lệ chuỗi đã hoàn toàn biến mất. Bằng Python 2. 6 bạn không thể nuôi chúng, mặc dù bạn vẫn có thể bắt chúng để tương thích ngược. Trong bất kỳ trường hợp nào, bạn nên xóa tất cả việc sử dụng ngoại lệ chuỗi trong mã của mình và làm cho mã đó chạy trong Python 2. 6 trước khi làm bất cứ điều gì khác

>>> raise Exception("Something went wrong!")
Traceback (most recent call last):
...
Exception: Something went wrong!

Bước tiếp theo là chạy mã của bạn trong Python 2. 6 hoặc Python 2. 7 với tùy chọn -3 . Thao tác này sẽ cảnh báo về những thứ không được hỗ trợ trong Python 3 và những thứ 2to3 sẽ không chuyển đổi. Đó chủ yếu là những cách thực hiện những việc đã bị phản đối từ lâu và có những cách thay thế mới hơn để thực hiện hoặc các mô-đun bị xóa khỏi thư viện tiêu chuẩn. Ví dụ: hỗ trợ cho Mac OS cổ điển đã bị xóa trong Python 3, hiện chỉ hỗ trợ OS X và vì lý do đó, các mô-đun hỗ trợ những thứ cụ thể về Mac OS cổ điển đã bị xóa.

Bạn sẽ nhận được cảnh báo về nhiều thay đổi được liệt kê bên dưới (nhưng không phải tất cả), cũng như đối với một số việc sắp xếp lại thư viện. Các thay đổi sắp xếp lại thư viện rất đơn giản và không cần giải thích, các cảnh báo sẽ cho bạn biết tên mới của mô-đun

Sử dụng // thay vì / khi chia các số nguyên

Trong Python 2 chia hai số nguyên trả về một số nguyên. Điều đó có nghĩa là năm chia hai sẽ trả lại hai

>>> 5/2
2

Tuy nhiên, trong Python 3, nó trả về hai rưỡi

>>> 5/2
2.5

Ngày nay, nhiều người sử dụng toán tử chia trong Python 2 dựa vào phép chia số nguyên để luôn trả về số nguyên. Nhưng việc chuyển đổi tự động với 2to3 sẽ không biết toán hạng là loại gì và do đó không biết toán tử chia có chia hết số nguyên hay không. Do đó, nó không thể thực hiện bất kỳ chuyển đổi nào ở đây. Điều này có nghĩa là nếu bạn đang sử dụng phép chia số nguyên cũ, thì mã của bạn có thể bị lỗi trong Python 3.

Vì thay đổi này đã được lên kế hoạch từ Python 2. 2, nó và tất cả các phiên bản sau này bao gồm một toán tử mới, được gọi là phép chia tầng, được viết bằng hai dấu gạch chéo. Nó luôn trả về toàn bộ số nguyên, ngay cả với số float. Bất kỳ vị trí nào trong mã của bạn mà bạn thực sự muốn phép chia tầng trả về số nguyên, bạn nên thay đổi toán tử chia thành toán tử chia sàn

>>> 5//2
2

>>> 5.0//2.0
2.0

Thường thì hành vi chia số nguyên trong Python 2 là không mong muốn. Cách phổ biến nhất để giải quyết vấn đề đó là chuyển đổi một trong các số nguyên thành số float hoặc thêm dấu phẩy thập phân vào một trong các số

>>> 5/2.0
2.5

>>> a = 5
>>> b = 2
>>> float(a)/b
2.5

Tuy nhiên, có một cách gọn gàng hơn để thực hiện việc này, đó là kích hoạt hành vi Python 3. Điều này được thực hiện thông qua nhập __future__ cũng có sẵn kể từ Python 2. 2.

>>> from __future__ import division
>>> 5/2
2.5

Mặc dù việc chuyển đổi một trong các toán hạng thành số float trước khi chia sẽ hoạt động tốt nhưng điều này là không cần thiết trong Python 3 và bằng cách sử dụng __future__ , bạn sẽ nhập được .

Chạy Python 2. 6 với tùy chọn -3 sẽ cảnh báo bạn nếu bạn sử dụng phép chia số nguyên cũ.

Sử dụng các lớp học kiểu mới

Trong Python 2 có hai loại lớp, “kiểu cũ” và “mới”. Các lớp "kiểu cũ" đã bị xóa trong Python 3, vì vậy, tất cả các lớp hiện được phân lớp từ đối tượng , ngay cả khi chúng không làm như vậy một cách rõ ràng.

Có nhiều sự khác biệt giữa các lớp mới và cũ, nhưng một vài trong số chúng sẽ gây ra cho bạn bất kỳ vấn đề nào với Python 3. Nếu bạn sử dụng nhiều kế thừa, có thể bạn sẽ gặp sự cố do các thứ tự giải quyết phương thức khác nhau

Nếu bạn sử dụng đa kế thừa, do đó, bạn nên chuyển sang sử dụng các lớp kiểu mới trước khi thêm hỗ trợ Python 3. Điều này được thực hiện bằng cách đảm bảo tất cả các lớp con của đối tượng từ đối tượng , và bạn có thể sẽ phải thay đổi thứ tự liệt kê các siêu lớp trong định nghĩa lớp.

Tách dữ liệu nhị phân và chuỗi

Trong Python 2, bạn sử dụng các đối tượng str để chứa dữ liệu nhị phân và văn bản ASCII, trong khi dữ liệu văn bản cần nhiều ký tự hơn những gì có sẵn . Trong Python 3, thay vì các đối tượng unicode objects. In Python 3, instead of strunicode , bạn sử dụng < . Loại bytes objects for binary data and str objects for all kinds of text data, Unicode or not. The str trong Python 3 ít nhiều giống với unicode type in Python 2 and the bytes type is quite similar to Python 2’s str type, even though there are significant differences.

Bước đầu tiên để chuẩn bị cho điều này là đảm bảo rằng bạn không sử dụng cùng một tên biến cho cả dữ liệu nhị phân và dữ liệu văn bản. Trong Python 2, điều này sẽ không gây nhiều rắc rối cho bạn, nhưng trong Python 3 thì có, vì vậy hãy cố gắng tách biệt dữ liệu nhị phân và văn bản càng nhiều càng tốt

Trong Python 2, không''b' file mode flags changes how newlines are treated on some platforms, for example Windows. But the flag makes no difference on Unix, so many programs that are developed for Unix tend to ignore that flag and open binary files in text mode. However, in Python 3 the flags also determine if you get byte hay unicode objects as results when you read from the file. So make sure you really use the text and binary flags when you open a file. Although the text flag is default, add it anyway, as you then show that the text mode is intentional and not just because you forgot to add the flag.

Chạy Python 2. 6 có tùy chọn -3 sẽ không cảnh báo về sự cố này vì đơn giản là không có cách nào để Python 2 biết dữ liệu là văn bản hay dữ liệu nhị phân.

Khi sắp xếp, hãy sử dụng phím key thay vì cmp

Trong Python 2, các phương pháp sắp xếp nhận một tham số cmp . Tham số này phải là một hàm trả về -1, 0 hoặc 1 khi so sánh hai giá trị.

________số 8_______

Vì Python 2. 4 . sort() cũng như hàm sorted() mới (xem ) take a key parameter which should be a function that returns a sorting key.

>>> def keyfunction(item):
..     """Key for comparison that ignores the first letter"""
..     return item[1:]
>>> names = ['Adam', 'Donald', 'John']
>>> names.sort(key=keyfunction)
>>> names
['Adam', 'John', 'Donald']

Điều này dễ sử dụng hơn và chạy nhanh hơn. Khi sử dụng tham số cmp , quá trình sắp xếp sẽ so sánh các cặp giá trị, vì vậy hàm so sánh được gọi nhiều lần cho mỗi mục. Tập dữ liệu càng lớn, hàm so sánh được gọi cho mỗi mục càng nhiều lần. Với hàm key , việc sắp xếp sẽ giữ giá trị khóa cho mỗi mục và so sánh các giá trị đó, vì vậy hàm key chỉ được gọi một lần cho mỗi mục. Điều này dẫn đến việc sắp xếp nhanh hơn nhiều đối với các tập dữ liệu lớn.

Hàm key thường đơn giản đến mức bạn có thể thay thế bằng lambda.

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
0

Trăn 2. 4 cũng giới thiệu tham số reverse .

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
1

Có một trường hợp sử dụng khóa key ít rõ ràng hơn so với sử dụng cmp and that’s when you need to sort on several values. Let’s say we want the result to be sorted with the longest names first and names of the same length should be sorted alphabetically. Doing this with a key không rõ ràng ngay lập tức, nhưng giải pháp thường là sắp xếp hai lần, sắp xếp ít quan trọng nhất trước.

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
2

Điều này hiệu quả vì kể từ Python 2. 3 thuật toán sắp xếp timsort được sử dụng. Đó là một thuật toán ổn định, nghĩa là nếu hai mục được sắp xếp bằng nhau thì thứ tự của các mục đó sẽ được giữ nguyên

Bạn cũng có thể tạo một hàm khóa trả về một giá trị kết hợp hai khóa và sắp xếp trong một lần. Điều này đáng ngạc nhiên là không phải lúc nào cũng nhanh hơn, bạn sẽ phải kiểm tra giải pháp nào nhanh hơn trong trường hợp của mình, nó phụ thuộc vào cả dữ liệu và chức năng chính

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
3

Thông số key đã được giới thiệu trong Python 2. 4, vì vậy nếu bạn cần hỗ trợ Python 2. 3 bạn không thể sử dụng nó. Nếu bạn cần thực hiện nhiều thao tác sắp xếp bằng hàm key, thì tốt nhất bạn nên triển khai một hàm sorted() đơn giản cho Python 2. 3 và sử dụng nó một cách có điều kiện thay vì sorted() dựng sẵn bằng Python 2. 4 trở lên.

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
4

Trăn 2. 4 hiện đã hơn 5 năm tuổi, vì vậy, rất có thể bạn sẽ không cần hỗ trợ Python 2. 3

Cảnh báo

Chạy Python với tùy chọn -3 sẽ chỉ cảnh báo bạn nếu bạn sử dụng cmp parameter explicitly:

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
5

Nhưng nó sẽ không cảnh báo nếu bạn sử dụng nó như thế này

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
6

Vì vậy, cú pháp này có thể trượt qua. Trong những trường hợp này, bạn gặp phải TypeError. phải sử dụng từ khóa đối số cho . key function when running the code under Python 3.

Trong Python 2. 7 và Trăn 3. 2 trở lên, có một hàm sẽ chuyển đổi hàm so sánh thành hàm chính thông qua lớp trình bao bọc. Nó rất thông minh, nhưng sẽ làm cho chức năng so sánh thậm chí còn chậm hơn, vì vậy chỉ sử dụng nó như là phương sách cuối cùng

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
7

Sử dụng các toán tử so sánh phong phú

Trong Python 2, cách phổ biến nhất để hỗ trợ so sánh và sắp xếp các đối tượng của bạn là triển khai một phương thức __cmp__() . . cmp() function, like this class that will sort according to lastname:

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
8

Tuy nhiên, bạn có thể có các đối tượng, chẳng hạn như màu, không “nhỏ hơn” cũng không “lớn hơn”, nhưng vẫn có thể “bằng” hoặc “không bằng”, do đó, vì Python 2. 1 cũng đã hỗ trợ cho các phương thức so sánh phong phú trong đó mỗi phương thức tương ứng với một toán tử so sánh. Họ là __lt__ cho < , __le__ for <=, __eq__ for ==, __ne__ for != , __gt__ cho > . __ge__ for >=.

Việc có cả phương pháp so sánh phong phú và phương pháp __cmp__() vi phạm nguyên tắc chỉ nên có một cách rõ ràng để thực hiện điều đó, . Do đó, đối với Python 3, bạn phải triển khai tất cả các toán tử so sánh phong phú nếu bạn muốn các đối tượng của mình có thể so sánh được. Bạn không cần phải làm điều này trước khi hỗ trợ Python 3 nhưng làm như vậy sẽ giúp trải nghiệm mượt mà hơn một chút. __cmp__() has been removed. For Python 3 you therefore must implement all of the rich comparison operators if you want your objects to be comparable. You don’t have to do this before supporting Python 3 but doing so makes the experience a bit smoother.

Tương đối khó

Việc tạo các phương thức so sánh có thể khá phức tạp, vì bạn cũng cần xử lý việc so sánh các loại khác nhau. Các phương thức so sánh phải trả về hằng số NotImplemented nếu nó không biết cách so sánh với đối tượng khác. Trả về NotImplemented hoạt động như một cờ cho phép so sánh Python khiến Python thử so sánh ngược lại. Vì vậy, nếu phương thức __lt__() của bạn trả về NotImplemented thì Python sẽ cố gắng . __gt__() method instead.

Chú ý

Điều này có nghĩa là bạn không bao giờ được gọi toán tử so sánh các đối tượng khác trong các phương thức so sánh phong phú của mình. Bạn sẽ tìm thấy một số ví dụ về trình trợ giúp so sánh phong phú sẽ chuyển đổi cuộc gọi lớn hơn như self. __gt__(other) vào return other < self. But then you are calling other. __lt__(self) và nếu nó trả về NotImplemented thì Python sẽ thử self. __gt__(other) lần nữa và bạn nhận được đệ quy vô hạn.

Việc triển khai một tập hợp tốt các toán tử so sánh phong phú hoạt động đúng trong mọi trường hợp không khó khi bạn hiểu tất cả các trường hợp, nhưng để nắm bắt được điều đó không hoàn toàn tầm thường. Bạn có thể thực hiện theo nhiều cách khác nhau, cách ưa thích của tôi là mixin này, cách này hoạt động tốt như nhau trong Python 2 và Python 3

>>> raise "Something went wrong!"
Traceback (most recent call last):
...
Something went wrong!
9

Các công cụ functool đã đề cập trước đó. total_ordering() trình trang trí lớp từ Python 3. 2 cũng là một giải pháp hay và nó cũng có thể được sao chép và sử dụng trong các phiên bản Python khác. Tuy nhiên, vì nó sử dụng bộ trang trí lớp nên nó sẽ không hoạt động trong các phiên bản thấp hơn Python 2. 6.

Để sử dụng mixin ở trên, bạn cần triển khai phương thức _cmpkey() trả về khóa của các đối tượng có thể so sánh được, tương tự như . Việc thực hiện có thể trông như thế này. key() function used when sorting. The implementation could look like this:

>>> raise Exception("Something went wrong!")
Traceback (most recent call last):
...
Exception: Something went wrong!
0

Mixin ở trên sẽ trả về NotImplemented nếu đối tượng được so sánh không triển khai a _cmpkey() . _cmpkey() method, or if that method returns something that isn’t comparable with the value that self._cmpkey() trả về. Điều này có nghĩa là mọi đối tượng có _cmpkey() trả về một bộ sẽ được so sánh với tất cả các đối tượng khác cũng có _cmpkey() that returns a tuple and most importantly, if it isn’t comparable, the operators will fall back to asking the other object if it knows how to compare the two objects. This way you have an object which has the maximum chance of meaningful comparisons.

Đang triển khai __hash__()

Trong Python 2, nếu bạn triển khai __eq__() thì bạn cũng nên ghi đè __hash__()< . Điều này là do hai đối tượng so sánh bằng nhau cũng phải có cùng giá trị băm. Nếu đối tượng có thể thay đổi, bạn nên đặt . This is because two objects that compare equal should also have the same hash-value. If the object is mutable, you should set __hash__ thành None , thành . Điều này có nghĩa là bạn không thể sử dụng nó làm khóa trong từ điển chẳng hạn, và điều đó tốt, chỉ các đối tượng bất biến mới là khóa từ điển.

Trong Python 3, __hash__ sẽ được đặt thành Không có automatically if you define __eq__(), and the object will become unhashable, so for Python 3 you don’t need to override __hash__() unless it is an immutable object and you want to be able to use it as a key value.

Giá trị được trả về bởi __hash__() cần phải là số nguyên và hai đối tượng so sánh bằng nhau phải có cùng giá trị băm. Nó phải giữ nguyên trong toàn bộ vòng đời của đối tượng, đó là lý do tại sao các đối tượng có thể thay đổi nên đặt __hash__ = None . to mark them as unhashable.

Nếu bạn đang sử dụng phương pháp _cmpkey() để triển khai các toán tử so sánh được đề cập ở trên, thì hãy triển khai . is very easy:

>>> raise Exception("Something went wrong!")
Traceback (most recent call last):
...
Exception: Something went wrong!
1

Các thuộc tính của lớp này được đánh dấu là nội bộ theo quy ước sử dụng dấu gạch dưới ở đầu, nhưng chúng không hoàn toàn là bất biến. Nếu bạn muốn một lớp thực sự bất biến trong Python, cách dễ nhất là phân lớp bộ sưu tập. têntuple , nhưng điều đó nằm ngoài phạm vi của cuốn sách này.

Đảm bảo rằng bạn không sử dụng bất kỳ mô-đun nào đã bị xóa

Nhiều mô-đun trong thư viện chuẩn đã bị xóa khỏi Python 3. Hầu hết chúng dành riêng cho các hệ điều hành cũ không còn được hỗ trợ nữa và các mô-đun khác đã được thay thế bằng các mô-đun mới với giao diện tốt hơn

Chạy Python 2. 6 với tùy chọn -3 sẽ cảnh báo bạn nếu bạn sử dụng một số mô-đun thường được sử dụng. Rất có thể bạn đang sử dụng bất kỳ mô-đun nào mà Python 2. 6 sẽ không cảnh báo, nhưng nếu bạn đang và dự định hỗ trợ cả Python 2 và Python 3, thì bạn nên thay thế chúng bằng các phiên bản hiện đại của chúng, nếu có.

Xem danh sách các mô-đun đã xóa

Thử nghiệm phạm vi và độc tố

Có một bộ kiểm thử tốt luôn có giá trị đối với bất kỳ dự án nào. Khi bạn thêm hỗ trợ Python 3, việc có các bài kiểm tra sẽ tăng tốc quá trình lên rất nhiều, vì bạn sẽ phải chạy đi chạy lại các bài kiểm tra và việc kiểm tra một ứng dụng bằng tay sẽ mất rất nhiều thời gian

Bạn nên tăng phạm vi thử nghiệm bằng nhiều thử nghiệm hơn. Công cụ Python phổ biến nhất để nhận báo cáo về phạm vi kiểm tra của các mô-đun của bạn là mô-đun phạm vi của Ned Batchelder. Nhiều khung chạy thử nghiệm như zope. thử nghiệm, mũi và py. thử nghiệm bao gồm hỗ trợ cho mô-đun mức độ phù hợp , vì vậy bạn có thể đã cài đặt mô-đun này rồi.

Nếu bạn đang phát triển một mô-đun hỗ trợ nhiều phiên bản Python, thì việc chạy thử nghiệm cho tất cả các phiên bản này sẽ nhanh chóng trở thành một việc vặt. Để giải quyết vấn đề này, Holger Krekel đã tạo một công cụ có tên là tox sẽ cài đặt một virtualenv cho mỗi phiên bản mà bạn muốn hỗ trợ và sẽ chạy thử nghiệm của bạn với tất cả các phiên bản này. . Nó có vẻ như là một điều nhỏ nhặt, và đúng là như vậy, nhưng nó làm cho trải nghiệm dễ chịu hơn một chút. Nếu bạn dự định hỗ trợ cả Python 2 và Python 3, bạn nên dùng thử.

Không bắt buộc. Sử dụng các phương thức lặp trên từ điển

Vì Python 2. 2, loại từ điển Python tích hợp có các phương thức iterkeys() , itervalues() and iteritems(). They yield the same data as keys() , values() và . items() do, but instead of returning lists they return iterators, which saves memory and time when using large dictionaries.

>>> raise Exception("Something went wrong!")
Traceback (most recent call last):
...
Exception: Something went wrong!
2

Trong Python 3 tiêu chuẩn keys() , values() and items() return dictionary views, which are very similar to the iterators of Python 2. As there is no longer any need for the iterator variations of these methods they have been removed.

2to3 sẽ chuyển đổi cách sử dụng các phương thức lặp thành các phương thức tiêu chuẩn. Bằng cách sử dụng rõ ràng các phương pháp lặp, bạn làm rõ rằng bạn không cần danh sách, điều này hữu ích cho chuyển đổi 2to3 , nếu không sẽ thay thế danh sách của bạn . values() dict.values() gọi bằng list(dict. values()) để đảm bảo an toàn.

Trăn 2. 7 cũng có các trình lặp dạng xem mới có sẵn trên từ điển như . viewitems() , . viewkeys(). viewvalues() , nhưng vì chúng không tồn tại trong các phiên bản Python cũ nên chúng chỉ hữu ích khi bạn có thể ngừng hỗ trợ Python 2. 6 trở về trước.

Cũng lưu ý rằng nếu mã của bạn dựa vào danh sách được trả về, thì có lẽ bạn đang lạm dụng từ điển bằng cách nào đó. Ví dụ: trong mã bên dưới, bạn thực sự không thể dựa vào thứ tự của các phím giống nhau mọi lúc, dẫn đến bạn không thể dự đoán chính xác mã sẽ hoạt động như thế nào. Điều này có thể dẫn đến một số gỡ lỗi rắc rối

CMP trong Python là gì?

Phương thức Python - cmp() . Kết quả so sánh là -1 nếu số thứ nhất nhỏ hơn số thứ hai và 1 nếu số thứ nhất lớn hơn số thứ hai. Nếu cả hai đều bằng nhau thì kết quả của cmp() bằng không. part of the python standard library which compares two integers. The result of comparison is -1 if the first integer is smaller than second and 1 if the first integer is greater than the second. If both are equal the result of cmp() is zero.

Chức năng CMP là gì?

CMP được sử dụng để kiểm tra một số chức năng và quy trình của cơ thể, bao gồm. Sức khỏe gan và thận . lượng đường trong máu. Nồng độ protein trong máu.

Làm cách nào để so sánh 2 danh sách trong Python?

Bạn có thể sử dụng hàm map() của Python cùng với các công cụ funcool. hàm reduce() để so sánh các mục dữ liệu của hai danh sách. Khi bạn sử dụng chúng kết hợp, hàm map() sẽ áp dụng hàm đã cho cho mọi phần tử và hàm reduce() đảm bảo rằng nó áp dụng hàm theo cách liên tiếp.

CMP trong mã hóa là gì?

Hàm cmp() . Hàm cmp() tích hợp thường sẽ chỉ trả về các giá trị -1, 0 hoặc 1. Tuy nhiên, có những nơi khác mong đợi các hàm có cùng trình tự gọi và các hàm đó có thể trả về các giá trị khác. A positive number if x is greater than y. The built-in cmp() function will typically return only the values -1, 0, or 1. However, there are other places that expect functions with the same calling sequence, and those functions may return other values.