Skip to content

Latest commit

 

History

History
571 lines (433 loc) · 28.4 KB

5.-data-structures.md

File metadata and controls

571 lines (433 loc) · 28.4 KB
description

5. Data Structures

Phần này sẽ mô tả chi tiết hơn những gì bạn đã học qua và bổ sung một số phần mới nữa!

5.1. Nhiều hơn về Lists

Có khá nhiều phương thức (methods) để xử lý kiểu Danh sách (list). Sau đây là tất cả các cách ấy:

list.append(x)

Nối thêm một phần tử vào cuối danh sách. Tương tự như là a[len(a):] = [x].

list.extend(iterable)

Mở rộng danh sách bằng cách thêm tất cả các phần tử từ iterable. Tương tự a[len(a):] = iterable.

list.insert(i, x)

Chèn một phần tử vào vị trí nào đó trong danh sách. Thông số đầu tiên là vị trí của phần tử phía trước, theo đó a.insert(0, x) sẽ chèn ngay đầu danh sách và a.insert(len(a), x) tương tự với a.append(x).

list.remove(x)

Loại bỏ phần tử có giá trị là x trong danh sách. Nó sẽ lỗi nếu không có phần tử thích hợp.

list.pop([i])

Loại bỏ phần tử có vị trí i và trả về nó. Nếu không có vị trí nào đặc biệt được chỉ định, a.pop() loại bỏ và trả về phần tử ở cuối danh sách. (Dấu ngoặc vuông quanh i trong phương thức biểu thị rằng thông số đó là tùy chọn chứ bạn không nên nhập nó vào. Bạn sẽ nhìn thấy ký hiệu này thường xuyên khi tham chiếu với thư viện của Python.)

list.clear()

Loại bỏ tất cả các phần tử trong danh sách. Tương tự với del a[:].

list.index(x[, start[, end]])

Trả về vị trí zero-based (đếm từ 0) của phần tử đầu tiên có giá trị x. Lỗi ValueError sẽ phát sinh nếu giá trị chỉ định không được tìm thấy.

Các thiết đặt startend được giải thích trong slice notation và sử dụng để giới hạn tìm kiếm đến một phần cụ thể trong danh sách. Vị trí trả về được xác định từ phần đầu của dãy đầy đủ thay vì từ vị trí start.

list.count(x)

Trả về số lần x xuất hiện trong danh sách.

list.sort(key=None, reverse=False)

Sắp xếp các phần tử trong danh sách tại chỗ (có thể sử dụng các tham số để tùy biến, xem sorted() để hiểu thêm).

list.reverse()

Đảo ngược thứ tự các phần tử của danh sách tại chỗ.

list.copy()

Trả về danh sách mới giống với cái cũ. Tương tự như việc cắt a[:].

Một số ví dụ làm rõ các phương thức trên:

>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4)  # Find next banana starting a position 4
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'

Có thể bạn đã nhận ra insert, remove hay sort chỉ thay đổi danh sách chứ không trả về phần tử nào – mặc định chúng sẽ trả về None. [1] Đây là nguyên tắc thiết kế của tất cả các cấu trúc dữ liệu biến đổi trong Python.

5.1.1. Sử dụng Lists như Ngăn xếp (Stacks)

Các list methods làm cho việc sử dụng list như một ngăn xếp (Stacks) trở nên dễ dàng, nguyên tắc là ai vào sau sẽ ra trước, giống như xếp chồng sách, cuốn nào xếp sau sẽ ở trên cùng và được lấy đầu tiên (“last-in, first-out”). Để thêm một phần tử vào stack, sử dụng append(). Để lấy ra phần tử đầu tiên (phần tử thêm sau cùng), sử dụng pop() mà không cần thêm vị trí cụ thể nhé. Ví dụ:

>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]

5.1.2. Sử dụng Lists như Hàng đợi (Queues)

Hoàn toàn khả thi nếu sử dụng Lists như một Hàng đợi (Queues), nghĩa là ai vào trước sẽ ra trước (“first-in, first-out”); tuy nhiên, không hiệu quả. Trong khi việc thêm hay lấy ra phần tử cuối cùng của danh sách diễn ra nhanh chóng thì chèn hay lấy phần tử đầu tiên lại khó khăn và chậm chạp hơn (bởi vì tất cả các thành phần đều phải dịch chuyển một bước).

Để cài một Queue, hãy sử dụng collections.deque được thiết kế để nối hay rút từ cả hai phía của danh sách. Ví dụ:

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")           # Terry arrives
>>> queue.append("Graham")          # Graham arrives
>>> queue.popleft()                 # The first to arrive now leaves
'Eric'
>>> queue.popleft()                 # The second to arrive now leaves
'John'
>>> queue                           # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])

5.1.3. Danh sách tổng quát (Comprehensions)

List comprehensions cung cấp cách tối giản để tạo ra một lists. Ứng dụng cơ bản là tạo ra danh sách mới chứa các phần tử là kết quả của một vài phép tính và được áp dụng cho mỗi thành phần của dãy số hay iterable, hoặc để tạo ra một phân dãy (subsequence) từ các phần tử thỏa mãn điều kiện nào đó.

Ví dụ, giả định chúng ta muốn tạo ra danh sách các số chính phương, như:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Chú ý rằng việc này tạo ra (hoặc ghi đè) biến x và tên biến sẽ được dùng tới khi vòng lặp kết thúc. Chúng ta có thể tính toán, bình phương mà không cần thêm gì khác:

squares = list(map(lambda x: x**2, range(10)))

Hay là:

squares = [x**2 for x in range(10)]

Thật là ngắn gọn, súc tích và dễ đọc phải không nào.

Một list comprehension bao gồm cặp ngoặc chứa các biểu thức, đi kèm câu lệnh for, sau đó có thể là không có hoặc nhiều vòng for hay là các lệnh if. Kết quả là một danh sách mới được lấy từ việc đánh giá các biểu thức trong điều kiện của vòng for và lệnh if đi kèm. Ví dụ, listcomp này dính các thành phần khác nhau của hai danh sách:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

và nó tương tự:

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Chú ý thứ tự của các câu lệnh forif tương ứng trong cả hai đoạn trích dẫn trên.

Nếu biểu thức là một tập hợp (tuple) (vd. như (x, y) trong ví dụ trên), thì phải dùng ngoặc đơn để gói lại.

>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
  File "<stdin>", line 1, in <module>
    [x, x**2 for x in range(6)]
               ^
SyntaxError: invalid syntax
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

List comprehensions có thể chứa biểu thức phức tạp và các hàm hợp:

>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

5.1.4. Các Lists Comprehension lồng nhau

Biểu thức khởi tạo trong một Lists Comprehension có thể là tùy ý, bao gồm nhiểu list-comp khác.

Xem ví dụ sau, một ma trận 3x4 là một danh sách của 3 danh sách khác có chiều dài 4:

>>> matrix = [
...     [1, 2, 3, 4],
...     [5, 6, 7, 8],
...     [9, 10, 11, 12],
... ]

List comprehension sau sẽ chuyển vị trí ở các hàng và các cột:

>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Như chúng ta thấy ở phần trước, listcomp lồng nhau được đánh giá trong điều kiện của vòng for, vậy nên ví dụ này tương đương với:

>>> transposed = []
>>> for i in range(4):
...     transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Nếu phân tích kỹ hơn thì là thế này:

>>> transposed = []
>>> for i in range(4):
...     # the following 3 lines implement the nested listcomp
...     transposed_row = []
...     for row in matrix:
...         transposed_row.append(row[i])
...     transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Trong thực tế, bạn nên ưu tiên dùng các hàm dựng sẵn (built-in functions) cho các biểu thức luồng phức tạp. Hàm zip() trở nên rất đẹp trong trường hợp này:

>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

Xem Unpacking Argument Lists để biết thêm chi tiết vể dấu *

5.2. Câu lệnh del

Có một cách để xóa một phần tử từ một danh sách bằng vị trí của nó thay vì là giá trị: Lệnh del. Cái này khác với phương thức pop() là nó có trả về giá trị của phần tử đó. Lệnh del cũng có thể được sử dụng để loại bỏ các mảnh (slices) của danh sách hoặc xóa sạch toàn bộ danh sách (Chúng tôi đã thực hiện việc này trước đó, bằng cách gán cho các slice một danh sách trống ). Ví dụ:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]

del còn được sử dụng để xóa các biến:

>>> del a

Tham chiếu a sau đây là một sai lầm (ít nhất cho tới khi nó được gán với một giá trị mới). Chúng ta sẽ tìm kiếm cơ hội để del tỏa sáng sau nhé.

5.3. Tuples và các dãy

Rõ ràng lists và strings có nhiều thuộc tính chung, đơn cử indexing hay slicing operations. Chúng là hai ví dụ của kiểu dữ liệu dãy sequence (xem Sequence Types — list, tuple, range). Vì Python là một ngôn ngữ phát triển (evolving language), các kiểu sequence khác có thể được thêm vào. Ngoài ra còn có một kiểu sequence chuẩn ấy là: tuple.

Một tuple chứa một số giá trị ngăn cách bởi dấu phẩy, ví dụ:

>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

Như bạn đã thấy, khi chào đời, Tuple luôn mang theo cặp ngoặc đơn (mình thường liên tưởng tới hình ảnh con rùa turtle) để thông dịch một cách chính xác; chúng có thể có hoặc không có dấu ngoặc đơn khi là đầu vào, dù vậy thường thì chúng ta luôn cần tới đôi ngoặc đơn này (nếu Tuple là một phần của biểu thức lớn hơn). Không thể gán các thành phần riêng lẻ của Tuple, tuy nhiên việc tạo ra một tuple chứa nhiều đối tượng như list thì là có thể.

Tuples có thể gần giống với Lists, chúng được sử dụng trong nhiều tình huống khác nhau và cho nhiều mục đích khác nhau. Tuples là bất biến, và thường chứa các thành phần có thứ tự hỗn độn được truy cập thông qua giải nén (xem phần này sau) hoặc indexing (hoặc thậm chí theo thuộc tính trong trường hợp namedtuples). Lists có thể biến đổi, và các thành phần của chúng thường có trật tự, được truy cập bằng cách lặp qua mảng.

Điều đặc biệt là cấu trúc của Tuples chứa 0 hoặc 1 phần tử: cú pháp có một vài ngoại lệ. Tuples rỗng được xây dựng bởi một cặp ngoặc đơn; một tuple với một phần tử bao gồm một giá trị kèm theo dấu phẩy (nó không đủ để kèm theo một gía trị trong dấu ngoặc đơn). Xấu, nhưng kết cấu nó...hiệu quả. Ví dụ:

>>> empty = ()
>>> singleton = 'hello',    # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

Câu lệnh t = 12345, 54321, 'hello!' là một ví dụ của tuple packing: giá trị 12345, 54321'hello!' được gói cùng nhau trong một Tuple. Và ngược lại, nó có thể được gán cho lần lượt các biến:

>>> x, y, z = t

Đây được gọi là, một cách thích hợp, giải nén dãy sequence unpacking nó hoạt động với bất kỳ tuple nào phía bên phải. Giải nén dãy yêu cầu có nhiều biến bên trái dấu bằng, tương đương với số phần tử trong tuple. Chú ý rằng việc gán nhiều một lúc thực chất là việc đóng gói tuple và giải nén dãy.

5.4. Sets

Python có một kiểu dữ liệu cho các tập hợp. Một set là một bộ sưu tập hỗn độn các phần tử khác nhau. Sử dụng đơn giản với việc kiểm tra thành viên và loại bỏ các mục trùng lặp. Đối tượng Set cũng hỗ trợ các toán tử như Hợp (union), Giao (intersection), Khác (difference) và Hiệu số đối xứng ( symmetric difference).

Dấu ngoặc nhọn hoặc hàm set() có thể sử dụng để tạo ra các set. Chú ý: để tạo một set rỗng bạn phải dùng set(), chứ không phải {}; vì nó sẽ trùng hợp với việc tạo ra một Dictionary rỗng, một cấu trúc mà chúng ta sẽ tìm hiểu sau.

Đây là một ví dụ ngắn gọn:

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket)                      # show that duplicates have been removed
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket                 # fast membership testing
True
>>> 'crabgrass' in basket
False

>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b                              # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # letters in both a and b
{'a', 'c'}
>>> a ^ b                              # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}

Giống với list comprehensions, set comprehensions cũng được hỗ trợ (thích ghê):

>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}

5.5. Từ điển (Dictionaries)

Một kiểu dữ liệu hữu dụng nữa được xây dựng cho Python đó là dictionary (xem Mapping Types — dict). Dictionaries thường được định nghĩa cùng các từ ngữ như “associative memories” hay “associative arrays”. Không giống như các dãy, định vị bằng chỉ số thì dictionaries được ghi bởi keys, nó (keys) có thể là một kiểu bất biến nào đấy; chuỗi (string) và các số cũng có thể là keys. Tuples có thể được sử dụng như là chìa khóa nếu chúng chỉ chứa các chuỗi, số, hoặc tuple; nếu một tuple chứa bất kỳ một đối tượng biến đổi nào đấy một cách trực tiếp hay gián tiếp thì nó không thể sử dụng như một key. Bạn không thể sử dụng danh sách như một key, vì lists có thể bị sửa đổi tại chỗ sử dụng index assignments, slice assignments, hoặc một số phương thức như append()extend().

Cách tốt nhất là hiểu Dict như tập hợp các cặp key: value, với yêu cầu rằng các keys phải độc nhất (trong mỗi Dict). Một cặp ngoặc nhọn tạo nên một dict trống: {}. Nhớ đặt dấu phẩy để phân cách các cặp key:value trong ngoặc nhọn nhé; đây cũng là cách hiển thị của Dict trong output.

Các thao tác chính với một dict là lưu trữ dữ liệu với một vài khóa và lấy về giá trị khi gọi tới khóa. Chúng ta cũng có thể xóa cặp key:value với del. Nếu bạn lưu trữ bằng khóa đã được sử dụng, giá trị được chỉ định trước đó sẽ bị xóa. Tất nhiên sẽ phát sinh lỗi nếu bạn truy cập một giá trị của một khóa không xác định.

Thao tác list(d.keys()) trên một Dict trả về một danh sách tất cả các key có trong dict đó, trong một sắp đặt bất kỳ (nếu bạn muốn sắp xếp lại, chỉ cần sử dụng sorted(d.keys())). [2] để kiểm tra xem có đúng là key trong dict không, sử dụng từ khóa in.

Sau đây là ví dụ đơn giản về việc sử dụng dictionary:

>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> list(tel.keys())
['irv', 'guido', 'jack']
>>> sorted(tel.keys())
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False

Hàm dựng dict() xây dựng dictionaries trực tiếp từ các cặp key:value:

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}

Ngoài ra, dict comprehensions có thể được sử dụng để tạo các dictionary từ các key and value tương ứng:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

Khi các khóa là các chuỗi đơn giản, đôi khi nó sẽ dễ dàng hơn trong việc chỉ định các cặp khóa:

>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}

5.6. Kỹ thuật lặp

Khi lặp qua các từ điển (dict), các khóa và giá trị tương ứng có thể được lấy ra cùng lúc bằng cách sử dụng phương thức items().

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
...     print(k, v)
...
gallahad the pure
robin the brave

Khi duyệt qua một dãy, chỉ số và giá trị tương ứng được lấy cùng lúc, chỉ cần sử dụng hàm enumerate().

>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print(i, v)
...
0 tic
1 tac
2 toe

Để duyệt qua nhiều dãy cùng lúc, có thể ghép toàn bộ lại bằng hàm zip().

>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
...     print('What is your {0}?  It is {1}.'.format(q, a))
...
What is your name?  It is lancelot.
What is your quest?  It is the holy grail.
What is your favorite color?  It is blue.

Để duyệt ngược, đầu tiên là xác định chiều của dãy và gọi tới hàm reversed().

>>> for i in reversed(range(1, 10, 2)):
...     print(i)
...
9
7
5
3
1

Để duyệt qua một danh sách có yêu cầu sắp xếp theo thứ tự, sử dụng hàm sorted() nó sẽ trả lại một list mới mà không phương hại gì tới list cũ.

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print(f)
...
apple
banana
orange
pear

Đôi khi bạn cố thay đổi danh sách trong lúc bạn đang lặp nó phải không nào; tuy nhiên, cách đơn giản và an toàn nhất vẫn là tạo một danh sách mới.

>>> import math
>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
...     if not math.isnan(value):
...         filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]

5.7. Nhiều hơn về Câu điều kiện

Câu điều kiện được sử dụng trong vòng while và lệnh if có thể chứa các phép tính, không chỉ đơn giản là so sánh.

Các toán tử so sánh innot in kiểm tra xem giá trị thuộc (hay không thuộc) một dãy. Toán tử isis not so sánh để xem hai thằng có giống nhau hay không; đây là các vấn đề của đối tượng biến đổi như Lists. Tất cả các phép so sánh với List đều được ưu tiên như nhau , ở mức thấp hơn tất cả các toán tử với số.

Chúng ta có thể 'xích' (chaind) nối các toán tử so sánh với nhau. Ví dụ, a < b == c thử a có nhỏ hơn bb có bằng c không.

Dính các phép so sánh với các toán tử Boolean and , or và phủ nhận kết quả của một phép so sánh (hoặc của bất kỳ các biểu thức Boolean nào) với not. Mức ưu tiên của các phép này thấp hơn so với các toán tử so sánh; trong đó, not có mức ưu tiên cao nhất và or thấp nhất, vậy nên A and not B or C tương đương với (A and (not B)) or C. Như thường lệ, ta lại thấy sự xuất hiện cửa dấu ngoặc đơn nhằm thể hiện rõ các thành phần tham gia.

Các toán tử Boolean andor được gọi là toán tử đoản mạch short-circuit : Đối số của chúng được đánh giá từ trái sang phải, và nó sẽ dừng lại ngay khi kết quả được xác định. Ví dụ, nếu AC là đúng nhưng B sai, A and B and C không đánh giá C nữa. Khi đối số là các giá trị thông thường, không phải là một Boolean, giá trị trả về của toán tử đoản mạch là đối số được đánh giá cuối cùng.

Chúng ta hoàn toàn có thể gán kết quả của một phép so sánh hoặc các biểu thức Boolean cho biến số. Ví dụ,

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'

Chú ý rằng trong Python, không giống C, phép gán không thể xảy ra bên trong biểu thức. Lâp trình viên C có lẽ sẽ cằn nhằn cho mà xem, nhưng nó tránh khỏi các sự cố nhập liệu trong chương trình C: Nhập = trong một biểu thức mà đã dự định dùng ==.

5.8. So sánh chuỗi và các loại khác

Các chuỗi cùng loại có thể được so sánh lẫn nhau. Để làm được việc ấy chúng ta sẽ sử dụng sắp xếp lexicographical : thoạt đầu hai phần tử đầu tiên được so sánh; nếu chúng khác nhau, kết quả sẽ được ghi nhận; nếu chúng bằng nhau, hai phần tử tiếp theo sẽ được đưa vào lò, và cứ như vậy, cho tới khi cả hai chuỗi cạn kiệt. Nếu bản thân hai phần tử để so sánh là các chuỗi cùng loại, thì lexicographical comparison được thực hiện đệ quy. Nếu tất cả phần tử của hai chuỗi đều bằng nhau, thì hai chuỗi đấy bằng nhau (dễ nhỉ). Nếu một trong hai chuỗi là một phân chuỗi mở đầu của cái kia thì chuỗi ngắn hơn sẽ nhỏ hơn (ít hơn). Sắp xếp Lexicographical cho các chuỗi sử dụng số điểm mã Unicode (code point) để sắp đặt các ký tự riêng lẻ. Một số ví dụ về so sánh hai chuỗi cùng loại:

(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)

Chú ý rằng việc so sánh các đối tượng khác loại với < or > là hợp lệ nếu có phương pháp phù hợp. Ví dụ, các loại số bị trộn (Mixed numeric) được đem đi so sánh bằng giá trị của chúng, 0 bằng 0.0, v.v. Mặt khác, thay vì cung cấp một sắp xếp tùy tiện, trình thông dịch sẽ phát sinh một TypeError ngoại lệ.

Ghi chú:

| [1] | Các ngôn ngữ khác sẽ trả về đối tượng biến đổi, cho phép sử dụng phương thức chuỗi(chain), như d->insert("a")->remove("b")->sort();. | | --- |

| [2] | Gọi d.keys() thì sẽ trả về một đối tượng dictionary view. Nó hỗ trợ các tiến trình như kiểm tra các thành viên và lặp, nhưng nội dung của nó không phụ thuộc vào dict gốc – chỉ là view. | | --- |