Python – Kiểu List


Được đăng vào ngày 23/01/2016 | 2 bình luận
Python – Kiểu List
5 (100%) 4 votes

Bên cạnh String, list cũng là một kiểu dữ liệu quan trọng và trong phần này chúng ta sẽ tìm hiểu sâu hơn về list.

List là một danh sách các phần tử, các phần tử trong một list có thể có nhiều kiểu dữ liệu khác nhau. Các phần tử trong list được lưu trữ theo thứ tự. Giá trị của các phần tử có thể giống nhau.

Các phần tử trong list có thể được truy xuất thông qua chỉ số. Cũng như các kiểu tập hợp khác, chỉ số trong list được đánh số từ 0.


nums = [1, 2, 3, 4, 5]
print (nums)

Trong ví dụ trên, chúng ta có một list có 5 phần tử. List được khởi tạo trong cặp dấu []Các phần tử của list được phân cách bởi dấu phẩy.

[1, 2, 3, 4, 5]

Các phần tử trong một list có thể mang nhiều kiểu dữ liệu khác nhau.


class Being:
    pass

objects = [1, -2, 3.4, None, False, [1, 2], "Python", (2, 3), Being(), {}]
print (objects)

Ví dụ trên tạo ra một list có nhiều kiểu dữ liệu khác nhau, bao gồm kiểu số nguyên, kiểu bool, một string, một tuple, một kiểu từ điển và nguyên cả một list khác.

[1, -2, 3.4, None, False, [1, 2], 'Python', (2, 3), <__main__.Being instance at 0xb76a186c>, {}]

Khởi tạo list

Cách khởi tạo ở trên là cách khởi tạo bằng cách đưa giá trị trực tiếp, ngoài ra bạn có thể khởi tạo mà không cần biết giá trị cụ thể:


n1 = [0 for i in range(15)]
n2 = [0] * 15

print (n1)
print (n2)

n1[0:11] = [10] * 10

print (n1)

Ví dụ trên mô tả hai cách khởi tạo một list. Cách đầu tiên dùng vòng lặp for với cú pháp comprehension bên trong cặp dấu [], cách thứ hai là dùng toán tử *.

n1 = [0 for i in range(15)]
n2 = [0] * 15

Hai dòng code trên ví dụ về cách khởi tạo list dùng toán tử * và cú pháp comprehension, cú pháp comprehension sẽ được giải thích ở gần cuối bài này. Kết quả đều cho ra một list các phần tử có giá trị là 0.

n1[0:11] = [10] * 10

Dòng code trên gán 10 phần tử đầu tiên với giá trị 10.

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0]

Hàm list()

Hàm list() có tác dụng khởi tạo một list từ một đối tượng tập hợp, có thể là 1 tuple, 1 list khác… hoặc tạo một list rỗng.


a = []
b = list()

print (a == b)

print (list((1, 2, 3)))
print (list("PhoCode"))
print (list(['Ruby', 'Python', 'Perl']))

Trong ví dụ trên, chúng ta khởi tạo một list rỗng, một list từ một string, một list từ một tuple và một list từ một list khác.

a = []
b = list()

Hai dòng trên là 2 cách để khởi tạo một list rỗng.

print (a == b)

Dòng trên sẽ cho ra kết quả True vì và bằng nhau.

print (list((1, 2, 3)))

Dòng trên tạo một list từ một tuple.

print (list("PhoCode"))

Dòng code trên tạo một list từ một string.

print (list(['Ruby', 'Python', 'Perl']))

Cuối cùng là tạo một list từ một list khác.

True
[1, 2, 3]
['Z', 'e', 't', 'C', 'o', 'd', 'e']
['Ruby', 'Python', 'Perl']

Các phép tính trên list

Đoạn code dưới đây ví dụ về các phép tính trên list.

n1 = [1, 2, 3, 4, 5]
n2 = [3, 4, 5, 6, 7]

print (n1 == n2)
print (n1 + n2)

print (n1 * 3)

print (2 in n1)
print (2 in n2)

Chúng ta khởi tạo 2 list gồm các số nguyên và thực hiện một số phép tính.

print (n1 == n2)

Dòng code trên thực hiện phép so sánh thông qua toán tử ==. Kết quả ra False vì các phần tử trong 2 list là khác nhau.

print (n1 + n2)

Toán tử + sẽ gộp hai list lại với nhau và tạo thành một list với chứa các phần tử của 2 list con.

print (n1 * 3)

Toán tử * sẽ nhân số lượng phần tử trong list lên n lần, trong trường hợp trên là 3 lần.

print (2 in n1)

Toán tử in kiểm tra xem một giá trị nào đó có tồn tại trong list hay không. Giá trị trả về là True hoặc False.

False
[1, 2, 3, 4, 5, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
True
False

Một số hàm dùng với list


n = [1, 2, 3, 4, 5, 6, 7, 8]

print ("There are %d items" % len(n))
print ("Maximum is %d" % max(n))
print ("Minimum is %d" % min(n))
print ("The sum of values is %d" % sum(n))

Đoạn code trên ví dụ về tác dụng của bốn hàm len(), max(), min(), và sum().

print ("There are %d items" % len(n))

Hàm len() lấy độ dài của một list.

print ("Maximum is %d" % max(n))
print ("Minimum is %d" % min(n))

Hàm max() và min() tìm giá trị lớn nhất và nhỏ nhất có trong list, tất nhiên là trong trường hợp các phần tử trong list phải có cùng kiểu dữ liệu, nếu không sẽ báo lỗi.

print ("The sum of values is %d" % sum(n))

Hàm sum() trả về tổng các giá trị của các phần tử trong list, chỉ có thể dùng khi list chứa các phần tử kiểu số.

There are 8 items
Maximum is 8
Minimum is 1
The sum of values is 36

Thêm phần tử mới vào list


langs = list()

langs.append("Python")
langs.append("Perl")
print (langs)

langs.insert(0, "PHP")
langs.insert(2, "Lua")
print (langs)

langs.extend(("JavaScript", "ActionScript"))
print (langs)

Có 3 phương thức để thêm một phần tử vào list, đó là các phương thức append(), insert() và extend().

langs.append("Python")
langs.append("Perl")

Phương thức append() thêm một phần tử vào cuối list.

langs.insert(0, "PHP")
langs.insert(2, "Lua")

Phương thức insert() có thể thêm phần tử vào vị trí bất kì trong list.

langs.extend(("JavaScript", "ActionScript"))

Trong khi phương thức append() chỉ thêm một phần tử vào cuối list thì phương thức extend() có thể thêm một dãy các phần tử vào cuối list.

['Python', 'Perl']
['PHP', 'Python', 'Lua', 'Perl']
['PHP', 'Python', 'Lua', 'Perl', 'JavaScript', 'ActionScript']

Lỗi IndexError, TypeError

Lỗi exception IndexError là lỗi khi chúng ta thực hiện các thao tác có sử dụng chỉ số mà chỉ số vượt ngoài phạm vi list. Loại lỗi exception sẽ được đề cập ở các bài sau.

n = [1, 2, 3, 4, 5]

try:
    n[0] = 10
    n[6] = 60    
except IndexError as e:
    (print e)

Trong ví dụ trên, chúng ta có một list có 5 phần tử, các phần tử được đánh số từ 0..4

n[6] = 60

Nếu chúng ta truy xuất phần tử vượt quá 4 thì lỗi IndexError sẽ xảy ra, trong ví dụ trên chúng ta truy xuất phần tử thứ 6.

list assignment index out of range

Một lỗi exception khác là TypeError, lỗi này xảy ra khi chỉ số chúng ta đưa vào không phải là kiểu số.


n = [1, 2, 3, 4, 5]

try:
    print (n[1])
    print (n['2']  ) 
except TypeError as e:
    print ("Error in file %s" % __file__)
    print ("Message: %s" % e)

Ví dụ trên sẽ xảy ra lỗi TypeError.

print (n['2'])

Chỉ số bắt buộc phải là kiểu số, tất cả các kiểu dữ liệu còn lại đều không hợp lệ.

2
Error in file ./typeerror.py
Message: list indices must be integers, not str

Xóa phần tử trong list


langs = ["Python", "Ruby", "Perl", "Lua", "JavaScript"]
print (langs)

langs.pop(3)
langs.pop()
print (langs)

langs.remove("Ruby")
print (langs)

Chúng ta có hai phương thức để xóa phần tử trong một list là phương thức pop() và phương thức remove(). Phương thức pop() xóa phần tử thông qua chỉ số, phương thức remove() xóa phần tử thông qua giá trị.

langs.pop(3)
langs.pop()

Ở đoạn code trên chúng ta xóa phần tử có chỉ số là 3, nếu chúng ta không đưa chỉ số vô thì  Python sẽ tự động xóa phần tử cuối cùng.

langs.remove("Ruby")

Dòng trên xóa phần tử theo giá trị, phần tử đầu tiên trong list có giá trị “Ruby” sẽ bị xóa.

['Python', 'Ruby', 'Perl', 'Lua', 'JavaScript']
['Python', 'Ruby', 'Perl']
['Python', 'Perl']

Ngoài ra chúng ta có thể xóa phần tử của list bằng từ khóa del.


langs = ["Python", "Ruby", "Perl", "Lua", "JavaScript"]
print (langs)

del langs[1]
print (langs)

#del langs[15]

del langs[:]
print (langs)

Trong ví dụ trên chúng ta có một list các string, chúng ta sẽ xóa các phần tử bằng từ khóa del.

del langs[1]

Dòng trên xóa phần tử thứ 1.

#del langs[15]

Nếu chúng ta xóa các phần tử có chỉ số vượt ngoài phạm vi của list thì lỗi IndexError sẽ xảy ra.

del langs[:]

Dòng code trên xóa toàn bộ list.

['Python', 'Ruby', 'Perl', 'Lua', 'JavaScript']
['Python', 'Perl', 'Lua', 'JavaScript']
[]

Thay đổi giá trị phần tử trong list


langs = ["Python", "Ruby", "Perl"]

langs.pop(2)
langs.insert(2, "PHP")
print (langs)

langs[2] = "Perl"
print (langs)

Đoạn code trên sửa đổi giá trị của phần tử cuối cùng trong list.

langs.pop(2)
langs.insert(2, "PHP")

Trong hai dòng code trên, chúng ta xóa phần tử cuối cùng sau đó thêm một phần tử mới vào, cách này khá rườm rà và mất thời gian.

langs[2] = "Perl"

Thay vào đó bạn chỉ đơn giản là gán cho phần tử đó một giá trị mới là được.

['Python', 'Ruby', 'PHP']
['Python', 'Ruby', 'Perl']

Sao chép một list


import copy

w = ["Python", "Ruby", "Perl"]

c1 = w[:]
c2 = list(w)
c3 = copy.copy(w)
c4 = copy.deepcopy(w)
c5 = [e for e in w]

c6 = []
for e in w:
    c6.append(e)
    
c7 = []
c7.extend(w)

print (c1, c2, c3, c4, c5, c6, c7)

Đoạn code trên chúng ta có một list chứa 3 string. Chúng ta sao chép list này sang 7 list khác.

import copy

Trong Python có module copy, module này có 2 phương thức dùng cho việc sao chép.

c1 = w[:]

Cách một bạn dùng cú pháp như trên sẽ copy được một list.

c2 = list(w)

Cách thứ 2 là dùng hàm list() để khởi tạo ngay một list.

c3 = copy.copy(w)
c4 = copy.deepcopy(w)

Cả hai phương thức copy() deepcopy() đều có tác dụng là tạo ra bản sao của một list. Đến đây nếu bạn không muốn nghe giải thích về sự khác nhau của 2 phương thức này thì có thể bỏ qua đoạn dưới vì cũng không cần thiết lắm :D.

Nếu đã từng học hướng đối tượng thì bạn đã biết là một đối tượng có một phần bộ nhớ dành riêng cho chúng trong máy tính. Khi chúng ta tạo một list trong Python, chẳng hạn như a = [1, 2, 3], một ô nhớ sẽ được cấp cho biến a để lưu trữ thông tin về 3 phần tử của nó, và 3 ô nhớ riêng được cấp cho 3 phần tử của list a. Khi chúng ta dùng phương thức copy(), vd b = copy.copy(a), thì biến b được cấp một vùng nhớ riêng, còn 3 phần tử của biến b cũng được cấp vùng nhớ nhưng chúng không trực tiếp lưu trữ giá trị như biến mà bản thân chúng là một con trỏ tham chiếu đến 3 phần tử của biến a. Còn nếu dùng phương thức deepcopy() thì biến cũng được cấp một vùng nhớ riêng, và 3 phần tử của biến b cũng được cấp vùng nhớ riêng và lưu trữ giá trị giống như biến a, có nghĩa là lúc này chúng là các thực thể độc lập, không liên quan đến nhau.

c5 = [e for e in w]

Đoạn code trên tạo ra một bản copy khác bằng cách dùng vòng lặp.

c6 = []
for e in w:
    c6.append(e)

Dòng trên cũng không có gì khó hiểu.

c7 = []
c7.extend(w)

Phương thức extend cũng có thể được dùng để tạo bản sao.

['Python', 'Ruby', 'Perl'] ['Python', 'Ruby', 'Perl'] ['Python', 'Ruby', 'Perl'] 
['Python', 'Ruby', 'Perl'] ['Python', 'Ruby', 'Perl'] ['Python', 'Ruby', 'Perl'] 
['Python', 'Ruby', 'Perl']

Chỉ số trong list

Như chúng ta đã biết, chúng ta có thể truy xuất phần tử thông qua chỉ số. Chỉ số trong Python được đánh số từ 0. Ngoài ra chúng ta có thể dùng chỉ số âm để lấy lùi.


n = [1, 2, 3, 4, 5, 6, 7, 8]

print (n[0])
print (n[-1])
print (n[-2])

print (n[3])
print (n[5])

Chỉ số được đặt bên trong cặp dấu [].

1
8
7
4
6

Phương thức index(e, start, end) tìm xem có phần tử nào có giá trị giống như tham số hay không trong phạm vi từ start đến end. Chúng ta có thể không cần đưa hai tham số sau vào và Python sẽ tự ngầm tìm từ đầu đến cuối list.


n = [1, 2, 3, 4, 1, 2, 3, 1, 2]

print (n.index(1))
print (n.index(2))

print (n.index(1, 1))
print (n.index(2, 2))

print (n.index(1, 2, 5))
print (n.index(3, 4, 8))

Đoạn code trên ví dụ về phương thức index().

print (n.index(1))
print (n.index(2))

Hai dòng code trên tìm vị trí của phần tử đầu tiên có giá trị 1 và 2.

print (n.index(1, 1))
print (n.index(2, 2))

Hai dòng code trên cũng tìm phần tử có giá trị 1 và 2 bắt đầu từ vị trí số 1.

print (n.index(1, 2, 5))

Đoạn code trên tìm phần tử có giá trị 1 trong phạm vi từ 2 đến 5.

0
1
4
5
4
6

Duyệt chuỗi

Tiếp theo chúng ta sẽ tìm hiểu cách duyệt một chuỗi.


n = [1, 2, 3, 4, 5]

for e in n:
    print (e,)
    
print ()  

Đoạn code trên duyệt chuỗi bằng vòng lặp for khá đơn giản.

1 2 3 4 5

Đoạn code dưới đây hơi rườm rà hơn một tí.


n = [1, 2, 3, 4, 5]

i = 0
s = len(n)

while i < s:
    print (n[i],)
    i = i + 1

print()   

Chúng ta duyệt qua chuỗi bằng vòng lặp while.

i = 0
l = len(n)

Đầu tiên chúng ta định nghĩa biến đếm và biến lưu trữ chiều dài của list.

while i < s:
    print (n[i],)
    i = i + 1

Cứ mỗi lần lặp, chúng ta tăng biến đếm lên.

Khi dùng vòng lặp for với hàm enumerate(), chúng ta có thể lấy được cả chỉ số và giá trị của các phần tử trong list.


n = [1, 2, 3, 4, 5]

for e, i in enumerate(n):
    print ("n[%d] = %d" % (e, i))
n[0] = 1
n[1] = 2
n[2] = 3
n[3] = 4
n[4] = 5

Đếm số lượng phần tử trong list

Không những đếm số lượng phần tử của list mà còn đếm số lần xuất hiện của các phần tử nhất định trong list.


n = [1, 1, 2, 3, 4, 4, 4, 5]

print (n.count(4))
print (n.count(1))
print (n.count(2))
print (n.count(6))

Chúng ta dùng phương thức count(), trong ví dụ trên, chúng ta đếm số lần xuất hiện của một vài chữ số trong list.

n = [1, 1, 2, 3, 4, 4, 4, 5]

Chúng ta tạo ra một list. Trong đó số 1 và số 4 được xuất hiện nhiều lần.

print (n.count(4))
print (n.count(1))
print (n.count(2))
print (n.count(6))

Ở đây chúng ta đếm số lần xuất hiện của số 4, 1, 2, và 6.

3
2
1
0

Lồng các list lại với nhau

Một list không chỉ chứa các phần tử đơn lẻ mà có thể chứa nguyên cả một list khác.

nums = [[1, 2], [3, 4], [5, 6]]

print (nums[0])
print (nums[1])
print (nums[2])

print (nums[0][0])
print (nums[0][1])

print (nums[1][0])
print (nums[2][1])

print (len(nums))

Trong ví dụ trên, chúng ta tạo ra một list chứa 3 list khác.

print (nums[0][0])
print (nums[0][1])

Để truy xuất phần tử của list con thì chúng ta dùng hai cặp dấu ngoặc vuông [].

[1, 2]
[3, 4]
[5, 6]
1
2
3
6
3

Đoạn code dưới đây lồng 4 list lại với nhau.


nums = [[1, 2, [3, 4, [5, 6]]]]

print (nums[0])
print (nums[0][2])
print (nums[0][2][2])

print (nums[0][0])
print (nums[0][2][1])
print (nums[0][2][2][0])
print (nums[0][0])
print (nums[0][2][1])
print (nums[0][2][2][0])

Để truy xuất các phần tử con thì chúng ta cứ dùng thêm các cặp dấu ngoặc vuông []. 

[1, 2, [3, 4, [5, 6]]]
[3, 4, [5, 6]]
[5, 6]
1
4
5

Sắp xếp list


n = [3, 4, 7, 1, 2, 8, 9, 5, 6]
print (n)

n.sort()
print (n)

n.sort(reverse=True)
print (n)

Trong ví dụ trên, chúng ta có một list chứa các con số không theo một thứ tự nào cả. Chúng ta sẽ sắp xếp chúng bằng phương thức sort(). 

n.sort()

Mặc định phương thức sort() sẽ sắp xếp từ bé đến lớn.

n.sort(reverse=True)

Nếu muốn sắp xếp theo chiều ngược lại, bạn cho tham số reverse là True.

[3, 4, 7, 1, 2, 8, 9, 5, 6]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1]

Phương thức sort() thay đổi chính list gốc, nếu bạn không muốn thay đổi list gốc mà chỉ muốn có một bản copy list mới đã được sắp xếp thì dùng phương thức sorted().


n = [3, 4, 1, 7, 2, 5, 8, 6]

print (n)
print (sorted(n))
print (n)
[3, 4, 1, 7, 2, 5, 8, 6]
[1, 2, 3, 4, 5, 6, 7, 8]
[3, 4, 1, 7, 2, 5, 8, 6]

Đảo ngược list

a1 = ["bear", "lion", "tiger", "eagle"]

a1.reverse()
print (a1)

Để đảo ngược một list thì chúng ta dùng phương thức reverse().

['eagle', 'tiger', 'lion', 'bear']

Khởi tạo list bằng comprehension

Comprehension là một kiểu cú pháp dùng khi khởi tạo list từ một list khác. Bạn đã thấy cú pháp này ở các phần trên và trong các bài trước.

L = [<biểu thức> for <biến> in <danh sách> [câu lệnh if]]

Đoạn code mã giả trên là cú pháp comprehension. Khi chúng ta khởi tạo list theo cú pháp này. Một vòng for sẽ lặp qua danh sách cho trước, cứ mỗi lần lặp, nó sẽ kiểm tra xem nếu câu lệnh if có thỏa điều kiện không, nếu thỏa thì thực hiện biểu thức và gán giá trị trả về của biểu thức cho list L.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9] 
b = [e + 2 for e in a if e % 2] 
print (b)

Trong ví dụ trên, chúng ta tạo list gồm các con số. Chúng ta tạo một list gồm các phần tử là các số nguyên không thể chia hết cho 2 trong list và cộng thêm 2 cho số đó.

b = [e + 2 for e in a if e % 2]

Trong vòng lặp for, mỗi lần lặp sẽ kiểm tra xem nếu e có chia hết cho 2 hay không, nếu không thì thực hiện biểu thức, biểu thức ở đây là cộng e thêm 2, sau đó thêm vào list b.

Cú pháp comprehension có thể viết một cách tường minh lại như sau:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]

b = list()
for e in a:
    if (e % 2):
       b.append(e + 2)
 
print (b)

Đoạn code trên tương đường với cú pháp comprehension.

[3, 5, 7, 9, 11]

Hàm map() và hàm filter()

Hai hàm map() và filter() là hai hàm có tác dụng thực thi các câu lệnh trên các phần tử của list và trả về một list mới. Hai hàm này có tác dụng tương tự như cú pháp comprehension. Hiện tại thì người ta có xu hướng dùng cú pháp comprehension nhiều hơn do tính hữu dụng của nó.

def to_upper(s):
    return s.upper()

words = ["stone", "cloud", "dream", "sky"]

words2 = map(to_upper, words)
print (words2)

Hàm map() có tác dụng thực thi một hàm khác lên từng phần tử của một list.

def to_upper(s):
    return s.upper()

Trong ví dụ trên thì đây là hàm mà chúng ta sẽ dùng để thực thi cho các phần tử của list. Ở đây chúng ta viết hoa một string cho trước.

words2 = map(to_upper, words)
print (words2)

Tham số đầu tiên của hàm map() là tên của hàm sẽ được thực thi, tham số thứ hai là list nguồn.

['STONE', 'CLOUD', 'DREAM', 'SKY']

Hàm filter() cũng thực thi một hàm nhưng không làm gì với list gốc cả mà chỉ đơn giản là lấy các phần tử của list gốc nếu chúng thỏa điều kiện nào đó.

def positive(x):
    return x > 0

n = [-2, 0, 1, 2, -3, 4, 4, -1]

print (filter(positive, n))

Trong ví dụ trên, chúng ta tạo một list có các số nguyên. Hàm filter() sẽ lọc ra các phần tử > 0 bằng hàm positive().

def positive(x):
    return x > 0

Đoạn code trên là hàm do chúng ta định nghĩa, hàm này sẽ được sử dụng bởi hàm filter(). Giá trị trả về của hàm này là một kiểu bool.

[1, 2, 4, 4]






Bình luận

2 bình luận trên "Python – Kiểu List"

Thông báo cho tôi qua email khi
avatar
Sắp xếp:   Mới nhất | Cũ nhất | Nhiều lượt vote nhất
hoàng
Khách

Cám ơn tác giả. Bài viết rất hữu ích với e.