Sự khác biệt là reversed
là một trình lặp (nó cũng là đánh giá lười biếng) và sorted
là một hàm hoạt động "háo hức".
Tất cả built-in lặp (ít nhất là trong python-3.x) như map
, zip
, filter
, reversed
, ... được thực hiện như lớp. Trong khi các trình cài sẵn hoạt động háo hức là chức năng, ví dụ: min
, max
, any
, all
và sorted
.
>>> a = [1,2,3,4]
>>> r = reversed(a)
<list_reverseiterator at 0x2187afa0240>
Bạn thực sự cần phải "tiêu thụ" các iterator để có được các giá trị (ví dụ list
):
>>> list(r)
[4, 3, 2, 1]
Mặt khác này "tiêu thụ" một phần là không cần thiết cho chức năng như sorted
:
>>> s = sorted(a)
[1, 2, 3, 4]
tôi n các ý kiến nó được hỏi lý do tại sao chúng được thực hiện như là các lớp thay vì chức năng. Điều đó không thực sự dễ dàng để trả lời nhưng tôi sẽ cố hết sức:
Sử dụng các hoạt động đánh giá lười biếng có một lợi ích to lớn: Chúng rất hiệu quả khi bị xâu chuỗi.Họ không cần tạo danh sách trung gian trừ khi chúng được "yêu cầu" rõ ràng. Đó là lý do tại sao map
, zip
và filter
được thay đổi từ các hàm hoạt động háo hức (python-2.x) thành các lớp hoạt động lười biếng (python-3.x).
Nói chung có hai cách bằng Python để tạo vòng lặp:
- lớp
return self
trong phương pháp __iter__
họ chức năng máy phát điện
- - chức năng có chứa một
yield
Tuy nhiên (ít nhất CPython) thực hiện tất cả các built-in của họ (và một số mô-đun thư viện tiêu chuẩn) trong C. Nó rất dễ dàng để tạo các lớp lặp trong C nhưng tôi đã không tìm thấy bất kỳ cách nào hợp lý để tạo ra máy phát funct các ion dựa trên Python-C-API. Vì vậy, lý do tại sao các trình vòng lặp này được thực hiện như các lớp (trong CPython) có thể chỉ là tiện lợi hoặc thiếu các lựa chọn thay thế (nhanh hoặc có thể thực hiện).
Có một lý do khác để sử dụng lớp thay vì máy phát: Bạn có thể triển khai các phương pháp đặc biệt cho lớp học nhưng bạn không thể triển khai chúng trên các chức năng của trình tạo. Điều đó nghe có vẻ không ấn tượng nhưng nó có lợi thế nhất định. Ví dụ: hầu hết các trình lặp có thể là pickled (ít nhất là trên Python-3.x) bằng cách sử dụng các phương thức __reduce__
và __setstate__
. Điều đó có nghĩa là bạn có thể lưu trữ chúng trên đĩa và cho phép sao chép chúng. Kể từ Python-3.4 một số vòng lặp cũng thực hiện __length_hint__
mà làm cho tiêu thụ các iterators với list
(và tương tự) nhanh hơn nhiều.
Lưu ý rằng reversed
dễ dàng có thể được thực hiện như nhà máy chức năng (như iter
) nhưng không giống như iter
, mà có thể trở lại hai độc đáo lớp, reversed
chỉ có thể trở lại một độc đáo lớp.
Để minh họa cho các lớp có thể (và duy nhất), bạn phải xem xét một lớp học mà không có __iter__
và không __reversed__
phương pháp nhưng iterable và ngược iterable (bằng cách thực hiện __getitem__
và __len__
):
class A(object):
def __init__(self, vals):
self.vals = vals
def __len__(self):
return len(self.vals)
def __getitem__(self, idx):
return self.vals[idx]
Và trong khi nó làm cho tinh thần để thêm một lớp trừu tượng (một chức năng nhà máy) trong trường hợp iter
- bởi vì lớp trở là tùy thuộc vào số lượng các đối số đầu vào:
>>> iter(A([1,2,3]))
<iterator at 0x2187afaed68>
>>> iter(min, 0) # actually this is a useless example, just here to see what it returns
<callable_iterator at 0x1333879bdd8>
Lý do đó không áp dụng cho reversed
:
>>> reversed(A([1,2,3]))
<reversed at 0x2187afaec50>
Chúng khác nhau vì chúng làm những việc khác nhau. Kết quả cuối cùng có thể được xem là tương tự, nhưng cách để có được kết quả cuối cùng là rất khác nhau. –
Đầu cơ không có dấu gạch ngang: 'đảo ngược' là một kiểu vì nó trả về một biến lặp thực hiện phương thức [' __length_hint__'] (https://docs.python.org/3/reference/datamodel.html#object.__length_hint__). Vì phương thức này phải được định nghĩa trong một lớp, nên nó có ý nghĩa đối với 'đảo ngược' chính nó là lớp đó. (Vấn đề với lý thuyết này là '__length_hint__' chỉ tồn tại kể từ python 3.4) –
Hãy để tôi hỏi câu hỏi ngược lại: tại sao bạn mong đợi chúng giống nhau? – jpmc26