Hướng dẫn python attrgetter - con trăn

Tác giả

Andrew Dalke và Raymond Hettinger

Phóng thích

0.1

Danh sách Python có phương thức

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
7 tích hợp để sửa đổi danh sách tại chỗ. Ngoài ra còn có một chức năng tích hợp
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
8 xây dựng một danh sách được sắp xếp mới từ một điều đáng tin cậy.

Trong tài liệu này, chúng tôi khám phá các kỹ thuật khác nhau để sắp xếp dữ liệu bằng Python.

Sắp xếp những điều cơ bản

Một loại tăng dần đơn giản là rất dễ dàng: chỉ cần gọi hàm

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
8. Nó trả về một danh sách được sắp xếp mới:

>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]

Bạn cũng có thể sử dụng phương pháp

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
7. Nó sửa đổi danh sách tại chỗ (và trả về
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
1 để tránh nhầm lẫn). Thông thường, nó ít thuận tiện hơn
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
8 - nhưng nếu bạn không cần danh sách ban đầu, thì nó lại hiệu quả hơn một chút.

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]

Một điểm khác biệt khác là phương thức

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
7 chỉ được xác định cho danh sách. Ngược lại, hàm
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
8 chấp nhận bất kỳ điều gì có thể.

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]

Chức năng chính¶

Cả

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
7 và
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
8 đều có tham số chính để chỉ định hàm (hoặc có thể gọi khác) để được gọi trên mỗi phần tử danh sách trước khi so sánh.

Ví dụ: ở đây, một so sánh chuỗi không nhạy cảm trường hợp:

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

Giá trị của tham số khóa phải là một hàm (hoặc có thể gọi khác) có một đối số duy nhất và trả về một khóa để sử dụng cho mục đích sắp xếp. Kỹ thuật này nhanh vì hàm chính được gọi chính xác một lần cho mỗi bản ghi đầu vào.

Một mẫu phổ biến là sắp xếp các đối tượng phức tạp bằng cách sử dụng một số chỉ số đối tượng là các khóa. Ví dụ:

>>> student_tuples = [
...     ('john', 'A', 15),
...     ('jane', 'B', 12),
...     ('dave', 'B', 10),
... ]
>>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Kỹ thuật tương tự hoạt động cho các đối tượng với các thuộc tính được đặt tên. Ví dụ:

>>> class Student:
...     def __init__(self, name, grade, age):
...         self.name = name
...         self.grade = grade
...         self.age = age
...     def __repr__(self):
...         return repr((self.name, self.grade, self.age))

>>> student_objects = [
...     Student('john', 'A', 15),
...     Student('jane', 'B', 12),
...     Student('dave', 'B', 10),
... ]
>>> sorted(student_objects, key=lambda student: student.age)   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Chức năng mô -đun vận hành

Các mẫu chức năng khóa được hiển thị ở trên là rất phổ biến, do đó, Python cung cấp các chức năng tiện lợi để làm cho các chức năng của người truy cập dễ dàng và nhanh hơn. Mô -đun

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
7 có chức năng
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
8,
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
9 và
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
0.

Sử dụng các chức năng đó, các ví dụ trên trở nên đơn giản và nhanh hơn:

>>> from operator import itemgetter, attrgetter

>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Các chức năng mô -đun toán tử cho phép nhiều cấp độ sắp xếp. Ví dụ, để sắp xếp theo cấp độ sau đó theo tuổi:

>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

Tăng dần và giảm dần¶

Cả

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
7 và
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
8 đều chấp nhận tham số ngược với giá trị boolean. Điều này được sử dụng để gắn cờ các loại giảm dần. Ví dụ: để lấy dữ liệu của học sinh theo thứ tự tuổi ngược:

>>> sorted(student_tuples, key=itemgetter(2), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

>>> sorted(student_objects, key=attrgetter('age'), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

Sắp xếp sự ổn định và các loại phức tạp

Các loại được đảm bảo là ổn định. Điều đó có nghĩa là khi nhiều bản ghi có cùng một khóa, thứ tự ban đầu của chúng được bảo tồn.

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

Lưu ý cách hai bản ghi cho Blue giữ lại thứ tự ban đầu của họ để

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
3 được đảm bảo trước
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
4.

Khách sạn tuyệt vời này cho phép bạn xây dựng các loại phức tạp trong một loạt các bước sắp xếp. Ví dụ, để sắp xếp dữ liệu học sinh bằng cấp giảm dần và sau đó tăng dần tuổi, hãy sắp xếp tuổi trước và sau đó sắp xếp lại bằng cấp:

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
0

Điều này có thể được trừu tượng hóa thành một hàm trình bao bọc có thể lấy một danh sách và bộ dữ liệu của trường và đặt hàng để sắp xếp chúng trên nhiều đường chuyền.

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
1

Thuật toán TIMSORT được sử dụng trong Python thực hiện nhiều loại hiệu quả vì nó có thể tận dụng bất kỳ thứ tự nào đã có trong bộ dữ liệu.

Trang trí-sort-undecignor¶

Idiom này được gọi là trang trí-dort-undeconation sau ba bước của nó:

  • Đầu tiên, danh sách ban đầu được trang trí với các giá trị mới kiểm soát thứ tự sắp xếp.

  • Thứ hai, danh sách trang trí được sắp xếp.

  • Cuối cùng, các trang trí được loại bỏ, tạo một danh sách chỉ chứa các giá trị ban đầu theo thứ tự mới.

Ví dụ, để sắp xếp dữ liệu của học sinh theo cấp bằng cách sử dụng phương pháp DSU:

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
2

Thành ngữ này hoạt động vì các bộ dữ liệu được so sánh từ vựng; Các mục đầu tiên được so sánh; Nếu chúng giống nhau thì các mục thứ hai được so sánh, v.v.

Không cần thiết hoàn toàn cần thiết trong tất cả các trường hợp để đưa Chỉ số I vào danh sách được trang trí, nhưng bao gồm cả nó mang lại hai lợi ích:

  • Sắp xếp ổn định - nếu hai mục có cùng một khóa, đơn đặt hàng của chúng sẽ được bảo tồn trong danh sách được sắp xếp.

  • Các mặt hàng ban đầu không phải so sánh vì thứ tự của các bộ dữ liệu được trang trí sẽ được xác định nhiều nhất là hai mặt hàng đầu tiên. Vì vậy, ví dụ danh sách ban đầu có thể chứa các số phức tạp không thể được sắp xếp trực tiếp.

Một cái tên khác cho thành ngữ này là Schwartzian Transform, sau Randal L. Schwartz, người đã phổ biến nó trong số các lập trình viên Perl.

Bây giờ việc sắp xếp Python cung cấp các chức năng chính, kỹ thuật này không cần thiết.

Các chức năng so sánh

Không giống như các chức năng chính trả về giá trị tuyệt đối để sắp xếp, hàm so sánh tính toán thứ tự tương đối cho hai đầu vào.

Ví dụ, thang đo cân bằng so sánh hai mẫu cho một thứ tự tương đối: nhẹ hơn, bằng nhau hoặc nặng hơn. Tương tự như vậy, một hàm so sánh như

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
5 sẽ trả về giá trị âm cho ít hơn, 0 nếu các đầu vào bằng nhau hoặc giá trị dương cho lớn hơn.

Người ta thường gặp các hàm so sánh khi dịch thuật toán từ các ngôn ngữ khác. Ngoài ra, một số thư viện cung cấp các chức năng so sánh như là một phần của API của họ. Ví dụ,

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
6 là một hàm so sánh.

Để phù hợp với các tình huống đó, Python cung cấp

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
7 để bọc chức năng so sánh để làm cho nó có thể sử dụng được như một hàm chính:

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
3

Vụn vặt¶

  • Để sắp xếp nhận thức địa phương, hãy sử dụng

    >>> sorted("This is a test string from Andrew".split(), key=str.lower)
    ['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
    
    8 cho chức năng chính hoặc
    >>> sorted("This is a test string from Andrew".split(), key=str.lower)
    ['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
    
    6 cho hàm so sánh. Điều này là cần thiết bởi vì các thứ tự sắp xếp theo thứ tự bảng chữ cái có thể thay đổi giữa các nền văn hóa ngay cả khi bảng chữ cái cơ bản là như nhau.

  • Tham số ngược vẫn duy trì sự ổn định sắp xếp (để các bản ghi có các khóa bằng nhau giữ lại thứ tự ban đầu). Thật thú vị, hiệu ứng đó có thể được mô phỏng mà không cần tham số bằng cách sử dụng hàm

    >>> student_tuples = [
    ...     ('john', 'A', 15),
    ...     ('jane', 'B', 12),
    ...     ('dave', 'B', 10),
    ... ]
    >>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
    
    0 tích hợp hai lần:

    >>> a = [5, 2, 3, 1, 4]
    >>> a.sort()
    >>> a
    [1, 2, 3, 4, 5]
    
    4

  • Các thói quen sắp xếp sử dụng

    >>> student_tuples = [
    ...     ('john', 'A', 15),
    ...     ('jane', 'B', 12),
    ...     ('dave', 'B', 10),
    ... ]
    >>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
    
    1 khi so sánh giữa hai đối tượng. Vì vậy, thật dễ dàng để thêm một thứ tự sắp xếp tiêu chuẩn vào một lớp bằng cách xác định phương thức
    >>> student_tuples = [
    ...     ('john', 'A', 15),
    ...     ('jane', 'B', 12),
    ...     ('dave', 'B', 10),
    ... ]
    >>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
    
    2:

    >>> a = [5, 2, 3, 1, 4]
    >>> a.sort()
    >>> a
    [1, 2, 3, 4, 5]
    
    5

    Tuy nhiên, lưu ý rằng

    >>> student_tuples = [
    ...     ('john', 'A', 15),
    ...     ('jane', 'B', 12),
    ...     ('dave', 'B', 10),
    ... ]
    >>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
    
    1 có thể quay trở lại bằng cách sử dụng
    >>> student_tuples = [
    ...     ('john', 'A', 15),
    ...     ('jane', 'B', 12),
    ...     ('dave', 'B', 10),
    ... ]
    >>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
    
    4 nếu
    >>> student_tuples = [
    ...     ('john', 'A', 15),
    ...     ('jane', 'B', 12),
    ...     ('dave', 'B', 10),
    ... ]
    >>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
    
    2 không được thực hiện (xem
    >>> student_tuples = [
    ...     ('john', 'A', 15),
    ...     ('jane', 'B', 12),
    ...     ('dave', 'B', 10),
    ... ]
    >>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
    [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
    
    6).

  • Các chức năng chính không cần phải phụ thuộc trực tiếp vào các đối tượng được sắp xếp. Một chức năng chính cũng có thể truy cập các tài nguyên bên ngoài. Chẳng hạn, nếu các lớp học sinh được lưu trữ trong từ điển, chúng có thể được sử dụng để sắp xếp một danh sách riêng các tên sinh viên:

    >>> a = [5, 2, 3, 1, 4]
    >>> a.sort()
    >>> a
    [1, 2, 3, 4, 5]
    
    6