Mục lục

Giới thiệu ngôn ngữ lập trình Python . . . . . . . . . . . . . . . . . . 17

1

1.1

Giới thiệu chung

17

1.1.1

Lịch sử của Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.1.2

Đặc điểm của ngôn ngữ Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

1.1.3

Bộ từ vựng của Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

1.1.4

Cấu trúc và thực thi chương trình Python . . . . . . . . . . . . . . . . . . . . . . . 21

1.1.5 Môi trường phát triển tích hợp IDE để lập trình Python . . . . . . . . . . . . . . 23

1.2

Các kiểu dữ liệu trong Python

29

1.2.1

Kiểu số nguyên (int) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

1.2.2

Kiểu số thực (float) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

1.2.3

Kiểu số phức (complex)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

1.2.4

Kiểu logic (bool) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

1.2.5

Kiểu chuỗi ký tự (string) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

1.3

Biến, phép gán, câu lệnh và biểu thức

38

1.3.1

Biến . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

1.3.2

Phép gán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

1.3.3

Câu lệnh và tham số dòng lệnh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

1.3.4

Chú thích trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

1.3.5

Phép toán số học . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Phép toán quan hệ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

1.3.6

Phép toán logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

1.3.7

Các phép toán trên kiểu chuỗi

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

1.3.8

Biểu thức số học, quan hệ và logic . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

1.3.9

1.3.10 Độ ưu tiên của các toán tử . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

Các lệnh nhập xuất

51

1.4

Xuất dữ liệu ra màn hình . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

1.4.1

Nhập dữ liệu từ bàn phím . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

1.4.2

Câu hỏi và bài tập

56

1.5

Câu hỏi lý thuyết

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

1.5.1

Câu hỏi trắc nghiệm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

1.5.2

Bài tập thực hành . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

1.5.3

Các cấu trúc điều khiển trong Python . . . . . . . . . . . . . . . . 63

2

Câu lệnh điều kiện và rẽ nhánh

64

2.1

Câu lệnh điều kiện if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

2.1.1

Biểu thức if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

2.1.2

Biểu thức If-elif-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

2.1.3

Câu lệnh pass

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

2.1.4

Sử dụng if/else như phép gán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

2.1.5

So sánh số thực trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

2.1.6

Cấu trúc if lồng nhau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

2.1.7

Các cấu trúc lặp

70

2.2

Cấu trúc lặp while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

2.2.1

Cấu trúc lặp for

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

2.2.2

Câu lệnh break và continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

2.2.3

Cấu trúc while/else và for/else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

2.2.4

Các kỹ thuật vòng lặp trong Python

75

2.3

Vòng lặp Python với điều kiện ở đầu . . . . . . . . . . . . . . . . . . . . . . . . . . 75

2.3.1

Vòng lặp Python với điều kiện ở giữa . . . . . . . . . . . . . . . . . . . . . . . . . . 76

2.3.2

Vòng lặp Python với điều kiện ở cuối

. . . . . . . . . . . . . . . . . . . . . . . . . . 76

2.3.3

Vòng lặp while lồng nhau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

2.3.4

Vòng lặp for lồng nhau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

2.3.5

Một số lưu ý khi sử dụng các cấu trúc điều khiển

78

2.4

Câu hỏi và bài tập

79

2.5

Câu hỏi

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

2.5.1

Câu hỏi trắc nghiệm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

2.5.2

Bài tập thực hành . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

2.5.3

Lập trình có cấu trúc với Python . . . . . . . . . . . . . . . . . . . . . . 93

3

3.1

Hàm trong Python

93

3.1.1

Khái niệm và cấu trúc hàm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

3.1.2

Nguyên tắc hoạt động và lời gọi hàm . . . . . . . . . . . . . . . . . . . . . . . . . 98

3.1.3

Phạm vi của biến và truyền tham số trong Python . . . . . . . . . . . . . . . . 100

3.1.4

Tham số hàm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

3.1.5

Viết tài liệu cho hàm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

3.1.6

Hàm đệ qui

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

3.2

Xử lý chuỗi (string)

112

3.2.1

Khái niệm chuỗi

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

3.2.2

Cấu trúc của chuỗi và truy cập . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

3.2.3

Các hàm cơ bản xử lý chuỗi trong Python . . . . . . . . . . . . . . . . . . . . . 115

3.3

Xử lý danh sách (list)

119

3.3.1

Khái niệm List

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

3.3.2

Truy cập các phần tử của List

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

3.3.3

Các thao tác cơ bản trên list trong Python . . . . . . . . . . . . . . . . . . . . . 121

3.4

Xử lý bộ (Tulpe)

125

3.4.1

Khái niệm và cấu trúc của Tulpe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

3.4.2

Truy cập các giá trị trong tuple trong Python . . . . . . . . . . . . . . . . . . . . 125

3.4.3

Các hàm cơ bản xử lý Tulpe trong Python . . . . . . . . . . . . . . . . . . . . . 126

3.5

Xử lý Dictionary

128

3.5.1

Khái niệm và cấu trúc của Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . 128

3.5.2

Truy cập các item của Dictionary trong Python . . . . . . . . . . . . . . . . . . 129

3.5.3

Các hàm cơ bản xử lý Dictionary trong Python . . . . . . . . . . . . . . . . . . 130

3.6

Xử lý tập hợp (Set)

135

3.6.1

Khái niệm và cấu trúc của tập hợp . . . . . . . . . . . . . . . . . . . . . . . . . . 135

3.6.2

Truy cập các giá trị của tập hợp trong Python . . . . . . . . . . . . . . . . . . 136

3.6.3

Các hàm xử lý tập hợp trong Python . . . . . . . . . . . . . . . . . . . . . . . . . 136

3.7

Xử lý mảng (array)

139

3.7.1

Thư viện array trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

3.7.2

Truy cập vào các phần tử của mảng . . . . . . . . . . . . . . . . . . . . . . . . . 140

3.7.3

Thay đổi, thêm phần tử trong mảng . . . . . . . . . . . . . . . . . . . . . . . . . . 141

3.7.4

Xóa phần tử của mảng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

3.7.5

Độ phức tạp khi loại bỏ array trong Python . . . . . . . . . . . . . . . . . . . . . 143

3.8

Xử lý tập tin (file)

144

3.8.1

Vì sao phải lưu tập tin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

3.8.2

Các thao tác trên tập tin với Python . . . . . . . . . . . . . . . . . . . . . . . . . . 144

3.8.3

Các thao tác xử lý file text, XML, JSON, CVS và Excel . . . . . . . . . . . . . . 148

3.8.4

Thao tác trên thư mục trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . 157

3.9 3.9.1

Câu hỏi và bài tập Câu hỏi

158 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

3.9.2 3.9.3

Câu hỏi trắc nghiệm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Bài tập thực hành . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

Lập trình hướng đối tượng với Python . . . . . . . . . . . . . . . 175

4

4.1

Lập trình hướng đối tượng

175

4.1.1

Các khái niệm lập trình hướng đối tượng trong Python . . . . . . . . . . . . 175

4.1.2 4.1.3 4.1.4

Lớp và đối tượng trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 Phương thức (Method) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Hàm tạo (contructor) trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

4.1.5 4.1.6 4.1.7 4.1.8 Ghi đè phương thức (Method Overriding) 4.1.9

Kế thừa (Inheritance) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 Đóng gói (Encapsulation) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 Đa hình (Polymorphism) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 . . . . . . . . . . . . . . . . . . . . . 200 Trừu tượng dữ liệu trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6

Thao tác trên module trong Python 201 Khái niệm module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Cách tạo module trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Lệnh import trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Đổi tên module với as . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Xem thuộc tính và phương thức của module . . . . . . . . . . . . . . . . . . . 206 Tải lại module với hàm reload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206

4.2.7

Phạm vi của biến của module trong Python . . . . . . . . . . . . . . . . . . . . 206

Thao tác trên các module có sẵn (built-in) trong Python

4.3 207 4.3.1 Module Date và Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 4.3.2 Module Calendar trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 4.3.3 Module Math trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 4.3.4 Module OS trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 4.3.5 Module Random trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 4.3.6 Module Statistics trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215 4.3.7 Module Sys trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216

4.4 4.4.1 4.4.2 4.4.3 4.4.4

216 Thao tác trên Package trong Python Khái niệm package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Tạo một package trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Tạo module trong package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Tạo package bên trong một package khác . . . . . . . . . . . . . . . . . . . . 218

4.5 4.5.1

Câu hỏi và bài tập Câu hỏi

220 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220

4.5.2 4.5.3

Câu hỏi trắc nghiệm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Bài tập thực hành . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

Phát triển ứng dụng với Python . . . . . . . . . . . . . . . . . . . . . . 233

5

5.1

Thiết kế giao diện với Tkinter

233

5.1.1 Giới thiệu Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

5.1.2

Thiết kế giao diện với Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

5.1.3

Project 1. Tạo cửa sổ và hộp thoại

. . . . . . . . . . . . . . . . . . . . . . . . . . . 241

5.1.4

Project 2. Tạo ứng dụng trắc nghiệm với Python Tinker . . . . . . . . . . . . . 244

5.1.5

Project 3. Sinh mã QR Code với Tinker sử dụng thư viện pyqrcode . . . . . 246

5.1.6

Project 4. Tạo máy tính cá nhân với Python Tinker

. . . . . . . . . . . . . . . . 247

5.1.7

Project 5. Tạo game rắn Snake Game . . . . . . . . . . . . . . . . . . . . . . . . . 249

5.2

Phát triển các ứng dụng cơ bản với Python

252

5.2.1

Projec 1. Vẽ hình với thư viện Turtle . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

5.2.2

Projec 2. Trực quan hóa dữ liệu với Matplotlib và Seaborn . . . . . . . . . . 257

5.2.3

Projec 3. Xử lý hình ảnh với thư viện Pillow . . . . . . . . . . . . . . . . . . . . . . 271

5.2.4

Projec 4. Xử lý yêu cầu http với thư viện Requests

. . . . . . . . . . . . . . . . 274

5.2.5

Projec 5. Tạo giao diện dòng lệnh với thư viện Fire . . . . . . . . . . . . . . . . 279

5.3

Phát triển các ứng dụng quản lý với Python

282

5.3.1

Kết nối và truy vấn cơ sở dữ liệu trong Python . . . . . . . . . . . . . . . . . . . 282

5.3.2

Projec 1. Quản lý thư viện . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

5.3.3

Projec 2. Quản lý sinh viên . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293

5.3.4

Projec 3. Quản lý bán hàng với Django . . . . . . . . . . . . . . . . . . . . . . . . 301

5.4

Phát triển các ứng dụng xử lý dữ liệu với Python

311

5.4.1

Tổng quan về xử lý dữ liệu với Python . . . . . . . . . . . . . . . . . . . . . . . . . 311

5.4.2

Project 1. Xử lý mảng số học hiệu năng cao trên thư viện NumPy . . . . . 311

5.4.3

Project 2. Phân tích và xử lý dữ liệu dạng bảng với thư viện Pandas . . . 319

5.4.4

Project 3. Xử lý mô hình hóa, tối ưu thống kê với SciPy . . . . . . . . . . . . . 327

5.5

Phát triển ứng dụng trí tuệ nhân tạo với Python

333

5.5.1

Project 1. Phát triển ứng dụng với TensorFlow . . . . . . . . . . . . . . . . . . . 333

5.5.2

Project 2. Phát triển ứng dụng với Keras

. . . . . . . . . . . . . . . . . . . . . . . 337

5.5.3

Project 3. Tạo Neural Network huấn luyện dữ liệu mẫu với TensoFlow, Kera 343

5.5.4

Project 4. Phát triển ứng dụng với thư viện PyTorch . . . . . . . . . . . . . . . 345

5.5.5

Project 5. Phát triển ứng dụng với thư viện Scikit-learn . . . . . . . . . . . . . 352

5.5.6

Project 6. Phát triển ứng dụng xử lý ngôn ngữ tự nhiên (NTLK) . . . . . . . . 355

5.5.7

Project 7. Phát triển ứng dụng với thư viện OpenCV . . . . . . . . . . . . . . 359

Phụ lục A. Môi trường thực hành . . . . . . . . . . . . . . . . . . . . 369

Phụ lục B. Đáp án câu hỏi trắc nghiệm . . . . . . . . . . . . . . 383

Phụ lục C. Hướng dẫn giải bài tập . . . . . . . . . . . . . . . . . . . 387

6 7 8

Tài liệu tham khảo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389

Danh sách hình vẽ

1.1 Guido Van Rossum và lịch sử ngôn ngữ lập trình Python . . . . . . . . . . . . . . . 18 . . . . . . . . . 18 1.2 Các ngôn ngữ lập trình phổ biến trên thế giới (tính đến 4/2025) 1.3 Quá trình thực thi chương trình Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.4 Cấu trúc một chương trình Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.5 Cài đặt Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1.6 Thư mục cài đặt Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 1.7 Chương trình Python đã được cài đặt 1.8 Kiểm tra version của Python đã cài đặt . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 1.9 Thực thi chế độ dòng lệnh với IDLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.10 Thực thi chế độ dòng lệnh qua Command Prompt . . . . . . . . . . . . . . . . . . 26 1.11 Thực thi chế độ chương trình qua IDLE . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1.12 Các bước cài đặt Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.13 Thư mục cài đặt Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.14 Giao diện của Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 1.15 Cài đặt extension Python trên Visual Studio Code . . . . . . . . . . . . . . . . . . . 28 1.16 Thực thi file Python trên Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . 28 1.17 Tạo ra môi trường ảo của Python với Visual Studio Code . . . . . . . . . . . . . . 29 1.18 Cài đặt thư viện cho môi trường ảo của Python với Visual Studio Code . . . 29 1.19 Các kiểu dữ liệu cơ sở trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 2.1 Câu lệnh if 2.2 Câu lệnh if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 2.3 Câu lệnh if-elif-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 2.4 Sử dụng if/else như phép gán . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 2.5 Câu lệnh while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 2.6 Cấu trúc lặp for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

5.27 Đồ thị heatmap theo màu sắc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 5.28 Đồ thị heatmap với trục số liệu theo màu sắc. . . . . . . . . . . . . . . . . . . . . 269 5.29 Vẽ nhiều biểu đồ con. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 5.30 Vẽ biểu đồ tổng hợp. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 5.31 Thư viện http - Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 5.32 Thư viện tạo giao diện dòng lệnh - Fire . . . . . . . . . . . . . . . . . . . . . . . . . 279 5.33 Giao diện đăng nhập hệ thống quản lý thư viện . . . . . . . . . . . . . . . . . . 293 5.34 Giao diện thêm, xem, trả, sách trong hệ thống quản lý thư viện . . . . . . . 293 5.35 Hệ thống quản lý sinh viên . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 5.36 Giao diện phát triển ứng dụng django . . . . . . . . . . . . . . . . . . . . . . . . . 302 5.37 Giao diện hệ thống quản lý bán hàng . . . . . . . . . . . . . . . . . . . . . . . . . 308 5.38 Giao diện quản lý app product trong superuser . . . . . . . . . . . . . . . . . . . 309 5.39 Giao diện quản lý phân trang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 5.40 Thư viện mảng đa chiều, ma trận - Numpy . . . . . . . . . . . . . . . . . . . . . . 312 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 5.41 Mảng đa chiều n-dimentional 5.42 Phân phối đồng nhất và phân phối chuẩn . . . . . . . . . . . . . . . . . . . . . . 316 5.43 (a) Phân phối đều với các giá trị nằm trong khoảng từ 0 đến 1; (b) Phân phối

chuẩn với mean = 0, standard deviation = 1 . . . . . . . . . . . . . . . . . . . . . . . . . . 316 5.44 Index và Slicing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 5.45 Objects trong Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 5.46 Tổng hợp dữ liệu (Aggregation) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 5.47 Hợp nhất dữ liệu trong Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326 5.48 Kết quả phân cụm (a) kmean() và (b) kmean2() . . . . . . . . . . . . . . . . . . 331 5.49 hàm số trong miền thời gian (a) và hàm số trong miền tần số . . . . . . . . . 332 5.50 Thư viện Machine Learning - TensorFlow . . . . . . . . . . . . . . . . . . . . . . . . . 334 5.51 Thư viện Deep Learning - Keras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 5.52 Một mẫu dữ liệu đầu vào với kích thước 28x28, tương ứng với nhãn "pullover" -

áo len chui đầu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341 5.53 Kết quả phân lớp sử dụng thư viện Deep Learning - Keras . . . . . . . . . . . . 344 5.54 Cơ chế hoạt động của Scikit-learn . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 5.55 Sử dụng GPU để tăng tốc Scikit-learn APIs . . . . . . . . . . . . . . . . . . . . . . . 354 5.56 Thư viện xử lý ngôn ngữ tự nhiên - Natural Language Toolkit . . . . . . . . . . 355 5.57 Thư viện Xử lý hình ảnh OpenCV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360

6.1 Download Notepad++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369 6.2 Các bước cài đặt Notepad++ v8.5.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . 370 6.3 Tùy chọn các thành phần cài đặt Notepad++ v8.5.4 . . . . . . . . . . . . . . . . 370 6.4 Cài đặt cửa sổ console làm việc với Notepad++ v8.5.4 . . . . . . . . . . . . . . 371 6.5 Soạn thảo và thực thi chương trình Python qua cmd với Notepad++ v8.5.4 371 6.6 Soạn thảo và thực thi chương trình Python qua PowerShell với Notepad++ v8.5.4

372 6.7 Tìm kiếm cài đặt pydev trên Eclipse Marketplace . . . . . . . . . . . . . . . . . . . 372 . . . . . . . . . . . . . . . 373 6.8 Các bước cài đặt pydev trên Eclipse và khởi động lại 6.9 Cấu hình Interpreter với Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 6.10 Cấu hình Interpreter với Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374 6.11 Môi trường lập trình Spyder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377 6.12 Tải phần mềm từ website PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 6.13 Lựa chọn phiên bản tải phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . 379 6.14 Lựa chọn phiên bản tải phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . 379 6.15 Cài đặt phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 6.16 Cài đặt phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 6.17 Cài đặt phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 6.18 Cài đặt phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380 6.19 Cài đặt phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 6.20 Cài đặt phần mềm PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381

Danh sách bảng

1.1 Các phiên bản Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.2 Bộ từ vựng của Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.3 Từ khóa trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.4 Cách biểu diễn số nguyên trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . 30 1.5 Cách biểu diễn số thực trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 1.6 Cách biểu diễn số phức trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 1.7 Cách biểu diễn chuỗi ký tự trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . 38 1.8 Các phép toán số học với số nguyên trong Python . . . . . . . . . . . . . . . . . . 46 1.9 Các phép toán số học với số thực trong Python . . . . . . . . . . . . . . . . . . . . 46 1.10 Các phép toán quan hệ trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.11 Các phép toán logic trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 1.12 Các phép toán trên kiểu chuỗi trong Python . . . . . . . . . . . . . . . . . . . . . . 48 1.13 Độ ưu tiên của các toán tử . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 1.14 Các ký tự điều khiển không in được . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 1.15 Các ký tự điều khiển đặc tả định dạng trong Python . . . . . . . . . . . . . . . . 54

3.1 Chức năng các hàm dựng sẵn trong Python . . . . . . . . . . . . . . . . . . . . . . . 95 3.2 Một số hàm xử lý chuỗi thông dụng trong Python . . . . . . . . . . . . . . . . . . . 116 3.3 Danh sách các hàm xử lý list trong Python . . . . . . . . . . . . . . . . . . . . . . . . 124 3.4 Danh sách các phương thức lý list trong Python . . . . . . . . . . . . . . . . . . . 124 3.5 Một số phương thức khác xử lý tuple trong Python . . . . . . . . . . . . . . . . . . 128 3.6 Một số hàm xử lý Dictionary khác trong Python . . . . . . . . . . . . . . . . . . . . 135 3.7 Một số phương thức khác xử lý Dictionary trong Python . . . . . . . . . . . . . . 135 3.8 Một số hàm xử lý tập hợp trong Python . . . . . . . . . . . . . . . . . . . . . . . . . . 139 3.9 Những mã kiểu thường dùng trong thư viện array . . . . . . . . . . . . . . . . . . 140 3.10 Các mode (chế độ) mở một file trong Python . . . . . . . . . . . . . . . . . . . . 145

3.11 Các phương thức xử lý file text trong Python . . . . . . . . . . . . . . . . . . . . . 149 3.12 Các thư viện xử lý file excel với Python . . . . . . . . . . . . . . . . . . . . . . . . . 155 3.13 Một số hàm xử lý file Excel với Pandas trong Python . . . . . . . . . . . . . . . . 157

4.1 Các hàm lớp dựng sẵn của Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 4.2 Các thuộc tính lớp tích hợp của Python . . . . . . . . . . . . . . . . . . . . . . . . . 185 4.3 Thuộc tính của Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 4.4 Các hàm được định nghĩa sẵn trong module time . . . . . . . . . . . . . . . . . . 209 4.5 Các hàm được định nghĩa sẵn trong module calendar . . . . . . . . . . . . . . 209 4.6 Các hàm thông dụng trong module random . . . . . . . . . . . . . . . . . . . . . . 214 . . . . . . . . . . . . . . . . . . . . . . . . . 216 4.7 Các hàm thông dụng trong module sys

5.1 Một số tùy chọn với điều khiển label . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 5.2 Một số tùy chọn với điều khiển button . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 5.3 Các phương thức với điều khiển Button . . . . . . . . . . . . . . . . . . . . . . . . . 235 5.4 Dữ liệu vẽ dạng pandas dataframe đơn giản . . . . . . . . . . . . . . . . . . . . . 265 5.5 Dữ liệu vẽ biểu đồ heatmap matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 5.6 Một số hàm có sẵn hỗ trợ tạo mảng trong NumPy . . . . . . . . . . . . . . . . . . 315 5.7 Dữ liệu mẫu phân tích với Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 5.8 Các hàm tổng hợp dữ liệu (Aggregation) trong Pandas . . . . . . . . . . . . . . 325 5.9 So sánh giữa phương pháp sử dụng trong Pandas và trong SQL . . . . . . . . 326 5.10 Tổng hợp các gói con của Scipy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

1. Giới thiệu ngôn ngữ lập trình Python

Mục tiêu: Kết thúc chương này, sinh viên có thể:

• Biết được quá trình hình thành Python, nên dùng Python khi nào và tại sao. • Nắm được cấu trúc một chương trình Python. • Hiểu và sử dụng được biến (variables). • Phân biệt sự khác nhau giữa biến và hằng (constants). • Nắm vững và sử dụng các kiểu dữ liệu khác nhau trong chương trình Python.

1.1 Giới thiệu chung

Python là một ngôn ngữ lập trình bậc cao, thông dịch, đa mô hình (multi-paradigm) do Guido van Rossum phát triển và ra mắt vào năm 1991. Với cú pháp đơn giản, dễ đọc, cùng khả năng mở rộng mạnh mẽ, Python đã nhanh chóng trở thành một trong những ngôn ngữ phổ biến và được ưa chuộng nhất thế giới với cộng đồng lớn mạnh, hệ sinh thái thư viện đồ sộ. Python được sử dụng rộng rãi trong nhiều lĩnh vực, bao gồm:

• Trí tuệ nhân tạo (Artificial Intelligence - AI) và học máy (Machine Learning) với nhiều thư viện mạnh mẽ như TensorFlow, PyTorch, Scikit-learn giúp Python dẫn đầu trong nghiên cứu và ứng dụng AI. • Khoa học dữ liệu và phân tích dữ liệu với thư viện Pandas, NumPy, Matplotlib, Python là công cụ hàng đầu cho các nhà phân tích và nhà khoa học dữ liệu.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 18

• Phát triển web mạnh mẽ với các framework như Django, Flask, FastAPI giúp xây dựng hệ thống web nhanh chóng và bảo mật.

• Tự động hóa và DevOps (Development and Operations) với việc sử dụng Python phổ biến trong scripting, tự động hoá hệ thống, kiểm thử phần mềm và triển khai (Continuous Integration/Continuous Delivery-CI/CD), rút ngắn thời gian đưa phần mềm ra thị trường. • Internet of Things (IoT) và Robot, Python hỗ trợ lập trình nhúng, tương thích tốt với Raspberry Pi, Arduino,... • Python thường là ngôn ngữ đầu tiên được giảng dạy tại các trường đại học vì tính đơn giản và phổ quát.

1.1.1 Lịch sử của Python

Python là ngôn ngữ lập trình bậc cao, được phát triển bởi Guido van Rossum vào cuối những năm 1980 và ra mắt lần đầu vào tháng 2 năm 1991. Guido van Rossum khởi tạo xây dựng Python với mục tiêu tạo ra một ngôn ngữ dễ đọc, dễ viết và dễ bảo trì, hỗ trợ lập trình hướng đối tượng, lập trình hàm và thủ tục, có thể mở rộng, tích hợp tốt với hệ thống và C/C++. Python được kế thừa nhiều đặc điểm từ ngôn ngữ ABC (ngôn ngữ giảng dạy do CWI phát triển), Modula-3, C và một phần từ Unix shell, Perl. Tên gọi “Python” không bắt nguồn từ loài rắn, mà từ nhóm hài Monty Python’s Flying Circus – Guido muốn ngôn ngữ có sự “vui vẻ”.

Hình 1.1: Guido Van Rossum và lịch sử ngôn ngữ lập trình Python

Theo statista.com, Python là một trong những ngôn ngữ lập trình phổ biến nhất thế giới với các phiên bản1 đã phát hành gồm:

1Python Release Schedule - https://www.python.org/

Hình 1.2: Các ngôn ngữ lập trình phổ biến trên thế giới (tính đến 4/2025)

1.1 Giới thiệu chung 19

Bảng 1.1: Các phiên bản Python

Phiên bản

Ngày phát hành Ngày dừng hỗ trợ

Python 1.0 (Bản phát hành chuẩn đầu tiên) Python 1.6 (Phiên bản 1.x cuối cùng) Python 2.0 (Giới thiệu list comprehension) Python 2.7 (Phiên bản 2.x cuối cùng) Python 3.0 (Loại bỏ cấu trúc và môđun trùng lặp) Python 3.8 (PEP 569) Python 3.9 (PEP 596) Python 3.10 (PEP 619) Python 3.11 (PEP 664) Python 3.12 (PEP 693) Python 3.13 (PEP 719) (Bản mới, thời điểm biên soạn) Python 3.12 (PEP 745 - Dự kiến)

01/1994 16/09/2000 16/10/2000 03/07/2010 03/12/2008 20/07/2020 05/10/2020 04/10/2021 24/10/2022 02/10/2023 07/10/2024 07/10/2025

10/2024 10/2025 10/2026 10/2027 05/2025 05/2026 05/2027

1.1.2 Đặc điểm của ngôn ngữ Python

Ngôn ngữ Python có các đặc điểm sau:

• Đơn giản, dễ học: Python có cú pháp rất đơn giản, rõ ràng, dễ đọc và viết hơn nhiều so với những ngôn ngữ lập trình khác như: C++, Java, C#. Python giúp việc lập trình trở nên thú vị hơn, cho phép người lập trình tập trung vào những giải pháp chứ không phải cú pháp.

• Miễn phí, mã nguồn mở: Python có thể tự do sử dụng và phân phối, thậm chí là dùng với mục đích thương mại vì là ứng dụng mã nguồn mở nên không những có thể sử dụng các phần mềm, chương trình được viết trong Python mà còn có thể thay đổi mã nguồn của nó. Python có một cộng đồng rộng lớn, không ngừng cải thiện nó mỗi lần cập nhật. • Khả năng di chuyển: Các chương trình Python có thể di chuyển từ nền tảng này sang nền tảng khác để thực thi mà không có bất kỳ thay đổi nào như Windows, macOS, Linux. • Khả năng mở rộng và có thể nhúng: Giả sử một ứng dụng đòi hỏi sự phức tạp rất lớn, chúng ta có thể dễ dàng kết hợp các phần code bằng C/C++ và những ngôn ngữ khác (có thể gọi được từ C) vào code Python. Điều này sẽ cung cấp cho ứng dụng của chúng ta những tính năng tốt hơn cũng như khả năng scripting mà những ngôn ngữ lập trình khác khó có thể làm được.

• Ngôn ngữ thông dịch cấp cao: Không giống như C/C++, với Python, chúng ta không phải lo lắng những nhiệm vụ khó khăn như quản lý bộ nhớ, dọn dẹp những dữ liệu vô nghĩa,... Khi chạy code Python, nó sẽ tự động chuyển đổi code sang ngôn ngữ máy tính có thể hiểu. Chúng ta không cần lo lắng về bất kỳ hoạt động ở cấp thấp nào.

• Thư viện tiêu chuẩn lớn để giải quyết những tác vụ phổ biến: Python có một số lượng lớn thư viện tiêu chuẩn giúp cho công việc lập trình của chúng ta trở nên dễ thở hơn rất nhiều, đơn giản vì không phải tự viết tất cả code. Ví dụ: Khi cần kết nối cơ sở dữ liệu MySQL trên Web server? Chúng ta có thể nhập thư viện MySQLdb và sử dụng nó. Những thư viện này được kiểm tra kỹ lưỡng và được sử dụng bởi hàng trăm người nên

Chương 1. Giới thiệu ngôn ngữ lập trình Python 20

có thể chắc chắn rằng nó sẽ không làm hỏng code hay ứng dụng.

• Hướng đối tượng: Mọi thứ trong Python đều là hướng đối tượng (OOP) giúp giải quyết những vấn đề phức tạp một cách trực quan. Với OOP, chúng ta có thể phân chia những vấn đề phức tạp thành những tập nhỏ hơn bằng cách tạo ra các đối tượng. Hỗ trợ module và hỗ trợ gói (Package), xử lý lỗi bằng ngoại lệ (Exception), có thể nhúng vào ứng dụng như một giao tiếp kịch bản (Scripting Interface).

Ngôn ngữ Python có các ưu điểm sau: • Có ngữ pháp đơn giản, dễ đọc. Viết mã ngắn gọn hơn những chương trình tương đương được viết trong C, C++, C#, Java,...

• Có các bộ thư viện chuẩn và các module ngoài, đáp ứng gần như mọi nhu cầu lập trình. • Có khả năng chạy trên nhiều nền tảng (Windows, Linux, Unix, OS/2, Mac, Amiga, máy ảo .NET, máy ảo Java, Nokia Series 60,...)

• Có cộng đồng lập trình rất lớn, hệ thống thư viện chuẩn, mã nguồn chia sẻ nhiều. Nhược điểm của ngôn ngữ Python: • Chương trình chạy chậm. • Giao tiếp với các thư viện viết bằng các ngôn ngữ khác tương đối khó khăn. • Yếu trong hỗ trợ tính toán trên di động. • Cách viết khối lệnh dễ gây nhầm lẫn cho người mới bắt đầu lập trình. • Gỡ lỗi chương trình đòi hỏi kinh nghiệm. • Hỗ trợ các cơ sở dữ liệu kém.

1.1.3 Bộ từ vựng của Python

Mọi ngôn ngữ lập trình đều được xây dựng từ một bộ ký tự, các ký tự được nhóm lại để tạo nên các từ. Các từ lại được liên kết với nhau theo một qui tắc để tạo nên các câu lệnh. Một chương trình bao gồm nhiều câu lệnh và thể hiện một thuật toán để giải một bài toán nào đó. Ngôn ngữ Python được xây dựng trên bộ ký tự được cho trong Bảng 1.2. Ký tự gạch nối (_) và khoảng trắng space (’ ’) dùng để phân tách các từ. Khi viết chương trình, chúng ta không được sử dụng bất kỳ ký tự nào khác ngoài các ký tự trên.

Bảng 1.2: Bộ từ vựng của Python

Bộ ký tự

Danh sách các ký tự

Bộ chữ cái 26 ký tự Latinh A, B, C, . . . , Z, a, b, c, . . . , z. Bộ chữ số thập phân Các ký hiệu toán học Các ký tự đặc biệt

0, 1, 2, . . . , 9 + - * / = < > ( ) . , : ; [, ], % #, $, ’

Ví dụ 1.1.1. Khi lập chương trình giải phương trình bậc hai ax2 + bx + c = 0, ta cần tính định thức Delta ∆ = b2 − 4ac, trong ngôn ngữ Python không cho phép dùng ký tự ∆ nên ta phải dùng ký hiệu khác để thay thế.

1.1 Giới thiệu chung 21

Từ khóa (Keyword) là các từ (word) dành riêng trong ngôn ngữ Python, được sử dụng để khai báo các kiểu dữ liệu, để viết các toán tử và các câu lệnh. Chúng ta không thể sử dụng từ khóa để đặt tên cho biến, hàm, tên chương trình. Từ khóa được sử dụng để xác định cú pháp và cấu trúc của ngôn ngữ Python, ó sự phân biệt chữ hoa và chữ thường. Với phiên bản Python 3.10.2 có tất cả 35 từ khóa đều ở dạng chữ thường ngoại trừ True, False và None (Bảng 1.3). Để xem danh sách tất cả các từ khóa trong Python chúng ta gõ lệnh help(“keywords”).

while assert async

False None True and

await break class continue

else except finally for

import in is lambda

pass raise return try

or elif not del

yield if with global

as def from nonlocal

Bảng 1.3: Từ khóa trong Python

Tên/Định danh (Identifier) là một dãy ký tự được đặt cho các thực thể như lớp, hàm, biến,. . . Định danh giúp phân biệt thực thể này với thực thể khác với qui tắc đặt tên như sau: 1. Tên định danh có thể bao gồm các chữ thường (a đến z), chữ hoa (A đến Z), chữ số (0 đến 9), dấu gạch dưới _ (underscore).

2. Tên định danh không được bắt đầu bằng một chữ số. 3. Không được đặt tên định danh giống với từ khóa (keyword). 4. Không được sử dụng các ký hiệu đặc biệt như !, @, #, $,%,. . . trong tên định danh. 5. Tên định danh có thể có độ dài bất kỳ. 6. Tên định danh không bao gồm ký tự khoảng trắng. 7. Python phân biệt chữ hoa và chữ thường.

Ví dụ 1.1.2. Đặt tên định danh trong Python

• Tên định danh hợp lệ: myClass, var_1 và print_this_to_screen. • Tên định danh 1variable không hợp lệ nhưng variable1 thì hợp lệ. • Tên định danh VaRiable và variable là khác nhau. • Tên định danh count a là không hợp lệ, nhưng counta thì hợp lệ.

Nên đặt tên định danh có ý nghĩa và dễ nhớ. Thay vì đặt tên định danh của biến là c = 10 thì có thể đặt là count = 10. Lúc này, tên định danh của biến sẽ rõ nghĩa hơn và cho biết biến count là một biến dùng để lưu một giá trị đếm. Các từ trong một tên định danh có thể được nối với nhau bởi dấu gạch dưới. Ví dụ như this_is_a_long_variable.

1.1.4 Cấu trúc và thực thi chương trình Python

Python là một ngôn ngữ thông dịch (Interpreted Language). Tuy nhiên, quá trình thực thi một chương trình Python bao gồm cả quá trình biên dịch (Compiled) và thông dịch (Interpreted). Quá trình thực thi một chương trình Python được thể hiện trong Hình 1.3. Đầu tiên, mã nguồn Python được viết trong file có đuôi mở rộng là .py. Sau đó, trình biên dịch

Chương 1. Giới thiệu ngôn ngữ lập trình Python 22

CPython sẽ đọc từng dòng code Python và kiểm tra cú pháp của mỗi dòng. Nếu gặp lỗi thì CPython sẽ ngừng biên dịch và thông báo lỗi. Nếu không có lỗi thì CPython sẽ biên dịch mã nguồn Python thành bytecode và được lưu trữ trong file có phần mở rộng là .pyc hoặc .pyo.

Hình 1.3: Quá trình thực thi chương trình Python

CPU không thể thực thi được bytecode mà bytecode cần được gửi đến PVM (Python Virtual Machine) để thông dịch thành mã máy (Machine Code) để thực thi. Nếu có lỗi xảy ra thì quá trình thực thi chương trình sẽ bị ngừng và xuất thông báo lỗi. Các lỗi này được gọi là lỗi runtime. Tại sao phải biên dịch mã nguồn thành bytecode rồi thông dịch để thực thi? Ưu điểm của việc này là chỉ cần biên dịch source code một lần thành bytecode. Sau đó, có thể mang bytecode này thực thi trên các nền tảng khác nhau (Windows, Linux, MacOS,. . . ). Tuy nhiên, nhược điểm là quá trình chạy chương trình Python thường chậm hơn so với các ngôn ngữ khác như C/C++.

Cấu trúc một chương trình Python gồm hai phần chính là khai báo và thân chương trình. Phần khai báo có thể có hoặc không (tùy theo từng chương trình cụ thể), phần thân chương trình bắt buộc phải có.

Hình 1.4: Cấu trúc một chương trình Python

1.1 Giới thiệu chung 23

Không phải khi nào chúng ta cũng có phần khai báo, chỉ khai báo khi chương trình có sử dụng đến thư viện chương trình con (module) nào đó. Ví dụ, import math để khai báo thư viện math. Việc khai báo hằng, biến không nhất thiết phải khai báo ở đầu chương trình mà có thể khai báo bất cứ vị trí nào trong chương trình trước khi dùng biến. Phần thân chương trình là các câu lệnh thực thi. Các câu lệnh trong Python được viết theo định dạng mà một câu lệnh chỉ được viết trong một dòng duy nhất. Trình thông dịch coi "Ký tự dòng mới" là kết thúc của một lệnh. Chúng ta có thể viết nhiều câu lệnh trên mỗi dòng, nhưng nó không tốt vì nó làm giảm khả năng đọc code. Cố gắng tránh viết nhiều câu trong một dòng.

1 2

print("Chao mung ban den voi Khoa Cong nghe thong tin") print("Lap trinh phat trien ung dung voi Python")

Ví dụ 1.1.3. Chương trình Python đầu tiên.

Tuy nhiên, chúng ta vẫn có thể viết nhiều dòng bằng cách chấm dứt một câu với sự trợ giúp của dấu ’;’. Trong trường hợp này, dấu ’;’ được sử dụng như là dấu kết thúc một câu lệnh.

1 2

a = 3; b = 4; c = a + b print(a); print(b); print(c)

Ví dụ 1.1.4. .

Một số câu lệnh có thể rất dài buộc phải cuộn màn hình sang trái và phải thường xuyên. Chúng ta có thể điều chỉnh code của mình theo cách mà không phải cuộn nhiều. Python cho phép chúng ta viết một câu lệnh trong nhiều dòng, còn được gọi là tiếp tục dòng. Đồng thời, tiếp tục dòng cũng tăng cường khả năng đọc code. Một số quy tắc khi lập trình Python như sau: - Tất cả từ khóa là chữ thường (không in hoa). Đoạn mã trong chương trình Python có phân biệt chữ thường và chữ hoa. Ví dụ: do while thì khác với DO WHILE. - Từ khóa không thể dùng cho các mục đích khác như đặt tên biến (Variable name) hoặc tên hàm (Function name). - Hàm main() luôn là hàm đầu tiên được gọi đến khi một chương trình bắt đầu chạy.

1.1.5 Môi trường phát triển tích hợp IDE để lập trình Python

Môi trường phát triển tích hợp IDE (Integrated Development Environment) để lập trình Python gồm các thành phần chính sau: Biên tập chương trình nguồn (Edit), biên dịch chương trình (Complile), chạy chương trình nguồn (Runtime), sửa lỗi chương trình nguồn (Debug). Các bước để thực hiện dịch một chương trình Python từ mã nguồn thành mã thực thi như sau: • Soạn thảo: Ta dùng một trình xử lý từ (Word processor) hay trình soạn thảo (editor) để viết mã nguồn (Source code). Python chỉ chấp nhận loại mã nguồn viết dưới dạng tập tin văn bản chuẩn. Vài trình biên dịch cung cấp môi trường lập trình gồm trình soạn thảo. • Mã nguồn: Đây là đoạn văn bản của chương trình mà người dùng có thể đọc. Nó là đầu vào của trình biên dịch C dưới dạng các file *.py.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 24

• Bộ tiền xử lý Python: Từ mã nguồn, bước đầu tiên là chuyển nó qua bộ tiền xử lý của C. Bộ tiền xử lý này sẽ xem xét những câu lệnh bắt đầu bằng dấu #. Những câu lệnh này gọi là các chỉ thị tiền biên dịch (Directives). Điều này sẽ được giải thích sau. Chỉ thị tiền biên dịch thường được đặt nơi bắt đầu chương trình mặc dù nó có thể được đặt bất cứ nơi nào khác. Đây là những tên ngắn gọn được gán cho một tập mã lệnh.

• Mã nguồn mở rộng Python: Bộ tiền xử lý của Python khai triển các chỉ thị tiền biên dịch và đưa ra kết quả. Đây gọi là mã nguồn C mở rộng, sau đó nó được chuyển cho trình biên dịch Python.

• Trình biên dịch Python (Compiler): Trình biên dịch Python dịch mã nguồn mở rộng thành ngôn ngữ máy để máy tính hiểu được. Nếu chương trình quá lớn nó có thể được chia thành những tập tin riêng biệt và mỗi tập tin có thể được biên dịch riêng rẽ. Điều này giúp ích khi mà một tập tin bị thay đổi, toàn chương trình không phải biên dịch lại. • Bộ liên kết (Linker): Mã đối tượng cùng với những thủ tục hỗ trợ trong thư viện chuẩn và những hàm được dịch riêng lẻ khác kết nối lại bởi bộ liên kết để cho ra mã có thể thực thi được.

1.1.5.1 Cài đặt Python trên Windows 11

Một số môi trường IDE thông dụng để soạn thảo và lập trình Python là: Notepad++, PyCharm, Visual Studio Code, Sublime Text, IDLE (Python 3.5 64-bit)...(Xem hướng dẫn sử dụng các môi trường trong Phụ lục A).

Các phiên bản của Python có 2 nhánh chính là Python 2 và Python 3. Python 3 không hoàn toàn tương thích với Python 2. Trong giáo trình này, chúng ta sẽ sử dụng phiên bản Python 3.10.2 trên Windows 11 được download ở website chính thức của Python với link https://www.python.org/downloads/. Chúng ta double click vào file cài đặt Python để bắt đầu cài đặt.

Hình 1.5: Cài đặt Python

Giao diện cài đặt có các lựa chọn sau:

(1) Cài đặt với đường dẫn và các cấu hình mặc định. (2) Chỉnh sửa đường dẫn và các cấu hình. (3) Nên chọn để cấu hình môi trường Python trong Windows.

1.1 Giới thiệu chung 25

Sau khi cài đặt thành công, chúng ta sẽ thấy folder cài đặt Python trong thư mục tương ứng.

Hình 1.6: Thư mục cài đặt Python

Để xem các chương trình Python đã được cài đặt, chúng ta vào Start trên Windows 10.

Hình 1.7: Chương trình Python đã được cài đặt

Chương trình IDLE là môi trường phát triển tích hợp đơn giản cho Python, được đóng gói với bộ cài đặt từ phiên bản Python 1.5.2b1. Chương trình Python 3.10 (64 bit) là trình thông dịch Python, các source code muốn chạy được thì đều phải được thông dịch bởi trình thông dịch Python. Để kiểm tra version của Python đã cài đặt, chúng ta sử dụng lệnh python trên Command Prompt của Windows 11.

Hình 1.8: Kiểm tra version của Python đã cài đặt

Python có 2 chế độ thực thi: • Chế độ dòng lệnh: Người lập trình gõ và chạy từng lệnh một thông qua Command Line hoặc chương trình IDLE. Chúng ta gõ dòng lệnh nào xong nhấn Enter, python sẽ thực thi ngay dòng lệnh đó. Để chấm dứt chế độ này, gõ lệnh: quit().

Chương 1. Giới thiệu ngôn ngữ lập trình Python 26

Hình 1.9: Thực thi chế độ dòng lệnh với IDLE

Hình 1.10: Thực thi chế độ dòng lệnh qua Command Prompt

• Chế độ chương trình: Người lập trình biên soạn chương trình và lưu thành file, sau đó chỉ ra chương trình cần thực hiện thông qua lệnh python first.py chạy file first.py. Trình dịch python sẽ nạp, dịch và chạy file chương trình đó.

Hình 1.11: Thực thi chế độ chương trình qua IDLE

1.1.5.2 Cài đặt Visual Studio Code

1.1 Giới thiệu chung 27

Visual Studio Code là trình soạn thảo được phát triển bởi Microsoft rất gọn nhẹ, hỗ trợ nhiều ngôn ngữ lập trình, có đầu đủ các chức năng như: debugging, syntax highlighting, intelligent code completion, snippets, code refactoring và embedded Git. Chúng ta có thể download và cài đặt từ đường link https://code.visualstudio.com/download. Các bước cài đặt được thể hiện trong Hình 1.12, nhấn Next rồi chọn đường dẫn để cài đặt.

Hình 1.12: Các bước cài đặt Visual Studio Code

Thực hiện thay đổi đường dẫn cài đặt, sau khi cài đặt thành công, chúng ta sẽ thấy folder cài đặt Visual Studio Code như sau:

Hình 1.13: Thư mục cài đặt Visual Studio Code

Giao diện khi mới bắt đầu “Get Started” của Visual Studio Code được thể hiện trong Hình 1.14.

Hình 1.14: Giao diện của Visual Studio Code

Chương 1. Giới thiệu ngôn ngữ lập trình Python 28

Thiết lập môi trường lập trình Python với Visual Studio Code: Để lập trình Python với Visual Studio Code, chúng ta cần cài extension Python cho Visual Studio Code. Extension Python được phát hành bởi Microsoft giúp tự động nhận biết trình thông dịch Python, hỗ trợ gợi nhớ code, gợi ý lỗi, debug, format code,. . .

Cài đặt extension Python trên Visual Studio Code: Để cài đặt extension Python trong Vi- sual Studio Code, chúng ta tìm đến phần Extensions (hoặc nhấn tổ hợp phím Ctrl+Shift+X), gõ python và tiến hành cài đặt extension. Sau đó, tìm đến phần Explorer (hoặc nhấn tổ hợp phím Ctrl+Shift+E) để open một folder người dùng sẽ tạo các file source code Python.

Hình 1.15: Cài đặt extension Python trên Visual Studio Code

Để thực thi một file Python trong Visual Studio Code

(1) Khu vực các file source code của Python (2) Khu vực soạn thảo source của Python (3) Trình thông dịch sẽ tự động được nhận diện khi đang mở file .py (4) Nhấn để thực thi source code của Python (5) Khu vực Terminal để hiển thị kết quả chương trình Python

Hình 1.16: Thực thi file Python trên Visual Studio Code

Môi trường ảo trong Python: Một ứng dụng Python thường có những thư viện với các phiên bản khác nhau. Trong nhiều trường hợp, chúng ta lập trình cho nhiều ứng dụng cùng lúc. Sẽ rất phiền phức và gặp những lỗi không đáng có nếu các ứng dụng này sử dụng các phiên bản thư viện khác nhau nhưng chúng lại đụng độ với nhau. Ví dụ, ứng dụng A sử dụng thư viện abc version 1.7. Ứng dụng B cũng sử dụng thư viện abc nhưng version 2.1. Cả 2 thư viện này đều có hàm method1() nhưng do phiên bản khác nhau nên chúng sẽ xử lý khác nhau. Khi chạy ứng dụng A và B thì rất dễ gây ra lỗi hoặc làm cho chương trình chạy không chính

1.2 Các kiểu dữ liệu trong Python 29

xác. Những trường hợp này xảy ra rất nhiều trong thực tế khi chúng ta phải bảo trì các dự án cũ và phát triển các dự án mới.

Cài đặt môi trường ảo cho chương trình Python: Để quản lý các thư viện tốt hơn, Python cho phép tạo ra các môi trường ảo (virtual environment) riêng, chứa các thư viện riêng cho từng ứng dụng. Để tạo môi trường ảo cho Python trong Visual Studio Code, chúng ta vào khu vực Terminal, gõ lệnh python -m venv .venv. Trong đó, .venv là tên của môi trường ảo được tạo. Tên của môi trường ảo là do chúng ta tự chọn.

Hình 1.17: Tạo ra môi trường ảo của Python với Visual Studio Code

Tạo ra môi trường ảo của Python với Visual Studio Code: Trong ví dụ trên, chúng ta tạo môi trường ảo .venv trong folder C:\python-examples của một ứng dụng Python. Sau đó, chúng ta sử dụng lệnh .venv\Scripts\activate để kích hoạt môi trường ảo. Với .venv là tên của môi trường ảo và cũng là folder chứa môi trường ảo. Khi đang ở môi trường ảo, chúng ta có thể cài đặt các thư viện cho riêng môi trường ảo này với lệnh pip install . Hoặc muốn thoát khỏi môi trường ảo thì sử dụng lệnh deactivate.

Hình 1.18: Cài đặt thư viện cho môi trường ảo của Python với Visual Studio Code

1.2 Các kiểu dữ liệu trong Python

Bất cứ chương trình ứng dụng nào cần xử lý dữ liệu cũng cần có nơi để lưu trữ tạm thời dữ liệu ấy. Nơi mà dữ liệu được lưu trữ gọi là bộ nhớ. Những vị trí khác nhau trong bộ nhớ có thể được xác định bởi các địa chỉ duy nhất. Những ngôn ngữ lập trình trước đây yêu cầu lập trình viên quản lý mỗi vị trí ô nhớ thông qua địa chỉ, cũng như giá trị lưu trong nó. Các lập trình viên dùng những địa chỉ này để truy cập hoặc thay đổi nội dung của các ô nhớ. Khi ngôn ngữ lập trình phát triển, việc truy cập hay thay đổi giá trị ô nhớ đã được đơn giản hoá nhờ sự ra đời của khái niệm biến.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 30

Trong khoa học máy tính và lập trình máy tính, một kiểu dữ liệu (Data type) hay đơn giản type là một cách phân loại dữ liệu cho trình biên dịch hoặc thông dịch hiểu các lập trình viên muốn sử dụng dữ liệu. Hầu hết các ngôn ngữ hỗ trợ nhiều kiểu dữ liệu khác nhau, như số thực, số nguyên hay logic. Như vậy, kiểu dữ liệu chính là một cách phân loại dữ liệu, mô tả dữ liệu để chương trình hiểu những lập trình viên đang muốn sử dụng dữ liệu, và dữ liệu đó được mô tả bởi kiểu dữ liệu mà các ngôn ngữ lập trình hỗ trợ. Các kiểu dữ liệu cơ sở trong Python được minh họa trong Hình 1.19.

Hình 1.19: Các kiểu dữ liệu cơ sở trong Python

1.2.1 Kiểu số nguyên (int)

Kiểu số nguyên int trong Python được sử dụng để biểu diễn các số nguyên có dấu với độ lớn tùy ý. Kiểu int trong Python không sử dụng số bit cố định để biểu diễn như trong các ngôn ngữ khác. Tùy thuộc vào giá trị cụ thể Python sẽ chọn số bit phù hợp. Giá trị nguyên lớn nhất mà Python biểu diễn được chỉ phụ thuộc vào bộ nhớ.

Python hỗ trợ biểu diễn số nguyên dương, số nguyên âm, số ở dạng thập phân, hệ cơ số 8, hệ cơ số 16. Khi biểu diễn số ở cơ số 8 chúng ta dùng tiền tố 0o hoặc 0O (số không và chữ o hoa/thường). Khi biểu diễn số ở hệ 16 thì dùng tiền tố 0x hoặc 0X (số 0 và chữ x/X). Bảng 1.4 minh họa ví dụ về cách biểu diễn số nguyên trong Python:

Bảng 1.4: Cách biểu diễn số nguyên trong Python

Giá trị

Nội dung biểu diễn

Số nguyên dương Số nguyên âm Số dương ở cơ số 8 (số 64 cơ số 10) Số âm ở cơ số 8 Số dương ở cơ số 16 (256 cơ số 10) Số âm ở cơ số 16

100 -100 0o100, 0O100 -0o100, -0O100 0x100, 0X100 -0x100, -0X100

Ví dụ, các số được biểu diễn ở dạng int như: ..., -100, -99,..., 0, 1, 2,..., 999, 1000,.... Trong toán học, kiểu int chính là biểu diễn cho các số thuộc tập số nguyên N. Số thuộc kiểu int có thể được tạo bằng các nhập trực tiếp một số nguyên. Hoặc là kết quả của các phép toán giữa các số nguyên. Chú ý khi viết số ở cơ số 8 tốt nhất là dùng chữ o (thường) do chữ O (hoa) rất dễ nhầm lẫn với số 0.

1.2 Các kiểu dữ liệu trong Python 31

1 2 3 4 5

>>> a = 168 # gan gia gia tri cua bien a la so 168, la mot so nguyen >>> a 168 >>> type(a) # so nguyen thuoc lop ’int’ trong Python

Ví dụ 1.2.1. Nhập và xuất các số nguyên và in ra kiểu của biến.

Python cũng cho phép dùng ký tự gạch chân _ để nhóm các chữ số trong biểu diễn số:

1 2 3

>>> i = 1_000_000 # tuong duong voi 1000000 nhung de doc hon >>> i 1000000

Ví dụ 1.2.2. Sử dụng tự gạch chân _ để nhóm các chữ số trong số nguyên.

Có một số ngoại lệ trong Python, ví dụ khi phép chia giữa các số kiểu int nhưng sẽ lại trả về kiểu float. Các số thuộc kiểu int chỉ được tạo ra từ phép toán giữa các số thuộc kiểu int. Hoặc sử dụng ép kiểu với hàm int():

1 2 3 4 5

>>> tuoi = int(input("Nhap tuoi cua ban: ")) # chuyen chuoi ve so nguyen Nhap tuoi cua ban: 40 >>> print(’Ban sinh nam ’, 2023-tuoi) Ban sinh nam 1983 >>>

Ví dụ 1.2.3. Sử dụng ép kiểu số nguyên.

Lưu ý:

1. Python 2.x có hai kiểu số nguyên int và long. Kiểu long cần biểu diễn với hậu tố L (hoặc l). Số nguyên ở hệ cơ số 8 viết bắt đầu bằng 0. Vì vậy, khi đọc giáo trình, chúng ta nên lưu ý xem đó là Python 2 hay Python 3. Hai phiên bản này có nhiều điểm không tương thích.

2. Trong Python 3.X, kiểu dữ liệu số nguyên là vô hạn. Điều này cho phép người lập trình tính toán với những số cực kì lớn, điều mà đa số các ngôn ngữ lập trình khác không thể.

1.2.2 Kiểu số thực (float)

Kiểu số thực float trong Python được sử dụng để biểu diễn các số không ở dạng số nguyên hay nói cách khác là dạng thập phân. Trong toán học, float biểu diễn cho các số thuộc tập số thực R. Các cách biểu diễn số thực trong Python được cho trong Bảng 1.5.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 32

Bảng 1.5: Cách biểu diễn số thực trong Python

Giá trị

Nội dung biểu diễn

Giá trị 0.0 (float) chưa chắc đã bằng 0 (int) Số thực dương Số thực âm Cách viết khoa học là +/ − 100 × 102 = +/ − 10000.0

0.0 100.0 -100.0 100e2, -100e2 100e-2, -100e-2 Cách viết khoa học là +/ − 100 × 10−2 = +/ − 1.0

100., -100.

Không cần viết số 0 sau dấu chấm thập phân, tương đương 100.0, -100.0

1 2 3 4 5 6 7 8 9 10

>>> import sys >>> sys.float_info sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1) >>> sys.float_info.max # gia tri cuc dai cua kieu float 1.7976931348623157e+308 >>> sys.float_info.min # gia tri cuc tieu cua kieu float 2.2250738585072014e-308 >>>

Ví dụ 1.2.4. Xem các thông tin về kiểu float trong Python.

1 2 3

>>> i = 1_000_000.001 >>> i 1000000.001

Chúng ta cũng có thể dùng ký tự gạch chân đế nhóm các chữ số khi viết số thực:

Số thực có thể được tạo trực tiếp bằng các nhập một số có dấu thập phân hoặc sử dụng các phép toán như phép chia giữa các số nguyên. Đối với phép chia hết, các số 0 ở phần thập thân được bỏ qua. Tương tự, khi nhập trực tiếp, các chữ số 0 ở cuối cũng được lược bỏ.

1 2 3 4 5 6

>>> 3/8 0.375 >>> 0.98765432100000 0.987654321 >>> 8/2 4.0

Ví dụ 1.2.5. Thao tác tính toán trực tiếp trên các số thực.

Khi người dùng nhập "7" thì số có giá trị bằng 7 được lưu trữ trong máy tính dưới kiểu int. Tuy nhiên, nếu nhập "7.0" thì vẫn số có giá trị bằng 7 đó nhưng sẽ được lưu trữ dưới kiểu float. Lưu ý, việc chia các số nguyên có thể tạo ra một kết quả thuộc kiểu float. Tuy nhiên, một số thuộc kiểu float cũng được sinh ra khi thực hiện các phép toán giữa các số thuộc kiểu float, hoặc một số kiểu float với một số kiểu integer.

1.2 Các kiểu dữ liệu trong Python 33

1 2 3 4 5 6 7 8 9 10

>>> f = 1.23 # gan gia tri cua bien f la so 1.23, la mot so thuc >>> f 1.23 >>> type(f) # so thuc trong Python thuoc lop ’float’ >>> q = 1.0 # day la so thuc, khong phai so nguyen >>> q 1.0 >>> type(q)

Ví dụ 1.2.6. Gán giá trị của biến f là 1.23 và xuất ra kiểu dữ liệu của f.

Ngoài ra, số float cũng có thể được tạo ra bằng việc chuyển đổi từ một kiểu dữ liệu số khác (việc chuyển đổi này gọi là ép kiểu) với hàm float().

1 2 3 4 5

>>> a = 8 >>> print(a) 8 >>> print(float(a)) 8.0

Ví dụ 1.2.7. Thực hiện ép kiểu một số thuộc kiểu int sang kiểu float.

Máy tính không thể lưu trữ số float hoàn toàn chính xác. Tương tự như việc chúng ta không thể viết hết phần thập phân của phân số 1/3 (0.3333333333333...). Đây không phải do lỗi của người lập trình, hay do Python. Điều này xảy ra trên toàn bộ các ngôn ngữ lập trình. Một cách dễ hiểu, là cách lưu trữ số thập phân của máy tính tạo nên lỗi này. Máy tính lưu trữ các số dưới dạng các dãy nhị phân. Do đó nên khi muốn lưu trữ bất kì một số nào đó, máy tính sẽ phải chuyển số đó về dạng nhị phân. Nhưng có nhiều số không thể được chuyển một cách chính xác hoàn toàn, và xuất hiện sai số. Khi học tập cũng như khi làm việc, chúng ta cần chú ý đến những lỗi như thế này để tránh nhầm lẫn.

1 2 3 4 5 6

>>> 0.1 + 0.2 0.30000000000000004 >>> 0.20 - 0.15 0.05000000000000002 >>> 0.05 * 0.2 0.010000000000000002

Ví dụ 1.2.8. Một số nhầm lẫn khi thực hiện với số thực float.

Số thực trong Python có độ chính xác xấp xỉ 15 chữ số phần thập phân.

1 2

>>> 10 / 3 # day la mot so vo han tuan hoan 3.3333333333333333333.. 3.3333333333333335

Ví dụ 1.2.9. Số thực trong Python có độ chính xác xấp xỉ 15.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 34

Nếu chúng ta muốn có kết quả được chính xác cao hơn thì sử dụng Decimal

1 2 3 4 5 6 7 8 9 10

>>> from fractions import Fraction # Lay toan bo noi dung cua thu vien Decimal # Nen dung: from fractions import Fraction de tao thoi quen trong cong viec sau nay. >>> getcontext().prec = 30 # lay toi da 30 chu so phan nguyen va phan thap phan >>> Decimal(10) / Decimal(3) Decimal(’3. 33333333333333333333333333333’) >>> Decimal(100) / Decimal(3) Decimal(’33.3333333333333333333333333333’) >>> type(Decimal(5)) # cac so Decimal thuoc lop Decimal

Ví dụ 1.2.10. Sử dụng thư viện Decimal để tăng độ chính xác của số thực.

Lưu ý: 1. Thông thường, khi viết số thực, phần nguyên và phần thập phân được tách nhau bởi dấu phẩy (,) nhưng trong Python, dấu phẩy (,) được thay thế thành dấu chấm (.).

2. Tuy Decimal có độ chính xác cao hơn so với float tuy nhiên nó lại khá rườm rà so với float. Do đó, hãy cân bằng sự tiện lợi và chính xác để chọn kiểu dữ liệu phù hợp.

1.2.3 Kiểu số phức (complex)

Python là một trong số ít các ngôn ngữ hỗ trợ trực tiếp kiểu số phức complex. Tuy nhiên số phức tương đối ít được sử dụng. Trong toán học, số phức được biểu diễn ở dạng tổng quát a + bi với a là phần thực, b là phần ảo, i là đơn vị ảo. Trong Python, đơn vị ảo được biểu diễn bằng ký tự j hoặc J. Như vậy, số phức trong Python cần chứa ký tự j (hoặc J) để biểu diễn phần ảo. Chúng ta xem xét một số ví dụ về cách biểu diễn số phức trong Python trong Bảng 1.6.

Bảng 1.6: Cách biểu diễn số phức trong Python

Giá trị

Nội dung biểu diễn

3.14j 45.j 3 + 2j 1+3.2e25j 1+j

Chỉ có phần ảo (0 + 3.14j) Chính là (0 + 45j) Số phức (3 + 2j) Phần ảo biểu diễn ở dạng khoa học Lỗi: j ở đây sẽ hiểu là một biến, phải viết 1 + 1j

Lưu ý: Trong Python, j (J) phải đi kèm số mới được xem là đơn vị ảo. Nếu đứng một mình j (J) sẽ được xem là tên biến nên 1 + j là một biểu thức với j là biến, nhưng 1 + 1 j là một số phức. Để tạo một số phức, chúng ta có thể sử dụng hàm complex với cú pháp sau: complex(,). Để gán giá trị số phức cho một biến: = + j. Để làm việc riêng với phần thực hoặc phần

1.2 Các kiểu dữ liệu trong Python 35

ảo chúng ta có thể sử dụng real và imag là hai thành viên của kiểu complex giúp chúng ta trích giá trị của phần nguyên và phần ảo.

1 2 3 4 5

>>> c = 1.23 + 4.56j >>> c.real 1.23 >>> c.imag 4.56

Ví dụ 1.2.11. Sử dụng phần thực và phần ảo của số phức.

>>> 3j + 1 # phan thuc la 1, phan ao la 3 (1 + 3j) >>> c = 2 + 1j # gan gia tri cho bien c la mot so phuc voi phan thuc 2, phan ao 1 >>> c (2 + 1j) >>> 4 + j # phan ao la 1, tuy vay chung ta khong duoc phep bo so 1 nhu trong toan Traceback (most recent call last):

File "", line 1, in

NameError: name ’j’ is not defined >>> 4 + 1j (4 + 1j) >>> c.imag # lay phan ao cua so phuc 2 + 1j ma ta da gan cho bien c 1.0 >>> c.real # lay phan thuc 2.0 >>> complex(3, 1) # dung ham complex de tao mot so phuc voi phan thuc la 3, ao la 1 (3 + 1j) >>> complex(2) # chi co phan thuc, phan ao duoc mac dinh la 0 (2 + 0j) >>> type(3 + 1j) # cac so phuc thuoc lop complex

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

Ví dụ 1.2.12. Nhập một số số phức 1 + 3j. Gán biến c có giá trị 2+1j. Xuất ra phần thực và phần ảo của biến c. 4 +j (sẽ có lỗi vì kiểu dữ liệu nhập vào không đúng). Tạo số phức có phần thực là 3, phần ảo là 1.Tạo số phức chỉ có phần thực là 2. Xuất ra kiểu dữ liệu của số 3+1j.

1.2.4 Kiểu logic (bool)

Kiểu logic bool trong Python được sử dụng để biểu diễn hai các giá trị True hoặc False (hay có hoặc không). True và False đồng thời được xem là hai từ khóa trong Python.

>>> a = True >>> type(a) # ham cho biet kieu cua bien

>>> b = False >>> type(b)

1 2 3 4 5 6 7

Ví dụ 1.2.13. Gán trực tiếp kiểu Boolean bằng cách nhập từ bàn phím.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 36

Nếu chúng ta đã học một ngôn ngữ trong họ C cần lưu ý giá trị là True/False (T và F phải viết hoa). Viết true/false là sai và sẽ bị báo lỗi như sau:

>>> a = true # Python se hieu true la mot bien (von chua ton tai) Traceback (most recent call last):

File "", line 1, in NameError: name ’true’ is not defined

1 2 3 4

Ví dụ 1.2.14. Python phân biệt True/False và true/false.

Có thể tạo bằng cách gán trực tiếp từ giá trị True hoặc False trong code hoặc là kết quả của giữa các toán tử so sánh: >, >=, <=, ==, and, or... Hoặc là ép kiểu.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

>>> a = 10; b = 5 >>> a > b True >>> a <= b False >>> a != b True >>> a == b False >>> 0 < b < a < 11 # Python cho phep viet nhu the nay True >>> a = ’Hello’; b = ’Python’ >>> a != b True >>> a > b False >>> a < b True >>> a == b False

Ví dụ 1.2.15. Các phép toán so sánh tạo ra giá trị logic.

1 2 3 4 5

>>> b = 3 >>> c = 4 >>> a = (c >= b) and (c == 4) >>> print(a) True

Ví dụ 1.2.16. Kết quả giữa các toán tử logic and, or, so sánh trên kiểu bool.

1 2 3 4

>>> print(bool(1)) >>> True >>> >>> print(bool(0.1))

Ví dụ 1.2.17. Ép kiểu trên kiểu bool.

5 6 7 8

>>> True >>> >>> print(bool(0)) >>> False

1.2 Các kiểu dữ liệu trong Python 37

Ép kiểu ngầm: Chúng ta cần biết một quy tắc ngặt nghèo rằng, các toán tử chỉ thực hiện được khi trên cùng một kiểu dữ liệu. Vậy tại sao các phép toán được thực hiện trên các kiểu dữ liệu khác nhau đề cập ở trên vẫn trả về kết quả đúng (Ví dụ, phép toán giữa float với integer). Lý do đó chính là việc chuyển đổi ngầm, hay gọi là ép kiểu ngầm do đây là một ngoại lệ vì Python âm thầm chuyển đổi kiểu dữ liệu để thực hiện các phép tính ở trên thay vì quy tắc trong Python. Thông thường chúng ta phải chuyển đổi giá trị bằng tay nếu muốn code hoạt động trên chúng.

>>> 2 / 2 1.0 >>> 3.0 / 2 1.5 >>> True + False 1 >>> True + 1 2 >>> 1 / True 1.0 >>> False and 1 False >>> False or 1 1

1 2 3 4 5 6 7 8 9 10 11 12 13 14

Ví dụ 1.2.18. Ép kiểu ngầm trên kiểu Boolean.

>>> my_string = "Hello World" >>> my_string.isalnum() #kiem tra xem chuoi co chua toan chu so False >>> my_string.isalpha() # chuoi chua toan chu cai False >>> my_string.isdigit() # chuoi co chua chu so False >>> my_string.isupper() # chuoi chua toan ky tu hoa False >>> my_string.islower() # chuoi chua toan ky tu thuong False >>> my_string.isspace() # chuoi chi chua khoang trang False >>> my_string.endswith(’d’) # ket thuc la d True >>> my_string.startswith(’H’) # bat dau la H True

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Ví dụ 1.2.19. Các phương thức kiểm tra trên kiểu dữ liệu ký tự str cũng trả về giá trị bool.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 38

1.2.5 Kiểu chuỗi ký tự (string)

Kiểu string trong Python là chuỗi các ký tự unicode. Python cho phép viết giá trị chuỗi theo nhiều cách khác nhau:

Bảng 1.7: Cách biểu diễn chuỗi ký tự trong Python

Giá trị

Nội dung biểu diễn

’Hello world’ ’’Hello world’’ ’’’Hello world’” “””Hello world””” ‘I want to say “I love you”‘ “My name’s Nhuongld ‘My name\’s Donald’ “I want to say \”I love you\””

Sử dụng cặp dấu nháy đơn Sử dụng cặp dấu nháy kép Sử dụng cặp ”’ (3 dấu nháy đơn) Sử dụng cặp “”” (3 dấu nháy kép) Có thể dùng dấu nháy kép trong chuỗi nằm trong cặp dấu nháy đơn Có thể dùng dấu nháy đơn trong chuỗi nằm trong cặp dấu nháy kép Dùng \’ để biểu diễn dấu ‘ trong chuỗi nằm giữa cặp nháy đơn Dùng \” để biểu diễn dấu ” trong chuỗi nằm giữa cặp nháy kép

Ghi chú: Python không có kiểu ký tự như các ngôn ngữ khác. Kiểu ký tự trong Python có thể xem như một chuỗi chỉ chứa 1 ký tự.

Chuỗi ký tự đặt trong cặp dấu nháy đơn có thể chứa dấu nháy kép. Tương tự, nếu chuỗi ký tự đặt trong cặp dấu nháy kép thì có thể chứa cả dấu nháy đơn. Chuỗi ký tự tạo ra bởi cặp dấu nháy đơn hoặc nháy kép bắt buộc phải nằm trên một dòng. \’ và \” được gọi là các escape character biểu diễn cho ký tự ‘ và “. Cặp 3 dấu nháy đơn (hoặc cặp 3 dấu nháy kép) cho phép tạo ra chuỗi với nhiều dòng.

>>>text = """Strings are amongst the most popular types in Python. We can create them simply by enclosing characters in quotes. Python treats single quotes the same as double quotes. Creating strings is as simple as assigning a value to a variable.""" >>>print(text)

1 2 3 4 5 6 7 8

>>>line = "Hello world" >>>print(line)

Ví dụ 1.2.20. .

Tương tự như Các kiểu dữ liệu số trong Python, string cũng là kiểu dữ liệu bất biến (immutable). Nghĩa là mọi thao tác cập nhật chuỗi đều dẫn đến tạo chuỗi mới. Điều này cũng tương tự như kiểu string trong C#.

1.3 Biến, phép gán, câu lệnh và biểu thức

1.3.1 Biến

Một chương trình ứng dụng có thể quản lý nhiều loại dữ liệu. Trong trường hợp này, chương trình phải chỉ định bộ nhớ cho mỗi đơn vị dữ liệu. Khi chỉ định bộ nhớ, có hai điểm cần lưu ý

1.3 Biến, phép gán, câu lệnh và biểu thức 39

như sau: Bao nhiêu bộ nhớ sẽ được gán và mỗi đơn vị dữ liệu được lưu trữ ở đâu trong bộ nhớ. Trước đây, các lập trình viên phải viết chương trình theo ngôn ngữ máy gồm các mã 1 và 0. Nếu muốn lưu trữ một giá trị tạm thời, vị trí chính xác nơi mà dữ liệu được lưu trữ trong bộ nhớ máy tính phải được chỉ định. Vị trí này là một con số cụ thể, gọi là địa chỉ bộ nhớ. Các ngôn ngữ lập trình hiện đại cho phép chúng ta sử dụng các tên tượng trưng gọi là biến, chỉ đến một vùng bộ nhớ nơi mà các giá trị cụ thể được lưu trữ.

Biến (Variable) là một đại lượng được người lập trình định nghĩa và được đặt tên thông qua việc khai báo biến. Biến dùng để chứa dữ liệu trong quá trình thực hiện chương trình và giá trị của biến có thể bị thay đổi trong quá trình này. Cách đặt tên biến giống như cách đặt tên đã nói trong phần trên. Mỗi biến thuộc về một kiểu dữ liệu xác định và có giá trị thuộc kiểu đó. Định nghĩa và cách hoạt động của biến trong Python có điểm khác biệt với các ngôn ngữ như C. Trong Python, biến là một tên gọi đại diện cho một giá trị trong bộ nhớ. Trong đó, giá trị có thể do chúng ta tự khai báo hoặc được Python tính toán từ một biểu thức. Để dễ hình dung, biến trong Python có nét tương tự như file và shortcut trong windows. Trong đó, file trên ổ đĩa tương tự như giá trị của biến trong bộ nhớ còn shortcut (lối tắt) đến file tương tự như biến trong Python. Khi đó:

• Nhiều biến có thể “trỏ” đến cùng một giá trị trong bộ nhớ: Giống như chúng ta có thể tạo nhiều lối tắt tới cùng một file, chúng ta có thể để cho nhiều biến khác nhau cùng trỏ tởi một giá trị chung.

• Một biến có thể trỏ sang các giá trị khác nhau: Khi tạo ra biến chúng ta có thể để cho nó trỏ tới giá trị a, sau đó chúng ta có thể để cho nó trỏ tới giá trị b, trong đó a và b hoàn toàn khác kiểu nhau.

Như vậy, biến trong Python thực tế chỉ là một tên gọi mà chúng ta có thể sử dụng để truy xuất giá trị. Biến trong Python không trực tiếp chứa giá trị (Biến trong Python gần tương tự như con trỏ trong C/C++ hay kiểu tham chiếu trong C#) Cú pháp khai báo biến: =

# bien x tro toi gia tri 5

1 2 3

x = 5 ch = "Python" y = False

Ví dụ 1.3.1. Khai báo biến

Biến có thể trỏ sang giá trị khác (bỏ lại giá trị cũ trong bộ nhớ). Giá trị cũ không sử dụng tới sẽ bị thu dọn tự động. Biến trong Python bắt buộc phải tạo ra cùng phép gán. Giá trị của biến trong bộ nhớ được tự động “thu dọn” khi không sử dụng đến nhờ một tiến trình gọi là Garbage Collection. Tên biến bắt buộc phải tuân thủ quy tắc đặt định danh trong Python. Ngoài ra có một số kiểu đặt tên biến người lập trình nên tuân theo:

• Kiểu 1: Ký tự đầu tiên viết thường; các chữ cái trong từ viết thường; nếu tên có nhiều từ thì viết hoa chữ cái đầu mỗi từ tiếp theo. Ví dụ companySortedList, firstName, lastName. Đây là lối đặt tên thường gặp trong các ngôn ngữ kiểu C và được gọi là kiểu camelCase.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 40

• Kiểu 2: tất cả ký tự trong tên gọi đều viết thường; nếu tên có nhiều từ thì phân tách bằng dấu gạch chân _. Ví dụ first_name, last_name, company_sorted_list. Đây là quy ước dùng phổ biến hơn trong Python.

Lưu ý: Trong Python không có khái niệm hằng như trong các ngôn ngữ khác. Nếu muốn sử dụng hằng, chúng ta hãy tạo một biến và đặt tên toàn bộ là chữ hoa để nhớ rằng mình không được thay đổi giá trị của “biến” này!

1.3.2 Phép gán

Phép gán thường được sử dụng trong lập trình dùng để gán giá trị cho biến. Cú pháp của toán tử gán như sau:

= = =

1 2 3 4

a = 16883 b = a c = b a = 468*2

Ví dụ 1.3.2. Cách sử dụng phép gán.

Lệnh gán a = 16883 sẽ tạo ra một giá trị số nguyên 16883 trong bộ nhớ và ‘a’ được dùng để trỏ tới giá trị này. ‘a’ đại diện cho giá trị 16883 trong bộ nhớ chứ ‘a’ không trực tiếp chứa giá trị 16883. Sử dụng ‘a’ trong chương trình tương đương với sử dụng giá trị 16883 từ bộ nhớ. Lệnh gán b = a tạo tiếp biến b trỏ tới cùng giá trị với a, tức là cùng trỏ tới giá trị 16883 trong bộ nhớ. Khi này b và a thực tế là như nhau. Tương tự, lệnh gán c = b tạo tiếp biến c và cùng trỏ tới giá trị của b (và cũng là giá trị của a). Như vậy, a, b và c thực tế là cùng một giá trị nhưng khác tên gọi. Giống như cùng một file nhưng chúng ta có thể tạo nhiều shortcut tới nó. Lưu ý: Trong Python, khai báo biến luôn phải đi kèm gán giá trị, không cần chỉ định kiểu dữ liệu, không cần từ khóa nào khi khai báo biến.

Phép đa gán (multiple assignment) trong Python: Python cho phép chúng ta gán một giá trị đơn cho một số biến một cách đồng thời. Python hỗ trợ hai kiểu đa gán giá trị đơn cho nhiều biến như sau:

1 2 3 4

# tao ra 3 bien a, b, c va cung tro toi mot gia tri a = b = c = 16883 # tao 3 bien va tro toi 3 gia tri khac nhau (theo thu tu) first_name, last_name, age = "Le", "Dac Nhuong", 40

Ví dụ 1.3.3. Phép đa gán trong Python.

Như vậy, chúng ta có thể tạo ra nhiều biến cùng lúc và cho chúng trỏ tới cùng một giá trị, hoặc cũng có thể đồng thời khai báo nhiều biến trỏ tới nhiều giá trị khác nhau. Lưu ý, trong phép gán a = b = c = 16883. Nếu chúng ta tiếp tục gán a = 468 sau đó, Python sẽ tạo ra

1.3 Biến, phép gán, câu lệnh và biểu thức 41

một giá trị mới 2000 và a trỏ sang một giá trị mới này. Tuy nhiên b và c vấn trỏ sang giá trị cũ 16883. Điều tương tự xảy ra nếu giá trị là chuỗi. Số và chuỗi là các kiểu dữ liệu bất biến (immutable) trong Python. Kiểu dữ liệu không ảnh hưởng đến phép gán. Nghĩa là ban đầu chúng ta gán cho biến giá trị số, sau này có tiếp tục gán cho biến đó giá trị chuỗi,...

1 2 3 4 5 6 7

>>> a = 1000 # ban dau a tro toi gia tri so >>> a 1000 >>> a = "Phat trien ung dung voi Python" # a tro toi gia tri chuoi >>> a ’Phat trien ung dung voi Python’ >>>

Ví dụ 1.3.4. Kiểu dữ liệu không ảnh hưởng đến phép gán.

Trong ví dụ trên, ban đầu a trỏ tới giá trị số nguyên, sau đó a lại trỏ tới giá trị chuỗi ký tự.

1.3.3 Câu lệnh và tham số dòng lệnh

Câu lệnh (Statement): là một chỉ thị trực tiếp, hoàn chỉnh nhằm ra lệnh cho máy tính thực hiện một số tác vụ nhất định nào đó. Trình biên dịch bỏ qua các khoảng trắng (hay tab hoặc xuống dòng) chèn giữa lệnh. Trong Python mỗi dòng tương ứng với một câu lệnh. Khác với C, Python không cần kí tự chấm phẩy “;” để kết thúc câu lệnh. Tuy nhiên ta có thể dùng dấu chấm phẩy này để viết nhiều câu lệnh trên một dòng.

1 2 3 4 5

a = 168 x = "abc" print(a) x = 1; print(x) a = 1; b = 2; c = 3

Ví dụ 1.3.5. Câu lệnh.

Một câu lệnh cũng có thể viết trên nhiều dòng với điều kiện: sử dụng dấu nối dòng \ hoặc các dòng được đặt trong dấu ngoặc (), [], {}.

a = 1 + 2 + 3 + \ 4 + 5 + 6 + \ 7 + 8 + 9

b = (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)

1 2 3 4 5 6 7 8 9 10 11

colors = [’red’, ’blue’, ’green’ ]

Ví dụ 1.3.6. Viết câu lệnh trên nhiều dòng.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 42

Khối lệnh: Một khối lệnh (thường là khối lệnh của hàm, vòng lặp,. . . ) bắt đầu với thụt lề và kết thúc với dòng đầu tiên không thụt lề. Thụt lề bao nhiêu là tùy ý nhưng chúng phải nhất quán trong suốt khối lệnh đó (các lệnh trong cùng một khối thì phải có độ thụt lề bằng nhau). Python không cung cấp các dấu ngoặc nhọn ({}) để chỉ các khối lệnh (code) cho định nghĩa lớp hoặc hàm hoặc điều khiển luồng. Các khối lệnh được nhận biết bởi độ thụt dòng (indentation) trong lập trình Python và đây là điều bắt buộc. Số khoảng trống trong độ thụt dòng là biến đổi, nhưng tất cả các lệnh bên trong khối phải được thụt cùng một số lượng khoảng trống như nhau.

if True:

print(True) print("True")

else:

1 2 3 4 5 6

print(False) print("False")

Ví dụ 1.3.7. Các khối lệnh được nhận biết bởi độ thụt dòng.

if True:

print(True) print("True")

else:

1 2 3 4 5 6

print(False) print("False")

Tuy nhiên khối lệnh sau sẽ có lỗi:

for i in range(1,11): print(i) if i == 5:

break

1 2 3 4 5

input()

Ví dụ 1.3.8. Các khối lệnh được nhận biết bởi độ thụt dòng lệnh for.

1 2 3 4 5

for i in range(1,11): print(i); if i == 5: break input()

Tuy nhiên khối lệnh sau sẽ có lỗi:

Các nhóm lệnh đa dòng (còn được gọi là suite) trong Python. Một nhóm các lệnh đơn, mà tạo một khối code đơn, được gọi là suite trong Python. Các lệnh phức hợp như if, while, def, và class cần một dòng header và một suite. Các dòng header bắt đầu lệnh (với từ khóa) và kết thúc với một dầu hai chấm (:) và được theo sau bởi một hoặc nhiều dòng để tạo nên một suite.

Ví dụ 1.3.9. Nhóm lệnh đa dòng (suite) trong Python.

if expression:

suite

elif expression:

suite

else:

1 2 3 4 5 6

suite

1.3 Biến, phép gán, câu lệnh và biểu thức 43

$ python -h usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ... Options and arguments (and corresponding environment variables): -c cmd : program passed in as string (terminates option list) -d : debug output from parser (also PYTHONDEBUG=x) -E : ignore environment variables (such as PYTHONPATH) -h : print this help message and exit

1 2 3 4 5 6 7 8 9

[ etc. ]

Tham số dòng lệnh trong Python: Nhiều chương trình có thể được chạy để cung cấp cho chúng ta một số thông tin cơ bản về cách chúng nên được chạy. Python cho chúng ta khả năng để làm điều này với -h:

1

$ python test.py arg1 arg2 arg3

Chúng ta cũng có thể lập trình cho script của mình theo cái cách mà nó nên chấp nhận các tùy chọn khác nhau tùy theo cách chúng ta thiết lập. Python cung cấp getopt Module giúp chúng ta phân tích cú pháp các tùy chọn và tham số dòng lệnh.

Trong đó, thư viện sys trong Python cung cấp sự truy cập tới bất kỳ tham số dòng lệnh nào thông qua sys.argv. Phục vụ hai mục đích:

• sys.argv là danh sách các tham số dòng lệnh. • len(sys.argv) là số tham số dòng lệnh.

import sys

1 2 3 4

print ’So tham so:’, len(sys.argv), ’tham so.’ print ’Danh sach tham so:’, str(sys.argv)

Ví dụ 1.3.10. Sử dụng tham số dòng lệnh.

1

$ python test.py arg1 arg2 arg3

Bây giờ chạy script trên như sau:

1 2

So tham so: 4 tham so. Danh sach tham so: [’test.py’, ’arg1’, ’arg2’, ’arg3’]

Kết quả là:

Ghi chú: tham số đầu tiên luôn luôn là tên script và nó cũng được đếm trong số tham số.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 44

1

getopt.getopt(args, option, [long_option])

Parse các tham số dòng lệnh: Python cung cấp getopt Module giúp phân tích cú pháp các tùy chọn và tham số dòng lệnh. Module này cung cấp hai hàm và một exception để kích hoạt việc phân tích cú pháp các tham số dòng lệnh. Phương thức getopt.getopt trong Python cho phép phân tích cú pháp danh sách tham số và các tùy chọn tham số dòng lệnh Cú pháp là:

Chi tiết về tham số như sau: • args: Là danh sách tham số để được phân tích. • option: Là chuỗi các tùy chọn mà script muốn để nhận ra. Các tùy chọn yêu cầu một tham số cần được theo sau bởi một dấu hai chấm (:).

• long_option: Là tham số tùy ý và nếu được xác định phải là một danh sách các chuỗi là tên các tùy chọn dài được hỗ trợ. Với các tùy chọn dài yêu cầu một tham số thì nên được theo sau bởi một dấu bằng (=). Để chỉ chấp nhận các tùy chọn dài, các tùy chọn nên là một chuỗi trống. • Phương thức này trả về trả trị bao gồm hai phần tử: phần tử đầu là một danh sách các cặp (option, value). Phần tử thứ hai là danh sách các tham số chương trình. • Cặp option-value được trả về có một dấu gạch nối ngắn ở trước (ví dụ -x) là tùy chọn ngắn, có hai dấu gạch nối là tùy chọn dài (ví dụ --long-option).

1

usage: test.py -i -o

Phương thức getopt.GetoptError trong Python: Đây là một exception và nó được tạo khi thấy một tùy chọn không được nhận ra trong danh sách tham số hoặc khi một tùy chọn cần một tham số mà không cung cấp tham số nào. Tham số cho exception là một chuỗi chỉ nguyên nhân gây ra lỗi. Các thuộc tính msg và opt cung cấp thông điệp lỗi và tùy chọn có liên quan. Giả sử, chúng ta muốn truyền hai tên file thông qua dòng lệnh và chúng ta cũng muốn cung cấp một tùy chọn để kiểm tra sự sử dụng của script. Usage của script là như sau:

import sys, getopt

def main(argv):

inputfile = ’’ outputfile = ’’ try:

opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])

except getopt.GetoptError:

print ’test.py -i -o ’ sys.exit(2)

for opt, arg in opts: if opt == ’-h’:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

print ’test.py -i -o ’ sys.exit()

Nội dung của script như sau:

elif opt in ("-i", "--ifile"):

inputfile = arg

elif opt in ("-o", "--ofile"):

outputfile = arg

print ’Input file is "’, inputfile print ’Output file is "’, outputfile

if __name__ == "__main__":

15 16 17 18 19 20 21 22 23

main(sys.argv[1:])

1.3 Biến, phép gán, câu lệnh và biểu thức 45

1 2 3 4 5 6 7

$ test.py -h usage: test.py -i -o $ test.py -i BMP -o usage: test.py -i -o $ test.py -i inputfile Input file is " inputfile Output file is "

Chúng ta sẽ thực thi script trên như sau:

1.3.4 Chú thích trong Python

Chú thích trên một dòng được bắt đầu bằng dấu thăng#. Chú thích nhiều dòng được đặt trong cặp ba dấu nháy đơn “””.

1 2 3 4 5 6 7

#This is a comment print out Hello print(’Hello’) input() """This is also a perfect example of multi-line comments""" print(’Hello’) input()

Ví dụ 1.3.11. Cả 2 chương trình dưới đây đều in ra chữ “Hello”.

Hàm input() để dừng màn hình như readline trong Pascal hay getch() trong C/C++. Chú thích đối tượng (Docstring) là viết tắt của Documentation string – chuỗi tài liệu, dùng để chú thích tóm tắt chức năng cho những đối tượng (môđun, hàm, method,. . . ). Ba dấu nháy kép được sử dụng để viết docstring.

1 2 3

def nhandoi(num): """Ham nhan doi gia tri nhap vao""" return 2*num

Ví dụ 1.3.12. Chú thích đối tượng trong Python.

1

print(nhandoi.__doc__)

Viết như trên, sau này ta có thể tra cứu (in ra) docstring của hàm để biết chức năng của hàm đã viết. Cách in như sau:

Kết quả sẽ là: “Ham nhan doi gia tri nhap vao”.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 46

1.3.5 Phép toán số học

Các phép toán số học với số nguyên:

Bảng 1.8: Các phép toán số học với số nguyên trong Python

Phép toán Kí hiệu

Ví dụ

Phép toán

Kí hiệu

Ví dụ

|

| Chia | Chia lấy thương | Chia lấy dư

/ // %

2 / 2 = 1 3 // 2 = 1 3 % 2 = 1

Cộng Trừ Nhân Lũy thừa

+ - * **

2 + 1 = 3 2 - 1 = 1 2 * 1 = 2 2 ** 2 = 4

import math x = 4 y = 10 print("Tong cua hai so la: ",x+y) print("Tich cua hai so la: ",x*y)

1 2 3 4 5

Ví dụ 1.3.13. Tính tổng và tích 2 số x và y.

1 2 3 4 5

import math a = 7 b = 4 c = 5 print("Trung binh cong cua 3 so nguyen la: ", (a+b+c)/3)

Ví dụ 1.3.14. Viết chương trình tính trung bình cộng 3 số nguyên dương x, y, z. Hiển thị kết quả ra màn hình.

Các phép toán số học với số thực (float):

Bảng 1.9: Các phép toán số học với số thực trong Python

Phép toán Kí hiệu

Ví dụ

Phép toán Kí hiệu

Ví dụ

|

Lũy thừa

| | Chia

** /

2.0 ** 3.0 = 8.0 4.0 / 2.0 = 2.0

Cộng Trừ Nhân

+ - *

2.0 + 1.0 = 3.0 2.0 - 1.0 = 1.0 2.0 * 3.0 = 6.0

1 2 3

r = 10 C = 2 * r * 3.14 print("Chu vi hinh tron la: ", C)

Ví dụ 1.3.15. Viết chương trình tính chu vi hình tròn biết bán kính r = 5. Hiển thị giá trị chu vi ra màn hình.

1.3 Biến, phép gán, câu lệnh và biểu thức 47

1.3.6 Phép toán quan hệ

Các toán tử quan hệ dùng để so sánh 2 biểu thức với nhau, kết quả thực hiện là 0 (hay False nếu sai) hoặc 1 (hay True nếu đúng). Các toán tử quan hệ gồm: ==, >, <, >=, <, <=, !=

Bảng 1.10: Các phép toán quan hệ trong Python

Phép toán Kí hiệu

Ví dụ

Phép toán

Kí hiệu

Ví dụ

|

Lớn hơn Nhỏ hơn Bằng

> < ==

a > b a < b a == b

| Khác | Lớn hơn hoặc bằng | Nhỏ hơn hoặc bằng

!= >= <=

a != b a >= b a <= b

Kết quả của các phép toán quan hện cho giá trị logic (True or False).

Ví dụ 1.3.16. Cho biết kết quả thực hiện các phép toán quan hệ sau:

• s1 = (1 == 2) và s2 = (1 != 2) • s3 = (1 > 2) và s4 = (1 >= 2) • s5 = (1 < 2) và s6 = (1 <= 2)

1.3.7 Phép toán logic

Các toán tử logic là tổ hợp nhiều biểu thức quan hệ với nhau gồm and, ||or|, not. Một trong những ứng dụng của phép toán logic là để tạo ra các biểu thức phức tạp từ các quan hệ đơn giản.

Bảng 1.11: Các phép toán logic trong Python

Phép toán

Kí hiệu

Ví dụ

True khi cả hai đều True True nếu một trong hai là True Không True khi False

and or not

a and b a or b not a

Ví dụ 1.3.17. Cho biết kết quả thực hiện các phép toán logic sau:

• s1 = (1 > 2) and (3 > 4) • s2 = (1 > 2) or (3 > 4) • s3 = not (1 > 2)

1.3.8 Các phép toán trên kiểu chuỗi

Python cung cấp sẵn một số phép toán trên chuỗi ký tự. Để dễ minh họa các phép toán này, chúng ta giả sử có hai chuỗi a = ‘Hello’ và b = ‘Python’. Lưu ý các phép so sánh chuỗi sẽ so từng cặp ký tự từ trái qua phải, ký tự hoa khác ký tự thường. Python cũng áp dụng các phép so sánh >, <, >=, <= cho kiểu chuỗi ký tự.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 48

Bảng 1.12: Các phép toán trên kiểu chuỗi trong Python

Phép toán Ý nghĩa

Ví dụ

+ * [i] [i1:i2]

Phép ghép xâu (concatenation) Phép lặp xâu (repetition) Phép cắt (slice), lấy ký tự ở vị trí i Phép cắt đoạn (range slice) từ vị trí i1 đến i2; có thể bỏ qua i1 hoặc i2; i1 và i2 âm thì tính từ cuối chuỗi Kiểm tra thành viên

in

Kiểm tra thành viên (phủ định) Chuỗi thô Định dạng chuỗi So sánh xâu (bằng) So sánh xâu (khác)

not in r/R % == !=

a + b cho ‘HelloPython’ a*2 cho ‘HelloHello’ a[0] cho ký tự ‘H’ a[1:4] cho ‘ell’, a[1:] cho ‘ello’ (lấy từ ký tự số 1 về cuối), a[-1:] cho ‘o’ (lấy từ ký tự thứ 1 từ cuối đến hết ký tự cuối cùng), a[1:-1] cho ‘ell’ (lấy từ ký tự số 1 đến ký tự gần cuối) ’lo’ in a cho kết quả True (‘Hello’ chứa ‘lo’), ’lol’ in a cho kết quả False (‘Hello’ không chứa ‘lol’) Giống như trên nhưng kết quả ngược lại Xem Bảng 1.14 Xem Bảng 1.14 a==b cho kết quả False a!=b cho kết quả True

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

>>> a, b = ’Hello’, ’Python’ >>> a + b ’HelloPython’ >>> a[1:] ’ello’ >>> a[-1:] ’o’ >>> a[-1:0] ’’ >>> a[-2:] ’lo’ >>> ’lo’ in a True >>> ’lol’ in a False >>> a * 2 ’HelloHello’ >>> a[0] ’H’ >>>

Ví dụ 1.3.18. Các phép toán trên chuỗi.

1.3.9 Biểu thức số học, quan hệ và logic

Biểu thức được tạo thành từ các toán tử (Operator) và các toán hạng (Operand). Toán tử tác động lên các giá trị của toán hạng và cho giá trị có kiểu nhất định:

• Toán tử: +, –, *, /, %. . . (Toán tử 2 ngôi là toán tử có hai toán hạng trong biểu thức như toán tử: +, –, *, /, % (chia lấy phần dư). Toán tử / được áp dụng cho một số nguyên hoặc ký tự, bất kỳ phần dư nào sẽ được cắt bỏ). • Toán hạng: hằng, biến, lời gọi hàm...

1.3 Biến, phép gán, câu lệnh và biểu thức 49

Một biểu thức số học trong Python bao gồm một tên biến nằm phía bên trái của dấu "=", tên biến hoặc hằng nằm bên phải dấu "=". Biến và hằng nằm bên phải của dấu "=" được nối với nhau bởi những toán tử số học như +, -, *, và /.

Biểu thức số học: Là một biến kiểu số hoặc một hằng số hoặc các biến kiểu số và các hằng số được liên kết với nhau bởi phép toán số học, các dấu ngoặc tròn (và) tạo thành một biểu thức số học.

Quy tắc viết biểu thức số học trong lập trình: • Chỉ dùng cặp ngoặc tròn () để xác định trình tự thực hiện. • Viết lần lượt từ trái qua phải. • Không được bỏ qua dấu nhân trong tích. Thứ tự thực hiện các phép toán: • Thực hiện các phép toán trong ngoặc trước. • Thực hiện từ trái sang phải. • Các phép toán: *,/,//,% thực hiện trước; các phép toán +, - thực hiện sau.

Biểu thức trong toán học Biểu thức trong Python

2x + y 7a - (3b2-5a) ab/(4-3a) 4a2 − (2 + 4ab)2

2*x + y 7*a - (3*a*2 - 5*a) a*b/(4 - 3*a) 4*a*a - (2 + 4*a*b)*(2 + 4*a*b)

Ví dụ 1.3.19. Biểu thức số học trong Python.

Biểu thức quan hệ: Là hai biểu thức cùng kiểu liên kết với nhau bởi phép toán quan hệ. Biểu thức 1, biểu thức 2 cùng là xâu, hoặc cùng là biểu thức số học.

Biểu thức quan hệ Giá trị tham chiếu

Thực hiện phép toán quan hệ

a + 20 > 23 (5X − 3) > 10

a = 4 X = 2

4 + 20 > 23 (52 − 3) > 10

Ví dụ 1.3.20. Biểu thức quan hệ trong Python.

Biểu thức logic: Là các biểu thức logic đơn giản, các biểu thức quan hệ liên kết với nhau bởi phép toán logic. Biểu thức logic đơn giản là biến logic hoặc hằng logic. Các biểu thức quan hệ phải được đặt trong cặp dấu (). Kết quả của biểu thức logic thuộc kiểu logic.

Ví dụ 1.3.21. Biểu thức logic trong Python.

1.3.10 Độ ưu tiên của các toán tử

Quy tắc thực hiện: • Thực hiện biểu thức trong ( ) sâu nhất trước.

Biểu thức logic

Giá trị tham chiếu

Thực hiện phép toán quan hệ

not(a>5) (a > 10) and (X < 9) (a == 5) or (b > 9)

a = 6 a = 11, X = 8 a = 3, b = 10

False True True

Chương 1. Giới thiệu ngôn ngữ lập trình Python 50

Bảng 1.13: Độ ưu tiên của các toán tử

Toán tử

Độ ưu tiên

[] ->

.

-

+

* (cast)

&

>=

++ -- / % - <= > !=

+= -=

*=

/= %=

&= ...

→ (Thực hiện từ trái qua phải) sizeof → (Thực hiện từ phải qua trái) → (Thực hiện từ trái qua phải) → (Thực hiện từ trái qua phải) → (Thực hiện từ trái qua phải) → (Thực hiện từ trái qua phải) → (Thực hiện từ trái qua phải) → (Thực hiện từ trái qua phải) → (Thực hiện từ trái qua phải) → (Thực hiện từ phải qua trái) → (Thực hiện từ phải qua trái)

() ! * + < == and or not = ,

• Thực hiện theo thứ tự ưu tiên các toán tử ⇒ Người lập trình chủ động thêm ( )

Ví dụ 1.3.22. Độ ưu tiên của các toán tử.

• n = 2 + 3 * 5; ⇒ n = 2 + (3 * 5); • a > 1 and b < 2; ⇒ (a > 1) and (b < 2);

Ví dụ 1.3.23. Viết biểu thức cho các mệnh đề sau:

• x lớn hơn hay bằng 3: x >= 3 • a và b cùng dấu: ((a>0)and(b>0)) || ((a<0) and (b<0)) hoặc (a>0 and b>0) || (a<0 and b<0)

• p bằng q bằng r: (p == q) and (q == r) hoặc (p == q and q == r) • -5 < x < 5: (x > -5) and (x < 5) hoặc (x > –5 and x < 5)

Toán tử điều kiện: Là toán tử 3 ngôi (gồm có 3 toán hạng), có cú pháp như sau: [on_true] if [expression] else [on_false]

1 2 3 4 5

>>>x = 5 >>>y = 6 >>>max = x if x>y else y >>>print (max) 6

Ví dụ 1.3.24. Toán tử điều kiện.

Toán tử membership: Toán tử membership trong Python giúp kiểm tra xem biến này có nằm trong dãy hay không. Có 2 toán tử membership trong Python đó là:

1.4 Các lệnh nhập xuất 51

• [biến] in [dãy các biến] • [biến] not in [dãy các biến]

1 2 3 4 5 6 7

>>>list = [1,2,3,4,5,6,7,8,9] >>>a = 1 >>>b = 12 >>>print(a in list) True >>>print(b in list) False

Ví dụ 1.3.25. Toán tử membership.

1.4 Các lệnh nhập xuất

Trong bất kỳ ngôn ngữ lập trình nào, việc nhập giá trị cho các biến và in chúng ra sau khi xử lý có thể được làm theo hai cách:

1. Thông qua phương tiện nhập/xuất chuẩn (I/O: Input/Output). 2. Thông qua những tập tin.

Trong phần này ta sẽ nói về chức năng nhập và xuất cơ bản. Nhập và xuất luôn là các thành phần quan trọng của bất kỳ chương trình nào. Để tạo tính hữu ích, chương trình cần có khả năng nhập dữ liệu vào và hiển thị lại những kết quả của nó. Trong ngôn ngữ lập trình Python, thư viện chuẩn cung cấp những thủ tục cho việc nhập và xuất. Thư viện chuẩn có những hàm quản lý các thao tác nhập/xuất cũng như các thao tác trên ký tự và chuỗi. Trong bài học này, tất cả những hàm nhập dùng để đọc dữ liệu vào từ thiết bị nhập chuẩn và tất cả những hàm xuất dùng để viết kết quả ra thiết bị xuất chuẩn. Thiết bị nhập chuẩn thông thường là bàn phím. Thiết bị xuất chuẩn thông thường là màn hình (Console). Nhập và xuất ra có thể được định hướng đến tập tin hay từ tập tin thay vì thiết bị chuẩn. Những tập tin có thể được lưu trên đĩa hay trên bất cứ thiết bị lưu trữ nào khác. Dữ liệu đầu ra cũng có thể được gửi đến máy in.

Hàm xuất có định dạng print() và hàm nhập có định dạng input(). Những hàm này gọi là những hàm được định dạng vì chúng có thể đọc và in dữ liệu ra theo các định dạng khác nhau được điều khiển bởi người dùng. Bộ định dạng qui định dạng thức mà theo đó giá trị của biến sẽ được nhập vào và in ra.

1.4.1 Xuất dữ liệu ra màn hình

Python hỗ trợ sẵn hàm print() để in dữ liệu ra màn hình. Cú pháp: print(value(s),sep=’’,end=’\n’,file=sys.stdout,flush=false) Trong đó:

• value(s): các giá trị sẽ được chuyển thành chuỗi để in ra màn hình. • sep=’’: tham số tùy chọn, có thể có hoặc không. Xác định dấu phân cách giữa các value muốn in ra trong trường hợp có nhiều value. sep mặc định là ’’.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 52

1 2 3

Input("Day chuoi can thong bao bien") x = input("Nhap chuoi thong bao: ") print(x)

• end=’\n’: tham số tùy chọn, có thể có hoặc không. Xác định ký tự được in ra cuối cùng. end mặc định là ’\n’. • file: tham số tùy chọn, có thể có hoặc không. Xác định đối tượng nhận value để in ra. Mặc định là sys.stdout (được in ra màn hình). • flush: tham số tùy chọn, có thể có hoặc không. Nếu là True thì không lưu value vào bộ nhớ đệm. Nếu là False thì lưu value vào bộ nhớ đệm. Mặc định là False. Giá trị nhập vào của hàm input() mặc định là kiểu xâu, do đó ta cần chuyển kiểu nếu như muốn lưu trữ giá trị nhập vào không phải kiểu chuỗi. Ví dụ:

>>>print("hello world") hello world >>>print("hello \n world") hello world >>>print("hello", end = "world") helloworld >>>print("") >>>print("hello","world", sep = ’*’) hello*world

1 2 3 4 5 6 7 8 9 10

Ví dụ 1.4.1. Xuất chuỗi "Hello World"

x = ("apple", "banana", "cherry") print(x) #Ket qua: (’apple’, ’banana’, ’cherry’)

1 2 3

Ví dụ 1.4.2. In một bộ tuples.

1 2

print("Hello", "how are you?", sep="---") #Ket qua: Hello---how are you?

Ví dụ 1.4.3. In hai chuỗi và chỉ định dấu phân tách.

Lưu ý: Giá trị nhập vào từ hàm input() luôn là mặc định kiểu xâu, vì vậy nếu trong trường hợp chúng ta muốn chuyển kiểu xâu sang kiểu khác ví dụ kiểu nguyên thì chúng ta sẽ phải ép kiểu. Ví dụ: Chúng ta muốn chuyển chuỗi "123" về dạng số 12 thì dùng hàm int("123"). Trường hợp trên thường xảy ra khi ta thực hiện phép tính toán.

Các ký tự điều khiển không in được (Escape sequence): Chuỗi trong Python cũng sử dụng các ký tự điều khiển tương tự như trong C. Escape character là một số ký tự có ý nghĩa đặc biệt nếu xuất hiện trong xâu. Mỗi escape character là một ký tự. Mỗi ký tự này có thể được biểu diễn ở dạng dấu xược quen thuộc (backslash notation) hoặc ở dạng mã hex.

Ví dụ 1.4.4. Xuất các ký tự điều khiển không in được.

1.4 Các lệnh nhập xuất 53

Bảng 1.14: Các ký tự điều khiển không in được

Ký tự điều khiển Mã hexa Ý nghĩa

0x07 0x08 0x09 0x0a 0x0b 0x1b 0x0c 0x0d 0x20

Tiếng chuông Xóa bỏ khoảng trắng phía trước nó. Dấu tab Xuống dòng Vertical tab Escape Khoảng cách trong chuỗi (Formfeed) Carriage return Khoảng cách (Space) Ký hiệu bát phân, trong đó n nằm trong phạm vi 0-7 Ký hiệu hệ 16, trong đó n nằm trong phạm vi 0-9, a-f hoặc A-F

\a \b \t \n \v \e \f \r \s \nnn \xnn

1 2 3 4 5 6

>>> print("Hello\tworld") Hello world >>> print("Hello\nworld") Hello world >>>

Trong cách viết chuỗi, \’ và \” cũng là các escape character biểu diễn cho ký tự ‘ và “. Nếu chúng ta muốn Python bỏ qua tất cả các escape character, ta có thể viết như sau:

1 2

>>> print(r’Hello\nworld’) # dat them r vao truoc gia tri chuoi Hello\nworld

Ví dụ 1.4.5. Sử dụng ký tự để chuyển thành chuỗi thô.

Khi đặt thêm r (hoặc R) vào trước giá trị của chuỗi. Ký tự r (hoặc R) sẽ biến chuỗi thành chuỗi thô (raw string), trong chuỗi thô mọi ký tự đặc biệt như escape character sẽ bị bỏ qua.

Lệnh định dạng (Conversion specifier): Định nghĩa cách thức các mục dữ liệu trong danh sách tham số sẽ được hiển thị. Một lệnh định dạng bắt đầu với một ký hiệu % và theo sau là một mã định dạng tương ứng cho mục dữ liệu. Dấu % được dùng trong hàm printf() để chỉ ra các đặc tả chuyển đổi. Các lệnh định dạng và các mục dữ liệu tương thích nhau theo thứ tự và kiểu từ trái sang phải. Một mã định dạng thì cần thiết cho mọi mục dữ liệu cần in ra.

Chương 1. Giới thiệu ngôn ngữ lập trình Python 54

Bảng 1.15: Các ký tự điều khiển đặc tả định dạng trong Python

Đặc tả Ý nghĩa

| Đặc tả Ý nghĩa

| | | |

Số nguyên cơ số 8 Số nguyên cơ số 16 Biểu diễn số dưới dạng khoa học Số thực

%o %x, %X %e, %E %f

Ký tự Chuỗi ký tự Số nguyên có dấu Số nguyên có dấu Số nguyên không dấu

%c %s %i %d %u

Để định dạng đầu ra dễ nhìn hơn, chúng ta có thể sử dụng phương thức str.format() để định dạng.

1 2 3 4 5 6 7

>>> name, age = ’Dac-Nhuong Le’, 40 >>> greeting = ’Xin chao, %s, %i tuoi’ % (name, age) >>> greeting ’Xin chao, Dac-Nhuong Le, 40 tuoi’ >>> print(’Chao mung, %s, %i years old’ % (name, age)) Chao mung, Dac-Nhuong Le, 40 tuoi >>>

Ví dụ 1.4.6. Sử dụng chuỗi định dạng trong Python.

Lưu ý các biến phải đặt trong cặp dấu () và phân tách nhau bởi dấu phẩy. Danh sách biến (thực chất là một biến kiểu tuple) phân tách với chuỗi bằng ký tự % – phép toán định dạng chuỗi của Python. Thứ tự biến trong tuple phải giống với thứ tự nó xuất hiện trong chuỗi. Trong ví dụ trên, nếu thay đổi thứ tự name và age sẽ gây lỗi.

Khi sử dụng hàm format chúng ta tạo ra các placeholder trong chuỗi với số thứ tự (tính từ 0). Biến với số thứ tự tương ứng từ phương thức format sẽ được đặt vào thay cho placeholder để tạo thành chuỗi hoàn chỉnh. Cách viết này tiện lợi hơn so với sử dụng phép toán định dạng %. Khi đó, chúng ta không cần nhớ các ký tự định dạng nữa.

1 2 3

>>> name, age = ’Dac-Nhuong Le’, 40 >>> print(f’Xin chao, {name}. Tuoi cua ban la {age}. Phat trien ung dung voi Python!’) Xin chao, Dac-Nhuong Le. Tuoi cua ban la 40. Phat trien ung dung voi Python!

Đây là cách thức tạo chuỗi có định dạng từ Python 2.x. Trong Python 3, chúng ta vẫn có thể dùng được lối viết này. Từ Python 3.6, chúng ta có thể sử dụng một cách viết chuỗi định dạng khác:

Đây là lối viết chuỗi định dạng tiện lợi nhất trong Python. Trong lối viết này chúng ta đặt ký tự f vào đầu chuỗi. Bên trong chuỗi chúng ta có thể sử dụng biến đặt trong cặp {}. Loại chuỗi này được gọi là f-string. Bên trong cặp {} chúng ta có thể sử dụng bất kỳ giá trị hoặc biểu thức nào của Python.

1.4 Các lệnh nhập xuất 55

1.4.2 Nhập dữ liệu từ bàn phím

Python cung cấp sẵn hàm input() để giúp chúng ta nhập dữ liệu cần thiết từ bàn phím cho chương trình. Khi hàm input() thực thi, luồng chương trình sẽ bị dừng lại cho đến khi người dùng nhập ký tự gì đó vào.

x = input() print(x)

1 2

Ví dụ 1.4.7. Nhập ký tự x vào chương trình.

num1 = int(input()) num2 = int(input()) sum = num1 + num2 print(sum) input()

1 2 3 4 5

Ví dụ 1.4.8. Nhập ký tự 2 số nguyên và tính tổng.

Giá trị nhập vào của hàm input() mặc định là kiểu xâu ký tự, chúng ta cần chuyển kiểu nếu như muốn lưu trữ giá trị nhập vào không phải kiểu chuỗi. Nếu chúng ta nhập một số nguyên thì hàm input() vẫn chuyển nó thành một chuỗi. Do đó, chúng ta có thể chuyển đổi sang kiểu dữ liệu số với các hàm được hỗ trợ sẵn trong Python.

x = input("Nhap chuoi thong bao: ") print(x)

1 2

Ví dụ 1.4.9. Nhập ký tự x kèm theo chuỗi thông báo.

value = input("Enter your value:") print(value) print("Type of value is ", type(value)) value = int(value) print("Type of value is ", type(value))

1 2 3 4 5

Ví dụ 1.4.10. Nhập dữ liệu cho biến và in ra kiểu dữ liệu của biến đó.

Enter your value:2 2 Type of value is Type of value is

1 2 3 4

Kết quả in ra màn hình:

Chúng ta có thể kết hợp định dạng dữ liệu và thông báo trong nhập và xuất dữ liệu.

Ví dụ 1.4.11. Kết hợp định dạng dữ liệu và thông báo.

num1 = input(’Nhap so thu nhat: ’) num2 = input(’Nhap so thu hai: ’) sum = int(num1) + int(num2) print(’Tong cua hai so vua nhap la:’, sum) print(’Tong cua {0} va {1} la {2}’.format(num1, num2, sum)) print(’Tong cua {1} va {0} la {2}’.format(num1, num2, sum)) input()

1 2 3 4 5 6 7

Chương 1. Giới thiệu ngôn ngữ lập trình Python 56

1 2 3 4 5

Nhap so thu nhat: 5 Nhap so thu hai: 9 Tong cua hai so vua nhap la: 14.0 Tong cua 5 va 9 la 14.0 Tong cua 9 va 5 la 14.0

Sự khác nhau giữa 3 lệnh print() trong ví dụ khi chạy chương trình là câu lệnh print thứ 2 và 3 có sử dụng định dạng dữ liệu để lồng vào thông báo. Kết quả chạy chương trình:

1.5 Câu hỏi và bài tập

1.5.1 Câu hỏi lý thuyết

1. Nêu đặc điểm của ngôn ngữ lập trình Python? 2. Nêu ưu, nhược điểm của ngôn ngữ lập trình Python? 3. Trình bày các kiểu dữ liệu cơ bản trong Python? 4. Biến là gì? Cú pháp khai báo biến trong Python? Cho ví dụ minh họa. 5. Câu lệnh là gì? Điểm khác biệt giữa câu lệnh trong Python với các ngôn ngữ biên dịch khác như C?

6. Trình bày về biểu thức, toán tử gán và toán tử 2 ngôi trong Python? Cho ví dụ minh họa. 7. Trình bày các toán tử điều kiện và toán tử logic? Cho ví dụ minh họa. 8. Phân biệt thứ tự ưu tiên của các toán tử trong Python khi thực hiện biểu thức. Cho ví dụ minh họa.

9. Trình bày cú pháp xuất dữ liệu ra bàn phím và giải thích các tham số quan trọng? 10. Trình bày cú pháp nhập dữ liệu từ bàn phím? Cho ví dụ minh họa. 11. Phân biệt chú thích và chú thích đối tượng trong Python? Cho ví dụ minh họa. 12. Trình bày ý nghĩa toán tử /, //, %, **, and, or, is. Cho ví dụ minh họa. 13. Phân biệt các phép toán trên kiểu chuỗi trong Python. Cho ví dụ minh họa. 14. Trình bày các loại lỗi khi lập trình và cách bắt lỗi trong Python. 15. Trình bày cách thức thiết lập môi trường lập trình Python với Visual Studio Code.

1.5.2 Câu hỏi trắc nghiệm

1. Ngôn ngữ lập trình Python được Guido Van Rossum phát triển dựa trên ngôn ngữ lập trình nào?

1.5 Câu hỏi và bài tập 57

ABC. (a) Ngôn ngữ A. (b) Ngôn ngữ B. (c) Ngôn ngữ C. (d) Ngôn ngữ 2. Ngôn ngữ lập trình Python được phát hành đầu tiên vào năm nào? (a) 1990. (b) 1991. (c) 1992. (d) 1993.

3. Khẳng định nào sau đây là đúng về Python? (a) Là ngôn ngữ thông dịch cấp cao. (b) Là ngôn ngữ biên dịch cấp cao. (c) Vừa là thông dịch, biên dịch cấp cao. (d) Tất cả các đáp án đều đúng. 4. Khẳng định nào sau đây là không đúng về Python? (a) Python có thể sử dụng trên nhiều hệ điều hành khác nhau: Unix, Windows,Mac OS, Linux,...

(b) Python là một ngôn ngữ không phân biệt kiểu chữ HOA, chữ thường. (c) Python hoàn toàn tạo kiểu động và dùng cơ chế cấp phát bộ nhớ tự động. (d) Python có tốc độ thực hiện chậm hơn nhiều lần so với các ngôn ngữ biên dịch như C, Java,... 5. Các khối code (khối lệnh của hàm, vòng lặp,...) trong Python được xác định bởi

(a) Dấu ngoặc nhọn {}. (b) Canh lề (Tab). (c) Dấu ngoặc đơn (). (d) Dấu ngoặc vuông []. 6. Khẳng định nào là đúng về chú thích trong Python?

(a) Python sử dụng kí tự # để bắt đầu một chú thích (b) Nội dung của chú thích sẽ được trình thông dịch bỏ qua. (c) Python dùng “”” ””” (3 cặp nháy đôi) hoặc ”’ ”’(3 cập nháy đơn) để viết chú thích

trên nhiều dòng. (d) Tất cả các đáp án trên. 7. Phép toán nào có thể được dùng để so sánh hai biến trong Python? (a) == (c) // (d) = (b) ** 8. Phát biểu nào sau đây là đúng?

(a) Câu lệnh của Python phải được kết thúc bằng dấu “;”. (b) Mỗi câu lệnh nên được viết trong một dòng. (c) Mỗi câu lệnh nên được viết trong một dòng và kết thúc bằng dấu “;”. (d) Các câu lệnh nên được viết trong một dòng.

9. Khai báo nào sau đây là chính xác? (b) Pi 3.14 (a) Pi := 3.14 (c) Pi = 3.14 (d) Pi:3.14 10. Biến X = “1” dưới đây sau khi được khai báo thuộc kiểu dữ liệu nào? (a) int (b) float (c) string (d) list 11. Đâu không phải là kiểu dữ liệu trong Python? (a) bool (b) set (c) dictionary (d) pointer 12. Khai báo x = float(1/3), kết quả của x là:

Chương 1. Giới thiệu ngôn ngữ lập trình Python 58

(a) 0 (b) 1 (c) 0.33333333 (d) 1/3 13. Phép toán lấy phần nguyên trong Python là: (a) % (b) // (d) div (c) / 14. Cho biết kết quả của biểu thức sau: 1 + 3/2 ∗ 4 − 1 (a) 4 (c) 6.0 (d) 0.375

(b) 7 15. Cho biết kết quả của biểu thức sau: 1 + int(3/2) ∗ 4 − 1 (b) 7 (a) 4 (d) 0.375 (c) 6.0 16. Viết biêu thức sau trong Python: xy3 − ((x + y)2 − z2)

(c) x*y^2-((x+y)^2-z^2) (d) x*y*y*y-(x+y)*(x+y)-z*z (a) xy3 − ((x + y)2 − z2) (b) x*y**3-((x+y)*(x+y)-z**2) 17. Kết quả của biểu thức 16%5**2 là gì: (a) 2 (c) 16 (d) 0.64 (b) 1 18. Câu lệnh nào sau đây in ra kiểu dữ liệu của biến x? (d) (c) (a) print(type(x)) (b) print(type[x]) print(typeof[x]) print(typeof(x))

19. Câu lệnh nào sau đây được dùng để gán giá trị cho x = 1, y = 2, z = 3 ? (b) x;y;z = 1;2;3 (a) x,y,z = 1;2;3 (c) x,y,z = 1,2,3 (d) x;y;z = 1,2,3 20. Kết quả của câu lệnh print(0b1010) là gì? (a) 10 (b) 0b1010 (d) ’0b1010’

(c) 1010 21. Kết quả của câu lệnh print(type(hex(15))) là gì? (c) 0xf (a) (b) (d) ’0xf’ 22. Kết quả của câu lệnh print(bin(4)) là gì? (a) 100 (b) 0b100 (c) 0o100 (d) 0x100 23. Kết quả của câu lệnh print(float(’ -50\n’)) là gì? (Lưu ý: số lượng khoảng trắng trước số đó là 5)

(a) -50 (b) -50.0 (c) -50.0000000000000000 (16 chữ số) (d) Có xuất hiện lỗi Error 24. Kết quả của câu lệnh print(float(’7e+002’)); print(float(’7e-002’)) là gì?

(a) 700.0; 0.07 (b) 700; 0.07 (c) ’7e+002’; ’7e-002’ (d) 7e+002; 7e-002

25. Kết quả của câu lệnh print(complex(’2+8j’)) là gì? (c) ’2+8j’ (d) (2+8j) (a) Có xuất hiện lỗi Error (b) complex(’2+8j’)

√ a (a) sqr(a) 26. Tính căn bậc hai của a, ta sử dụng câu lệnh nào? (c) (d) math.sqrt(a)

(a) bien-X = 5 (b) _bienX = 5 (b) sqrt(a) 27. Chỉ ra trường hợp không hợp lệ khi đặt tên biến trong Python? (c) bien_X = 5 (d) bienX = 5 28. Qui tắc nào sau đây là đúng khi đặt tên cho biến trong Python?

1.5 Câu hỏi và bài tập 59

(a) Tên biến có thể bắt đầu bằng một chữ số (b) Tên biến có thể chứa dấu gạch dưới "_" (c) Tên biến có thể có các ký hiệu đặc biệt như !, , #, $, %,.. (d) Tên biến có thể trùng với các từ khóa (keyword) 29. Để xuất thông tin ra màn hình ta dùng hàm nào? (a) print() (c) write() (d) put() (b) printf() 30. Để xuất ra màn hình “Hello world” ta sử dụng câu lệnh nào?

(a) string = print(Hello world) (b) print(Hello world) (c) print(string(Hello world)) (d) print(“Hello world”) 31. Kết quả của lệnh print(100, 200, "hello", "world", sep=’:’) là:

1 2 3

a = 16 x = a&1 print(x)

(a) 100:200:hello:world (b) 100200helloworld (c) 100 200 hello world (d) Có xuất hiện lỗi Error 32. Lệnh nào dùng để nhập dữ liệu từ bàn phím trong Python? (a) cin (b) scanf() (c) input() (d) read() 33. Kết quả hiển thị trên màn hình sau khi thực hiện các dòng lệnh sau là:

1 2 3

a = 16 x = a|1 print(x)

(a) 1 (b) 0 (c) 16 (d) 17 34. Kết quả hiển thị trên màn hình sau khi thực hiện các dòng lệnh sau là:

1 2 3

a = 15 x = a>>2 print(x)

(a) 1 (b) 0 (c) 16 (d) 17 35. Kết quả hiển thị trên màn hình sau khi thực hiện các dòng lệnh sau là:

(a) 17 (b) 0 (c) 3 (d) 13 36. Kiểu logic với giá trị sai được viết như thế nào? (a) False (c) true (d) True (b) false 37. Khẳng định nào sau đây là đúng?

(a) Dấu + có độ ưu tiên cao hơn dấu *. (b) Trong một biểu thức, phép toán trong ngoặc () sẽ được thực hiện trước. (c) Phép toán so sánh (>,<,>=,<=) có độ ưu tiên tương đương phép toán (+,-). (d) Pháp toán logic (AND, OR, NOT) được thực hiện trước các pháp toán so sánh. 38. Để nhập từ bàn phím một số nguyên n, ta dùng lệnh nào?

Chương 1. Giới thiệu ngôn ngữ lập trình Python 60

(a) n=int(input(“Nhập số nguyên n:”)). (b) n=input(“Nhập số nguyên n:”). (c) n=(“Nhập số nguyên n:”). (d) input(“Nhập số nguyên n:”). 39. Để in ra màn hình chữ “xin” và “chào” trên cùng một hàng, ta sử dụng lệnh nào?

(a) print(“xin”); print(“chao”) (b) print(“xin”, end = “”); print(“chao”) (c) print(“xin”); print(“chao”, end = “”) (d) print(“xin, chao”) 40. Kết quả của lệnh print(10//3,10%3,10/3,sep=" , ") là:

(a) 3 , 1 , 3.3333333333333335 (b) 1 , 3 , 3.3333333333333335 (c) 3.3333333333333335 , 1 , 3 (d) 3 , 3.3333333333333335 , 1 41. Kết quả của câu lệnh x = input("Enter a number: ") là gì?

(a) Biến x nhận giá trị kiểu int (b) x nhận giá trị kiểu float (c) x nhận giá trị kiểu bool (d) x nhận giá trị kiểu str 42. Câu lệnh nào dùng để in ra nhiều giá trị cách nhau bởi dấu -?

(a) print("a", "b", sep="-") (b) print("a" + "b" + "-") (c) print("a-b", end="") (d) print("a", "b", end="-") 43. Câu lệnh nào sau đây ghi dữ liệu ra file văn bản?

(a) file.read() (b) file.input() (c) file.write("Hello") (d) file.scanf("Hello") 44. Giả sử a = 5, b = 7. Kết quả của print("a =", a, "b =", b) là gì? (a) a =5 b =7 (b) a = 5 b = 7 (c) a=5b=7 (d) a5b7 45. Lệnh nào sau đây đọc số nguyên từ bàn phím?

(a) x = input() (b) x = int(input()) (c) x = str(input()) (d) x = float(input()) 46. Trong Python, để kết thúc câu lệnh print() mà không xuống dòng, ta dùng:

(a) print(..., end=" ") (b) print(..., sep="") (c) print(..., stop="\n") (d) print(..., close=False) 47. Để đọc toàn bộ nội dung từ một file văn bản data.txt, dùng lệnh nào?

(a) open("data.txt", "r").read() (b) input("data.txt") (c) read("data.txt") (d) file.readfile("data.txt") 48. Khi mở file với lệnh open("abc.txt", "w"), điều gì xảy ra nếu file đã tồn tại?

(a) File được giữ nguyên (b) File bị xóa và tạo lại (c) Ghi đè nội dung cũ từ dòng thứ hai (d) Tạo file mới có tên khác

49. Đâu là kết quả của lệnh print("A", "B", "C", sep="*")? (c) ABC (a) A B C (b) ABC (d) A B*C 50. Giả sử người dùng nhập vào chuỗi "12 34", câu lệnh nào sau đây giúp tách hai số và

chuyển thành số nguyên? (a) a, b = input().split() (b) a, b = map(int, input().split()) (c) a = int(input()); b = int(input()) (d) a, b = input().split(",")

1.5 Câu hỏi và bài tập 61

1.5.3 Bài tập thực hành

1. Viết chương trình in ra Hello World! 2. Viết chương trình cho phép nhập vào một chuỗi kí tự và in ra ký tự đó. 3. Viết chương trình nhập vào 2 số và in ra kết quả là tổng của 2 số đó. 4. Viết chương trình nhập vào 2 số là độ dài 2 cạnh của hình chữ nhật và in ra kết quả là chu vi và diện tích hình chữ nhật đó?

5. Viết chương trình nhập vào tên và họ của một người sau đó in ra họ và tên của người đó. 6. Viết chương chình nhập vào 2 số và in ra kết quả cả các phép toán trên bit: and, or, xor 7. Viết chương trình nhập vào 2 số và in ra kết quả là số dư của số thứ nhất chia số thứ 2 8. Viết chương trình nhập vào bán kính và in ra chu vi và diện tích của hình tròn 9. Viết chương trình nhập vào 3 số a,b,c và in màn hình là True nếu a>b>c và False trong trường hợp còn lại

10. Viết chương trình nhập vào một kí tự và một chuỗi kí tự. Tìm trong chuỗi kí tự đó có kí tự nhập vào ban đầu hay không. Nếu có thì in ra màn hình là True, nếu không thì in ra màn hình False.

11. Viết chương trình nhập năm sinh của một người. Tính tuổi người đó. 12. Viết chương trình nhập vào tên và năm sinh của một người. In ra màn hình tên và tuổi của người ấy ở hiện tại. (Gơi ý: sử dụng thư viện datetime để lấy thời gian chuẩn của hiện tại).

13. Viết chương trình nhập vào 2 số a và b. Tính tổng, hiệu, tính và thương của hai số đó. 14. Viết chương trình nhập vào 2 số tự nhiên a, b. in ra màn hình phần nguyên của a chia b. 15. Viết chương trình nhập vào 4 số tự nhiên, a,b,c,d. Nếu a>b và c>d hoặc a

tăng phải trả, biết: tiền = số lượng * đơn giá; thuế giá trị gia tăng = 10% tiền. 17. Viết chương trình nhập vào số xe (gồm 4 chữ số), tính tổng các số trong biển số xe. 18. Viết chương trình nhập vào 2 số nguyên. Tính min và max của hai số đó. 19. Viết chương trình nhập vào số giây bất kỳ t. Tính và xuất ra dạng Giờ:Phút:Giây 20. Viết chương trình nhập vào điểm ba môn Toán, Lý, Hóa của một học sinh. In ra điểm trung bình của sinh viên đó với hai số lẻ thập phân. 21. Viết chương trình tính xy, trong đó x, y là hai số thực với x > 0 bằng cách dùng các hàm toán học thông thường.

22. Giả sử rằng chúng ta có vài địa chỉ email dạng username@companyname.com, hãy viết một chương trình để in username và companyname của địa chỉ email cụ thể. Cả username và companyname chỉ bao gồm chữ cái.

23. Viết hàm để tính 5/0 và sử dụng try/exception để bắt lỗi. 24. Viết chương trình nhập vào một số dưới dạng thập phân, in số ra dưới dạng số nhị phân. 25. Viết chương trình nhập vào một số dưới dạng thập phân, in số ra dưới dạng số thập lục phân.

2. Các cấu trúc điều khiển trong Python

Mục tiêu: Kết thúc chương này, sinh viên có thể:

• Hiểu được cấu trúc câu lệnh if, câu lệnh if...else. • Nắm vững và sử dụng thành thạo các câu lệnh if lồng nhau. • Hiểu được cấu trúc câu lệnh switch. • Nắm vững và sử dụng thành thạo câu lệnh switch. • Phân biệt sự khác nhau giữa câu lệnh if và câu lệnh switch.

Các vấn đề được đề cập từ đầu đến nay cho phép chúng ta viết nhiều chương trình. Tuy nhiên các chương trình đó có nhược điểm là bất cứ khi nào được chạy, chúng luôn thực hiện một chuỗi các thao tác giống nhau, theo cách thức giống nhau. Trong khi đó, chúng ta thường xuyên chỉ cho phép thực hiện các thao tác nhất định nếu nó thỏa mãn điều kiện đặt ra. Các câu lệnh điều kiện cho phép chúng ta thay đổi luồng chương trình. Dựa trên một điều kiện nào đó, một câu lệnh hay một chuỗi các câu lệnh có thể được thực hiện hoặc không. Hầu hết các ngôn ngữ lập trình đều sử dụng lệnh if để đưa ra điều kiện. Nguyên tắc thực hiện như sau nếu điều kiện đưa ra là đúng (True), chương trình sẽ thực hiện một công việc nào đó, nếu điều kiện đưa ra là sai (False), chương trình sẽ thực hiện một công việc khác. Trong Python một điều kiện được coi là đúng (True) khi nó có giá trị khác 0, là sai (False) khi nó có giá trị bằng 0.

Chương 2. Các cấu trúc điều khiển trong Python 64

2.1 Câu lệnh điều kiện và rẽ nhánh

2.1.1 Câu lệnh điều kiện if

Một chương trình bao gồm nhiều câu lệnh, thông thường các câu lệnh được thực hiện một cách lần lượt theo thứ tự mà chúng được viết ra. Các cấu trúc điều khiển cho phép thay đổi trật tự nói trên, do đó máy có thể nhảy thực hiện một câu lệnh khác ở một ví trí trước hoặc sau câu lệnh hiện thời. Câu lệnh if cho phép ta đưa ra các quyết định dựa trên việc kiểm tra một điều kiện nào đó là đúng (True) hay sai (False) như sau:

Hình 2.1: Câu lệnh if

if (condition):

// khoi lenh nay thuc thi // neu condition = true

1 2 3

Cú pháp:

Mệnh đề theo sau từ khoá if là một điều kiện hoặc một biểu thức điều kiện (Condition) cần được kiểm tra. Tiếp đến là một lệnh hay một tập các lệnh sẽ được thực thi khi điều kiện (hoặc biểu thức điều kiện) có kết quả True.

age = 20; if (age > 18):

1 2 3

print ("Tuoi lon hon 18");

Ví dụ 2.1.1. Kiểm tra tuổi của một người.

Kết quả: Tuoi lon hon 18

x = 1 y = 2 if x==1:

print("x = 1")

if y==1:

1 2 3 4 5 6

print("y = 1")

Ví dụ 2.1.2. Kiểm tra xem x có bằng 1 không?

Kết quả hiện lên trên màn hình: x = 1

2.1 Câu lệnh điều kiện và rẽ nhánh 65

2.1.2 Biểu thức if-else

Ở trên chúng ta đã biết dạng đơn giản nhất của câu lệnh if, cho phép ta lựa chọn để thực hiện hay không một câu lệnh hoặc một chuỗi các lệnh. Python cũng cho phép ta lựa chọn trong hai khối lệnh để thực hiện bằng cách dùng cấu trúc if-else.

Hình 2.2: Câu lệnh if-else

if (condition):

// khoi lenh nay duoc thuc thi // neu condition = True

else:

// khoi lenh nay duoc thuc thi // neu condition = False

1 2 3 4 5 6

Cú pháp:

Lệnh if-else cũng kiểm tra giá trị dạng boolean của điều kiện. Nếu giá trị điều kiện là True thì chỉ có khối lệnh sau if sẽ được thực hiện, nếu là False thì chỉ có khối lệnh sau else được thực hiện.

a = int(input("Nhap so a = ")) if a%2==0:

print("a la so chan")

else:

print("a la so le")

1 2 3 4 5

Ví dụ 2.1.3. Kiểm tra tính chẵn lẻ của số nguyên a nhập từ bàn phím.

a = int(input("Nhap so a = ")) b = int(input("Nhap so b = ")) if a > b:

print("a la so lon nhat")

else:

print("b la so lon nhat")

1 2 3 4 5 6

Ví dụ 2.1.4. Viết chương trình kiểm tra số lớn nhất từ hai số a và b.

Chương 2. Các cấu trúc điều khiển trong Python 66

2.1.3 Biểu thức If-elif-else

Lệnh if-elif-else cũng kiểm tra giá trị dạng boolean của điều kiện. Nếu giá trị điều kiện if là True thì chỉ có khối lệnh sau if sẽ được thực hiện. Nếu giá trị điều kiện if else nào là True thì chỉ có khối lệnh sau else if đó sẽ được thực hiện... Nếu tất cả điều kiện của if và else if là False thì chỉ có khối lệnh sau else sẽ được thực hiện.

Hình 2.3: Câu lệnh if-elif-else

if (condition1):

// khoi lenh nay duoc thuc thi neu condition1 la true

elif (condition2):

// khoi lenh nay duoc thuc thi neu condition2 la true

elif (condition3):

// khoi lenh nay duoc thuc thi neu condition3 la true

... else:

// khoi lenh nay duoc thuc thi neu tat ca nhung dieu kien tren la false

1 2 3 4 5 6 7 8 9

Cú pháp:

if d < 0:

print("Phuong trinh vo nghiem")

elif d == 0:

print("Phuong trinh co 1 nghiem: ",-b/2*a)

else:

x1 = (-b - sqrt(d))/(2*a) x2 = (-b + sqrt(d))/(2*a) print("Phuong trinh co 2 nghiem: ",x1,x2)

1 2 3 4 5 6 7 8

Ví dụ 2.1.5. Giải phương trình bậc 2.

2.1 Câu lệnh điều kiện và rẽ nhánh 67

marks = 65;

if (marks < 50):

print("Truot!");

elif (marks >= 50 and marks < 60):

print("Xep loai D");

elif (marks >= 60 and marks < 70):

print("Xep loai C");

elif (marks >= 70 and marks < 80):

print("Xep loai B");

elif (marks >= 80 and marks < 90):

print("Xep loai A");

elif (marks >= 90 and marks < 100):

print("Xep loai A+");

else:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

print("Gia tri khong hop le!");

Ví dụ 2.1.6. Xếp loại dựa trên điểm sinh viên.

Kết quả: Xep loai C

2.1.4 Câu lệnh pass

1

pass

Câu lệnh pass trong Python được sử dụng để dành chỗ lập trình và xem là một lệnh trống. Trong trường hợp, chúng ta biết chỗ đó phải viết rất nhiều lệnh nhưng tại thời điểm hiện tại chưa kịp làm. Chúng ta sẽ dùng pass để đánh dấu vị trí đó, lệnh pass không làm gì cả, nó chỉ giữ chỗ cho các hàm, vòng lặp đã thêm vào, nhưng chưa dùng đến trong hiện tại mà để mở rộng trong tương lai. Cấu trúc của lệnh pass:

Chúng ta thường sử dụng lệnh này như một placeholder. Giả sử, chúng ta có một vòng lặp, hoặc một hàm, nhưng chưa biết nên xây dựng nó như thế nào, chưa biết nên code sao cho tối ưu và muốn để lại làm sau. Nhưng hàm, lệnh đó không thể có một khối lệnh rỗng, trình biên dịch sẽ báo lỗi, vì thế, chỉ cần sử dụng lệnh pass để xây dựng một khối lệnh rỗng, lúc này trình biên dịch sẽ hiểu và không "phàn nàn" gì nữa.

a = 50 b = 100

if b < a:

pass

else:

1 2 3 4 5 6 7

print("b lon hon a")

Ví dụ 2.1.7. Kiểm tra 2 số a và b với giá trị tương ứng là a = 50 và b = 100, nếu a > b thì để xử lý sau, còn nếu ngược lại thì in dòng chữ "b lớn hơn a".

Chương 2. Các cấu trúc điều khiển trong Python 68

Ở ví dụ trên, kết quả đầu ra sẽ là dòng chữ b lớn hơn a. Nếu ta tráo đổi giá trị 2 số a, b: a = 100 và b = 50 thì kết quả đầu ra sẽ không có gì cả (do câu lệnh pass được thực hiện mà không báo lỗi.

a = float(input("Nhap he so a = ")) b = float(input("Nhap he so a = ")) if a == 0: pass

else

1 2 3 4 5 6 7 8

x=-b/a print({"{0}x + {1} = 0"}.format(a,b)) print("Phuong trinh co nghiem x=",x)

Ví dụ 2.1.8. Giải phương trình ax + b = 0 bỏ qua trường hợp a = 0.

Ngoài ra, Python cũng sử dụng từ khóa pass để tạo ra một dummy suite (suite không làm gì cả) để phù hợp với cú pháp của ngôn ngữ. Như vậy, chúng ta vẫn có thể giữ được mệnh đề else nhưng nó sẽ không làm gì hết. Câu lệnh pass được tạo ra chỉ đơn thuần là để đáp ứng yêu cầu cú pháp của Python là mỗi mệnh đề phải có đủ phần tiêu đề (header) và và nội dung (suite). Từ khóa pass đóng vai trò là một suite hình thức (không làm gì hết).

Đối với cấu trúc điều khiển if, từ khóa pass có vẻ không mang nhiều ý nghĩa. Tuy nhiên, trong cấu trúc xử lý ngoại lệ chúng ta sẽ thấy sự cần thiết của câu lệnh này. Từ khóa pass không phải là đặc thù của cấu trúc if-elif-else mà là từ khóa xuất phát từ cấu trúc chung của các lệnh phức hợp trong Python.

2.1.5 Sử dụng if/else như phép gán

Đôi khi việc thực hiện if/else trong một biểu thức quá đơn giản sẽ làm cho if/else phức tạp không cần thiết:

Hình 2.4: Sử dụng if/else như phép gán

1

if else

Cú pháp:

a = 6 b = 8 if a!=b:

c = 168

else

c = 468

1 2 3 4 5 6 7

print(c)

Ví dụ 2.1.9. Sử dụng if/else như phép gán.

2.1 Câu lệnh điều kiện và rẽ nhánh 69

2.1.6 So sánh số thực trong Python

Khi ta thao tác với số thực, cần lưu ý một số rắc rối ở chỗ sai số, nên chúng ta cần có một ngưỡng sai số cho phép (tùy thuộc vào quyết định của người dùng).

d1 = 1.11 - 1.10 d2 = 2.11 - 2.10 print("d1=", d1," d1=", d2) if d1==d2:

print("d1 va d2 bang nhau")

else:

print("d1 va d2 khac nhau")

1 2 3 4 5 6 7

Ví dụ 2.1.10. So sánh số thực trong Python.

Nếu mắt thường quan sát ta tưởng rằng d1 bằng d2 vì 1.11-1.10 = 0.01 và 2.11-2.10 = 0.01. Nhưng thực ra số thực nó có sai số, nó không phải 100% là 0.01, lúc này d1 = 0.010000000000000009 và d2 = 0.009999999999999787 do đó d1 và d2 khác nhau. Vì vậy, chúng ta cần chọn một ngưỡng so sánh theo sai số cho phép

d1 = 1.11 - 1.10 d2 = 2.11 - 2.10 print("d1=", d1," d1=", d2) saiso = d1 - d2 if saiso<0:

saiso = - saiso if saiso<0.0000001:

print("Giong nhau")

else:

1 2 3 4 5 6 7 8 9 10

print("Khac nhau")

Ví dụ 2.1.11. Chọn ngưỡng so sánh số thực trong Python.

2.1.7 Cấu trúc if lồng nhau

if bieu_thuc1: cac_lenh if bieu_thuc2: cac_lenh

elif bieu_thuc3:

cac_lenh

else

1 2 3 4 5 6 7 8

cac_lenh

Đôi khi có một tình huống là khi chúng ta muốn kiểm tra thêm một điều kiện khác sau khi một điều kiện đã được ước lượng là true. Khi đó, chúng ta có thể sử dụng các lệnh if lồng nhau trong Python. Trong cấu trúc các lệnh if lồng nhau, chúng ta có thể có cấu trúc if...elif...else bên trong cấu trúc if...elif...else khác. Cú pháp của cấu trúc lồng các lệnh if như sau:

elif bieu_thuc4:

cac_lenh

else:

9 10 11 12

cac_lenh

Chương 2. Các cấu trúc điều khiển trong Python 70

var = 100 if var < 200:

print "Gia tri bieu thuc la nho hon 200" if var == 150:

print "Do la 150"

elif var == 100:

print "Do la 100"

elif var == 50:

print "Do la 50"

elif var < 50:

print "Gia tri bieu thuc la nho hon 50"

else:

print "Khong tim thay bieu thuc true"

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

print "Good bye!"

Ví dụ 2.1.12. Sử dụng cấu trúc các lệnh if lồng nhau trong Python.

2.2 Các cấu trúc lặp

2.2.1 Cấu trúc lặp while

Vòng lặp while trong Python được sử dụng để lặp một phần của chương trình một vài lần. Nếu số lần lặp không được xác định trước thì vòng lặp lặp while được khuyến khích sử dụng trong trường hợp này.

Hình 2.5: Câu lệnh while

while(condition):

1 2

// Khoi lenh duoc lap lai cho den khi condition = False

Có thể block sẽ không được thực hiện lần nào nếu condition là False ngày từ đầu. Chúng ta có thể kết thúc vòng while bằng cách đưa condition về False hoặc dùng từ khóa break để thoát. Cú pháp:

2.2 Các cấu trúc lặp 71

i = 1; while (i <= 10): print(i); i+=1;

1 2 3 4

Ví dụ 2.2.1. Vòng lặp while in ra các số từ 1 đến 10 trong python.

i = - 1; while i < 1) and i > 10:

1 2 3 4

i = int(intput("Nhap gia tri tu [1..10]:")) print("Gia tri binh phuong nhap vao la: ", pow(i,2))

Ví dụ 2.2.2. Viết chương trình yêu cầu nhập vào một số nguyên dương [1..10], nếu nhập sai yêu cầu nhập lại. Khi nhập đúng thì xuất ra bình phương của giá trị mới nhập vào.

Vòng lặp while vô tận: Nếu để điều kiện lặp là True thì vòng lặp while sẽ chạy đến vô tận... Đến khi chúng ta stop chương trình đối với mỗi IDE (Eclipse, Netbean...) hoặc bấm Ctrl+C khi chạy bằng command.

while (1==1):

1 2

print("Vong lap while vo tan...");

Ví dụ 2.2.3. Vòng lặp while vô tận trong python.

2.2.2 Cấu trúc lặp for

Vòng lặp for trong python được sử dụng để lặp một biến qua một dãy (List hoặc String) theo thứ tự mà chúng xuất hiện. Vòng lặp for trong python được sử dụng để lặp một phần của chương trình nhiều lần. Nếu số lần lặp là cố định thì vong lặp for được khuyến khích sử dụng, còn nếu số lần lặp không cố định thì nên sử dụng vòng lặp while.

Hình 2.6: Cấu trúc lặp for

Cú pháp:

for bien_vong_lap in day_sequense::

1 2

// khoi lenh

Chương 2. Các cấu trúc điều khiển trong Python 72

Nếu một mảng day_sequense gồm một danh sách các biểu thức, nó được ước lượng đầu tiên. Sau đó, item đầu tiên trong mảng được gán cho biến vòng lặp bien_vong_lap. Tiếp theo, các khối lệnh bên trong vòng lặp được thực thi và khối lệnh này được thực thi tới khi mảng này đã được lặp xong. Dưới đây là ví dụ minh họa vòng lặp for trong Python:

for letter in "Python":

print ("Chu cai hien tai:", letter);

1 2

Ví dụ 2.2.4. Vòng lặp for với kiểu chuỗi.

Chu cai hien tai: P Chu cai hien tai: y Chu cai hien tai: t Chu cai hien tai: h Chu cai hien tai: o Chu cai hien tai: n

1 2 3 4 5 6

Kết quả:

fruits = [’chuoi’, ’tao’, ’xoai’] for fruit in fruits:

print ("Ban co thich an:", fruit);

1 2 3

Ví dụ 2.2.5. Vòng lặp for với kiểu mảng.

Ban co thich an: chuoi Ban co thich an: tao Ban co thich an: xoai

1 2 3

Kết quả:

Lặp qua index của mảng: Một cách khác để lặp qua mỗi item là bởi chỉ mục index bên trong mảng đó. Chúng ta theo dõi ví dụ đơn giản sau:

# Vi du lap mot mang fruits = [’chuoi’, ’tao’, ’xoai’] for index in range(len(fruits)):

print ("Ban co thich an:", fruits[index]);

1 2 3 4

Ví dụ 2.2.6. Vòng lặp for với index.

Ban co thich an: chuoi Ban co thich an: tao Ban co thich an: xoai

1 2 3

Kết quả:

Ở đây, chúng ta sử dụng hàm len() có sẵn trong Python để cung cấp tổng số phần tử trong tuple cũng như hàm range() để cung cấp cho chúng ta dãy thực sự để lặp qua đó.

2.2 Các cấu trúc lặp 73

2.2.3 Câu lệnh break và continue

Lệnh break là từ khóa đặc biệt dùng để thoát khỏi vòng lặp chứa nó trực tiếp khi đạt được mức yêu cầu nào đó. Gặp lệnh break, chương trình sẽ không thực hiện bất cứ lệnh nào bên dưới nó, mà thoát luôn khỏi vòng lặp. Chúng ta có thể sử dụng lệnh break để thoát khỏi vòng lặp khi một điều kiện cụ thể được đáp ứng (True), do đó lệnh break thường đi kèm với câu lệnh if.

Hình 2.7: Cấu trúc lệnh break

while dieu_kien_kiem_tra:

#code ben trong vong lap while: if dieu_kien:

break

#code khac ben trong vong lap while

#code ben ngoai vong lap while

1 2 3 4 5 6

Cách sử dụng break trong vòng lặp while Python sẽ như sau:

#Su dung break trong for for val in "PhattrienungdungvoiPython":

if val == "n": break

print(val) print("Ket thuc!")

1 2 3 4 5 6

Ví dụ 2.2.7. Viết chương trình in ra các ký tự trừ chữ cái "n".

Trong đoạn code trên, chúng ta lặp các kí tự trong chuỗi "PhattrienungdungvoiPython" và kiểm tra điều kiện, nếu chữ cái là "n" thì sẽ thực thi lệnh break, nếu chữ cái khác "n" thì in ra màn hình.

bien = 10 while bien > 0:

print (’Gia tri bien hien tai la: ’, bien) bien = bien -1 if bien == 5:

break

print ("OK!")

1 2 3 4 5 6 7

Ví dụ 2.2.8. Kiểm tra và in biến theo giá trị giảm dần từ 10 đến khi bằng 5 thì kết thúc.

Chương 2. Các cấu trúc điều khiển trong Python 74

Lệnh continue được sử dụng để bỏ qua phần còn lại của code bên trong vòng lặp, áp dụng cho lần lặp hiện tại. Không giống như câu lệnh break, câu lệnh continue sẽ không hoàn toàn dừng vòng lặp mà nó chỉ đơn giản nhảy sang vòng lặp kế tiếp. Câu lệnh continue được sử dụng trong trường hợp chúng ta muốn bỏ qua vòng lặp của mình ở một giá trị điều kiện xác định, sau đó lại tiếp tục lặp tiếp.

Hình 2.8: Cấu trúc lệnh continue

s = 0 for n in rang(1, 16, 2): if n is 3 or n is 11:

continue

s+=n

1 2 3 4 5 6

print("Tong la s = ",s)

Ví dụ 2.2.9. Tính tổng các chữ số lẻ từ 1 đến 15, ngoại trừ số 3 và số 11.

Nhìn chung, lệnh break và continue trong Python được dùng để bỏ qua các phần của loop và break hiện tại ra khỏi vòng lặp hoàn toàn. • Lệnh break có thể được dùng nếu chúng ta cần thoát ra khỏi vòng lặp for hoặc while và chuyển tới phần code tiếp theo. • Lệnh continue có thể được dùng nếu chúng ta cần bỏ qua biến lặp hiện tại của for hoặc while và di chuyển vào vòng lặp tiếp theo.

2.2.4.1 Sử dụng lệnh else trong vòng lặp while

2.2.4 Cấu trúc while/else và for/else

while condition: while-block

else:

1 2 3 4

else-block

Python cho phép có một lệnh else để liên hợp với một lệnh vòng lặp. Nếu câu lệnh else được sử dụng với vòng lặp while, câu lệnh else được thực thi khi điều kiện là False. Python hỗ trợ else block trong trường hợp while kết thúc một cách bình thường (tức là không phải dùng break để kết thúc). Cú pháp:

2.3 Các kỹ thuật vòng lặp trong Python 75

count = 1 while count < 6:

print ("%d nho hon 5" %count); count = count + 1;

else:

print ("%d khong nho hon 5" %count);

1 2 3 4 5 6

2.2.4.2 Sử dụng lệnh else trong vòng lặp for

Ví dụ 2.2.10. Sử dụng while/else.

Python cho phép có một lệnh else để liên hợp với một lệnh vòng lặp for. Nếu câu lệnh else được sử dụng với vòng lặp for, thì câu lệnh else được thực thi khi vòng lặp kết thúc.

for num in range(10, 21): #lap num tu 10 toi 20

for i in range(2, num): #lap i tu 2 toi num - 1

if num % i == 0: #num co chia het cho i hay khong

print ("%d khong phai la so nguyen to." %(num)); break; # thoat vong lap for hien tai

else: # else la mot phan cua vong lap for print ("%d la so nguyen to" %(num));

1 2 3 4 5 6 7

Ví dụ 2.2.11. Kiểm tra các số từ 10 đến 20 xem có phải là số nguyên tố hay không?

1 2 3 4 5 6 7 8 9 10 11

10 khong phai la so nguyen to. 11 la so nguyen to 12 khong phai la so nguyen to. 13 la so nguyen to 14 khong phai la so nguyen to. 15 khong phai la so nguyen to. 16 khong phai la so nguyen to. 17 la so nguyen to 18 khong phai la so nguyen to. 19 la so nguyen to 20 khong phai la so nguyen to.

Kết quả:

2.3 Các kỹ thuật vòng lặp trong Python

2.3.1 Vòng lặp Python với điều kiện ở đầu

Đây là dạng lặp thông thường, không có lệnh break xuất hiện. Điều kiện của vòng lặp while sẽ xuất hiện ở đầu và vòng lặp kết thúc khi điều kiện này False.

# Dung lenh sau neu muon nguoi dung nhap so n = int(input("Nhap so n: "))

# Khoi tao tong tong va bien dem i

1 2 3 4

Ví dụ 2.3.1. Vòng lặp với điều kiện ở đầu:.

tong = 0 i = 1

while i <= n:

tong = tong + i i = i+1 # cap nhat so dem

print("Tong cac so tu 1 den ",n, " la", tong)

5 6 7 8 9 10 11

Chương 2. Các cấu trúc điều khiển trong Python 76

2.3.2 Vòng lặp Python với điều kiện ở giữa

Loại vòng lặp này có thể được thực hiện bằng cách sử dụng một vòng lặp vô hạn kết hợp với lệnh break trong khối lệnh của vòng lặp.

nguyenAm = "aeiouAEIOU"

# vong lap vo han while True:

m = input("Nhap mot nguyen am: ") # Dieu kien o giua khoi lenh if m in nguyenAm:

break

print("Day khong phai la nguyen am. Hay thu lai!")

print("Chuan roi, cam on ban!")

1 2 3 4 5 6 7 8 9 10

Ví dụ 2.3.2. Nhập dữ liệu đầu vào từ người dùng cho đến khi nhập một nguyên âm.

Chương trình trên yêu cầu người dùng nhập vào một nguyên âm, đi kèm với lệnh kiểm tra để buộc người dùng nhập cho đến khi đúng thì thôi. Chừng nào dữ liệu người dùng nhập vào không phải là nguyên âm chừng đó vòng lặp còn tiếp tục.

2.3.3 Vòng lặp Python với điều kiện ở cuối

Loại vòng lặp này đảm bảo rằng khối lệnh được thực thi ít nhất một lần. Nó có thể được thực hiện bằng cách sử dụng một vòng lặp vô hạn cùng với lệnh break ở cuối. Điều này khá giống với vòng lặp do...while trong C.

import random while True:

input("Nhan Enter de tung xuc xac")

# nhan so mat xuc xac bat ky tu 1 den 6 num = random.randint(1,6) print("Ban tung duoc mat",num) option = input("Ban co muon tung lai khong?(y/n) ")

# dieu kien if option == ’n’:

break

1 2 3 4 5 6 7 8 9 10 11 12

Ví dụ 2.3.3. Tung xúc xắc cho đến khi người dùng chọn thoát.

2.3 Các kỹ thuật vòng lặp trong Python 77

Ngôn ngữ lập trình Python cho phép chúng ta sử dụng một vòng lặp bên trong một vòng lặp khác hay còn gọi là vòng lặp lòng nhau trong python.

2.3.4 Vòng lặp while lồng nhau

while(condition1):

while(condition2):

// Khoi lenh duoc lap lai cho den khi condition2 = False

// Khoi lenh duoc lap lai cho den khi condition1 = False

1 2 3 4

Cú pháp lồng vòng lặp while trong Python:

i = 2 while(i < 100):

j = 2 while(j <= (i/j)):

if not(i%j): break j = j + 1

if (j > i/j) : print i, " la so nguyen to" i = i + 1

1 2 3 4 5 6 7 8 9

print "Good bye!"

Ví dụ 2.3.4. Sử dụng lồng vòng lặp để tìm số nguyên tố từ 2 tới 100.

2.3.5 Vòng lặp for lồng nhau

for bien_vong_lap_1 in day_seq_1:

for bien_vong_lap_2 in day_seq_2:

// khoi lenh

1 2 3 4

// khoi lenh

Cú pháp lồng vòng lặp for trong Python:

n=int(input("Nhap chieu cao: ")) for i in range(n):

for j in range(n):

if j==0 or i==j or j==n-1: print("*", end=’’)

else:

print(" ", end=’’)

1 2 3 4 5 6 7 8

print()

Ví dụ 2.3.5. In chữ cái N theo chiều cao tùy biến.

for num in range(2, 101): #lap tu 2 toi 100

for i in range(2, int(num / 2) + 1): #lap tu 2 toi num / 2 if num % i == 0: #num co chia het cho i hay khong

1 2 3 4

break; #thoat vong lap for thu 2

Ví dụ 2.3.6. Tìm các số nguyên tố nhỏ hơn 100.

#khoi lenh else khong duoc thuc thi

else: #else duoc thuc thi khi vong lap for thu 2 ket thuc va khong break

print ("%d la so nguyen to" %(num));

5 6 7

Chương 2. Các cấu trúc điều khiển trong Python 78

2.4 Một số lưu ý khi sử dụng các cấu trúc điều khiển

j=[] #Tao mot danh sach rong de luu ket qua #Duyet qua tat ca cac so trong doan tu 2000 den 3200 for i in range(2000, 3201):

#Kiem tra xem so i co chia het cho 7 va khong phai la boi so cua 5 khong

if (i%7==0) and (i%5!=0):

j.append(str(i)) #Neu dung, thi them so i vao danh sach result #In ra man hinh danh sach result, cac phan tu cach nhau bang dau phay print (’,’.join(j))

1 2 3 4 5 6 7 8

Ví dụ 2.4.1. Viết chương trình tìm tất cả các số chia hết cho 7 nhưng không phải bội số của 5, nằm trong đoạn 2000 và 3200 (tính cả 2000 và 3200). Các số thu được sẽ được in thành chuỗi trên một dòng, cách nhau bằng dấu phẩy..

x=int(input("Nhap so can tinh giai thua:")) def fact(x):

if x == 0:

return 1

return x * fact(x - 1)

print (fact(x))

1 2 3 4 5 6

Ví dụ 2.4.2. Viết một chương trình có thể tính giai thừa của một số cho trước. Kết quả được in thành chuỗi trên một dòng, phân tách bởi dấu phẩy. Ví dụ, số cho trước là 8 thì kết quả đầu ra phải là 40320.

n=int(input("Nhap vao mot so:")) d=dict() for i in range(1,n+1):

d[i]=i*i

print (d)

1 2 3 4 5

Ví dụ 2.4.3. Với số nguyên n nhất định, hãy viết chương trình để tạo ra một dictionary chứa (i, i*i) như là số nguyên từ 1 đến n (bao gồm cả 1 và n) sau đó in ra dictionary này. Giả sử số n là 8 thì đầu ra sẽ là: 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64.

(cid:113) 2∗C∗D H

#!/usr/bin/env python import math c=50

1 2 3

Ví dụ 2.4.4. Viết chương trình và in giá trị theo công thức cho trước Q = với giá trị cố định của C là 50, H là 30. D là dãy giá trị tùy biến, được nhập vào từ giao diện người dùng, các giá trị của D được phân cách bằng dấu phẩy.

h=30 value = [] items=[x for x in input("Nhap gia tri cua d: ").split(’,’)] for d in items:

value.append(str(int(round(math.sqrt(2*c*float(d)/h)))))

print (’,’.join(value))

4 5 6 7 8 9

2.5 Câu hỏi và bài tập 79

input_str = input("Nhap X, Y: ") dimensions=[int(x) for x in input_str.split(’,’)] rowNum=dimensions[0] colNum=dimensions[1] multilist = [[0 for col in range(colNum)] for row in range(rowNum)] for row in range(rowNum):

for col in range(colNum):

multilist[row][col]= row*col

print (multilist)

1 2 3 4 5 6 7 8 9

Ví dụ 2.4.5. Viết một chương trình có 2 chữ số, X, Y nhận giá trị từ đầu vào và tạo ra một mảng 2 chiều. Giá trị phần tử trong hàng thứ i và cột thứ j của mảng phải là i*j. Lưu ý: i = 0, 1, ..., X − 1 và j = 0, 1, ...,Y − 1. Ví dụ: Giá trị X, Y nhập vào là 3,5 thì đầu ra là: [[0, 0, 0, 0, 0], [0, 1, 2, 3, 4], [0, 2, 4, 6, 8]]

2.5 Câu hỏi và bài tập

2.5.1 Câu hỏi

1. Nêu chức năng và cú pháp biểu thức điều kiện if? Lấy ví dụ minh họa. 2. Nêu chức năng và cú pháp biểu thức điều kiện if-else? Lấy ví dụ minh họa. 3. Nêu chức năng và cú pháp biểu thức điều kiện if-elif-else? Lấy ví dụ minh họa. 4. Khi nào sử dụng lệnh if lồng nhau? 5. Trình bày ý nghĩa và cấu trúc lệnh pass? 6. Nêu cú pháp và giải thích cấu trúc lặp while? Lấy ví dụ minh họa. 7. Nêu cú pháp và giải thích cấu trúc lặp for? Lấy ví dụ minh họa. 8. Trình bày ý nghĩa và cấu trúc lệnh break trong vòng lặp? Lấy ví dụ minh họa. 9. Trình bày ý nghĩa và cấu trúc lệnh continue? Lấy ví dụ minh họa. 10. Trình bày cấu trúc và ý nghĩa của while/else? Lấy ví dụ minh họa. 11. Trình bày cấu trúc và ý nghĩa của for/else? 12. Nêu đặc điểm kỹ thuật vòng lặp Python với điều kiện ở đầu? Lấy ví dụ minh họa? 13. Nêu đặc điểm kỹ thuật vòng lặp Python với điều kiện ở giữa? Lấy ví dụ minh họa? 14. Nêu đặc điểm kỹ thuật vòng lặp Python với điều kiện ở cuối? Lấy ví dụ minh họa? 15. Giải thích cấu trúc vòng lặp while lồng nhau, vòng lặp for lồng nhau? Phân biệt các trường hợp sử dụng khác nhau.

Chương 2. Các cấu trúc điều khiển trong Python 80

2.5.2 Câu hỏi trắc nghiệm

1. Trong cấu trúc rẽ nhánh dạng thiếu câu lệnh được thực hiện khi:

(a) Điều kiện sai. (b) Điều kiện đúng. (c) Điều kiện bằng 0. (d) Điều kiện khác 0. 2. Trong các phát biểu sau, phát biểu nào sử dụng câu lệnh rẽ nhánh dạng thiếu?

(a) a là số chẵn. (b) Điều kiện cần để a là số chẵn là a chia hết cho 2. (c) a là số chẵn khi a chia hết cho 2. (d) Nếu a chia hết cho 2 thì a là số chẵn. 3. Trong các phát biểu sau, phát biểu nào sử dụng câu lệnh rẽ nhánh dạng đủ?

(a) Nếu a chia hết cho 2 thì a là số chẵn, ngược lại a là số lẻ. (b) Số a chia hết cho 2 thì a là số chẵn. (c) a là số chẵn khi a chia hết cho 2. (d) Điều kiện cần để a là số chẵn là a chia hết cho 2. 4. Câu lệnh if trong Python cần kết thúc bằng?

a, b = 5, 10 if a>b: a=a-b else: b=b-a print(a+b)

1 2 3 4

(c) Dấu : (d) Không cần dấu kết thúc. (a) Dấu { (b) Dấu ; 5. Hãy cho biết, đoạn lệnh dưới đây cho kết quả in ra màn hình là gì?

x = 5 if x > 3:

print("A")

else:

print("B")

1 2 3 4 5

(a) 5 (c) 15 (d) 0 (b) 10 6. Kết quả của đoạn mã sau là gì?

x = True, y = z = False if not x or y: print(1) elif not x or not y and z:

print(2)

elif not x or y or not y and x:

1 2 3 4 5 6 7

print(3) else: print(4)

(b) A (c) B (d) A B (a) Không in ra gì 7. Hãy cho biết, đoạn lệnh dưới đây cho kết quả in ra màn hình là gì?

2.5 Câu hỏi và bài tập 81

i = x = 0 while i < 10:

if i % 2 == 0: x += 1

1 2 3 4 5 6

i += 1 print (x)

(a) 1 (b) 2 (d) 4 (c) 3 8. Theo dõi đoạn code dưới đây và chọn đáp án đúng.

(a) 3 (b) 4 (c) 5 (d) 0 9. Để kiểm tra số tự nhiên n khác 0 là số chẵn hay lẻ, câu lệnh nào sau đây là đúng?

(a) if n//2==1: print(’so chan’)else: print(’so le’) (b) if n//2==0: print(’so chan’)else: print(’so le’) (c) if n%2==0: print(’so chan’) else: print(’so le’) (d) if n%2==1: print(’so chan’) else: print(’so le’) 10. Cho câu lệnh x=int(input(‘Nhập x:’)). Viết câu lệnh điều kiện với yêu cầu sau: Nếu x nằm trong khoảng (0;10) thì in ra màn hình TRUE?

(a) if x>0 or x<10: print(’TRUE’) (b) if x>0 and x<10: print(’TRUE’) (c) if (x>0) and (x<10): print(’TRUE’) (d) if x>0 or x<10: print(’TRUE’) 11. Cho câu lệnh x=int(input(‘Nhập x:’)). Viết câu lệnh điều kiện với yêu cầu sau: Nếu x nằm trong đoạn [0;10] thì in ra màn hình TRUE, ngược lại in ra FALSE?

1 2 3

a, b = 1, 2 if a>b: print(a) else: print(b)

(a) if (x>=0) and (x<=10): print(’TRUE’) else: print(’FALSE’) (b) if x>=0 and x<=10 print(’TRUE’) else print(’FALSE’) (c) if (x>0) and (x<10): print(’TRUE’) else: print(’FALSE’) (d) if (x>=0) or (x<=10): print(’TRUE’) else: print(’FALSE’) 12. Hãy cho biết, đoạn lệnh dưới đây cho kết quả in ra màn hình là gì?

1 2 3

x = 10, y = 3, d = 0 if x%y==0: d=x//y

(a) 1 (b) 2 (c) True (d) False 13. Hãy cho biết, đoạn lệnh dưới đây cho kết quả in ra màn hình là gì?

a = 0 for i in range (10 , 14):

1 2 3

a = a + 3

(c) 0 (d) Không xác định. (a) 3 (b) 1 14. Giá trị của a sau khi kết thúc vòng lặp là bao nhiêu?

Chương 2. Các cấu trúc điều khiển trong Python 82

55555 44444 33333 22222 11111 for i in range(5, 0, ____ ): print(str(i) * 5)

1 2 3 4 5 6

(a) 9 (b) 12 (c) 15 (d) 18 15. Điền phần còn thiếu trong đoạn code để được kết quả dưới đây

(a) 0 (b) None (c) 1 (d) -1 16. Câu lệnh nào sau đây đúng khi in ra màn hình các số tự nhiên từ 0..10 trên 1 dòng?

s=0 for i in range(5):

s=s+i

1 2 3

(a) for i in range(0,10,1): print(i,end=’’) (b) for i in range(11): print(i,end=’’) (c) for i in range(0,10): print(i,end=’’) (d) for i in range(10): print(i,end=’’) 17. Cho đoạn chương trình sau, khi thực hiện, giá trị của s bằng bao nhiêu?

s=0 for i in range(1,7,2):

s=s+i

1 2 3

(a) 0 (b) 5 (c) 10 (d) 15 18. Cho đoạn chương trình sau, khi thực hiện, giá trị của s bằng bao nhiêu?

for i in range(1,10,2):

print(i)

1 2

(a) 9 (b) 15 (c) 6 (d) 21 19. Cho đoạn chương trình sau, kho thực hiện màn hình i có các giá trị là?

for i in range(5): print(i,end=’’)

1 2

(c) 1,3,5,7,9,10 (d) 1,3,5,7,10 (a) 1,3,5,7,9 (b) 1,2,3,4,5,6,7,8,9,10 20. Câu lệnh sau cho kết quả là gì?

for i in range(10): if i%2==0:

print(i,end=’’)

1 2 3

(a) 1234 (b) 12345 (c) 01234 (d) 012345 21. Câu lệnh sau cho kết quả là gì?

for i in range(10): if i%2==1:

print(i,end=’’)

1 2 3

(a) 02468 (b) 13579 (c) 2468 (d) 246810 22. Đoạn chương trình sau cho kết quả thực hiện là gì?

2.5 Câu hỏi và bài tập 83

for i in range(1,5): print(i, end=’ ’) if i == 3:

break

1 2 3 4

(a) 02468 (b) 13579 (d) 246810 (c) 1357 23. Cho biết kết quả thực hiện của đoạn chương trình sau:

for i in range(20): if i == 10: break

else:

print(i,end="")

else:

1 2 3 4 5 6 7

print("*")

(a) IndentationError: expected an indented block . (b) 1 2 3 (c) 1 2 3 4 (d) 1 2 24. Kết quả nào là output của đoạn code dưới đây?

for item in "HelloWorld":

if item == "l": continue

1 2 3 4

print(item,end="")

(a) 0123456789* (b) 123456789 (c) 0123456789 (d) 123456789* 25. Kết quả nào là output của đoạn code dưới đây?

string = "my name is x" for i in string:

1 2 3

print (i, end=", ")

(a) HelloWorld (b) HeloWorld (c) HeoWord (d) HeoWorld 26. Kết quả của chương trình được in ra màn hình là?

myList = [1, 6, 3, 4, 5, 5, 1] _max = myList[0] index_max= 0 for i in range(1, len(myList)):

if myList[i] > _max: _max = myList[i] index_max = i

1 2 3 4 5 6 7 8

print(index_max)

(a) m, y, , n, a, m, e, , i, s, , x, (b) m y, , n, a, m, e, , i, s, , x (c) my, name, is, x, (d) Error 27. Cho biết output đoạn chương trình sau là gì?

Chương 2. Các cấu trúc điều khiển trong Python 84

a = [1, 4, 20, 2, 5] x = a[0] for i in a:

1 2 3 4 5 6

if i > x: x = i print(x)

(a) 0 (c) 1 (d) 5 (b) 4 28. Theo dõi đoạn code dưới đây và chọn đáp án đúng nhất?

for i in range (10):

if i == 4:

break

else:

print ( i )

else:

1 2 3 4 5 6 7

print(" Python ")

(a) x là giá trị trung bình của list (b) x là giá trị nhỏ nhất của list (c) x là giá trị lớn nhất của list (d) x là tổng giá trị các số trong list 29. Kết quả của đoạn code dưới đây là gì, biết rằng lệnh break dùng để thoát khỏi vòng lặp đang chứa nó?

1 2 3 4 5

11111 22222 33333 44444 55555

(a) 0 1 2 3 4 (b) 0 1 2 3 Python (c) 0 1 2 3 (d) 0 1 2 3 4 Python 30. Vòng lặp nào trả về kết quả dưới đây?

x = 1 y = "2" z = 3 sum = 0 for i in (x, y, z):

if isinstance(i, int):

sum += i

1 2 3 4 5 6 7 8

print(sum)

(a) for i in range(1, 6): print(i, i, i, i, i) (b) for i in range(1, 5): print(str(i) * 5) (c) for i in range(1, 6): print(str(i) * 5) (d) for i in range(0, 5): print(str(i) * 5) 31. Kết quả của chương trình được in ra màn hình là?

1 2

var = 10 for i in range(10):

(a) 2 (b) 3 (c) 4 (d) 6 32. Giá trị của var là gì sau khi vòng lặp for hoàn thành việc thực thi là?

for j in range(2, 10, 1): if var % 2 == 0: continue var += 1

var+=1

else:

3 4 5 6 7 8 9 10

var+=1 print(var)

2.5 Câu hỏi và bài tập 85

(a) 20 (b) 21 (c) 10 (d) 30 33. Vòng lặp While kết thúc khi nào?

(a) Khi điều kiện được thỏa mãn. (b) Khi đủ số vòng lặp. (c) Khi tìm được Output. (d) Tất cả các phương án. 34. Câu lệnh while nào sau đây là đúng cú pháp?

(c) while x < 10 (d) while x < 10 then (a) while(x < 10) (b) while x < 10: 35. Tính tổng S = 1 + 2 + 3 + . . . + n+ . . . cho đến khi S>109. Điều kiện nào sau đây cho

1 2 3 4

s = 0, i = 1 while i<=5: s=s+1 i=i+1

(c) while S<109: (d) while S!=109: vòng lặp while là đúng? (a) while S>=109: (b) while S =109: 36. Cho đoạn chương trình sau, khi thực hiện đoạn chương trình trên giá trị của s là?

(a) 9 (b) 15 (c) 5 (d) 10 37. Lệnh break dùng để làm gì trong vòng lặp?

(c) Bỏ qua một vòng lặp. (d) Kết thúc chương trình.

for i in range(3):

1 2

print(i, end=" ")

(a) Dừng vòng lặp ngay lập tức. (b) Tạm ngưng vòng lặp. 38. Lệnh continue dùng để: (a) Dừng vòng lặp. (b) Kết thúc chương trình. (c) Bỏ qua phần còn lại, tiếp tục vòng tiếp theo. (d) Lặp lại đoạn mã trước đó. 39. Đoạn mã sau in ra gì?

(a) 0 1 2 (b) 1 2 3 (c) 0 1 2 3 (d) 1 2 40. Câu lệnh range(2, 10, 2) tạo ra:

Chương 2. Các cấu trúc điều khiển trong Python 86

x = 0 while x < 3: x += 1

1 2 3 4

print(x)

(c) [2, 3, ..., 10] (d) [2, 5, 8] (a) [2, 4, 6, 8, 10] (b) [2, 4, 6, 8] 41. Đoạn mã sau in ra gì?

(a) 2 (b) 3 (c) 0 (d) Lỗi 42. Câu lệnh nào sau đây sai cú pháp?

(a) if a == b: (b) while x < 10: (c) for i in range(5): (d) for i to range(5):

for i in range(3): if i == 1:

break print(i)

1 2 3 4

43. Câu lệnh for i in range(5): sẽ lặp bao nhiêu lần? (b) 6 (a) 5 (c) 4 (d) Vô hạn. 44. Đoạn mã sau in ra gì?

for i in range(3): if i == 1:

continue

print(i)

1 2 3 4

(a) 0 (b) 0 1 (c) 1 (d) 0 1 2 45. Đoạn mã lệnh sau in ra gì?

(a) 0 1 2 (b) 1 2 (d) 0 1 (c) 0 2 46. Cú pháp đúng để tạo vòng lặp vô hạn trong Python là: (a) while x > 0: (b) while(True): (c) loop forever: (d) for(i=0;;i++) 47. Câu lệnh if x: trong Python tương đương với? (d) Lỗi cú pháp None: (c) if bool(x): (a) if x == True (b) if x is not 48. Lệnh range(5, 0, -1) tạo ra chuỗi nào?

x = 5 if x % 2 == 0:

print("Even")

else:

1 2 3 4 5

print("Odd")

(c) [5, 3, 1] (d) [5, 4, 3, 2, 1, 0] (a) [5, 4, 3, 2, 1] (b) [0, 1, 2, 3, 4, 5] 49. Đoạn mã lệnh sau in ra gì?

2.5 Câu hỏi và bài tập 87

(a) Odd (b) Even (c) None (d) 5 50. Từ khóa else trong vòng lặp for hoặc while được thực hiện khi nào?

(a) Khi điều kiện không đúng (b) Khi kết thúc lặp mà không gặp break (c) Khi lặp gặp continue (d) Luôn luôn

2.5.3 Bài tập thực hành

1. Viết chương trình nhập một số nguyên bất kỳ, hãy đọc giá trị của số đó nếu có giá trị từ 0 đến 9, ngược lại thông báo không đọc được. 2. Viết chương trình nhập một chữ cái. Nếu là chữ thường thì đổi sang chữ hoa, ngược lại đổi sang chữ thường. 3. Viết chương trình nhập vào 3 số nguyên a, b, c. Hãy tìm số lớn nhất và số nhỏ nhất trong ba số đó. 4. Viết chương trình nhập một số nguyên dương n (n > 0). Hãy cho biết đó có phải là số đối xứng? Ví dụ: 121, 12321. 5. Viết chương trình nhập một số nguyên dương n (n > 0). Hãy cho biết đó có phải là số chính phương? Ví dụ: 4, 9, 16 6. Viết chương trình chấp nhận chuỗi là các dòng được nhập vào, chuyển các dòng này thành chữ in hoa và in ra màn hình.

7. Viết chương trình chấp nhận đầu vào là chuỗi các số nhị phân 4 chữ số, phân tách bởi dấu phẩy, kiểm tra xem chúng có chia hết cho 5 không. Sau đó in các số chia hết cho 5 thành dãy phân tách bởi dấu phẩy. Ví dụ đầu vào là: 0100,0011,1010, 1001 thì đầu ra sẽ là: 1010.

8. Viết chương trình tìm tất cả các số trong đoạn 1000 và 3000 (tính cả 2 số này) sao cho tất cả các chữ số trong số đó là số chẵn. In các số tìm được thành chuỗi cách nhau bởi dấu phẩy, trên một dòng.

9. Viết chương trình chấp nhận đầu vào là một câu, đếm số chữ cái và chữ số trong câu đó. Giả sử đầu vào sau được cấp cho chương trình: hello world! 123 thì đầu ra sẽ là: Số chữ cái là 10 và số chữ số là 3.

10. Viết chương trình nhập vào 3 số a, b, c bất kỳ. Hãy kiểm tra xem ba số đó có thể là độ dài của các cạnh của một tam giác hay không? Thông báo lên màn hình ‘Thoả mãn’ hay ‘Không thoả mãn’ trong từng trường hợp tương ứng.

11. Hãy tìm cách tính xy, trong đó x, y là hai số thực với x > 0 bằng cách dùng các hàm toán học thông thường. Hãy lập chương trình nhập vào 2 số thực x, y rồi tính giá trị của xy.

12. Lập trình tính giá trị của biểu thức: z = ea=sin2(x)−x, với a, x nhập từ bàn phím. 13. Viết chương trình tìm tất cả các số chia hết cho 7 nhưng không phải bội số của 5, nằm trong đoạn 2000 và 3200 (tính cả 2000 và 3200). Các số thu được sẽ được in thành chuỗi trên một dòng, cách nhau bằng dấu phẩy.

Chương 2. Các cấu trúc điều khiển trong Python 88

14. Viết chương trình nhập vào một năm bất kỳ, kiểm tra năm đó có phải năm nhuận hay không?

15. Viết chương trình nhập vào một tháng và năm, cho biết số ngày trong tháng tương ứng. 16. Viết chương trình tính số tiền thực của một tài khoản ngân hàng dựa trên nhật ký giao dịch được nhập vào từ giao diện điều khiển. Định dạng nhật ký được hiển thị như sau: D 100; W 200 (D là tiền gửi, W là tiền rút ra). Giả sử đầu vào được cung cấp là: D 300; D 300; W 200; D 100 thì đầu ra sẽ là: 500.

17. Viết một chương trình chấp nhận đầu vào là một câu, đếm chữ hoa, chữ thường. 18. Viết chương trình phân tích số nguyên dương n thành thừa số nguyên tố. 19. Viết chương trình dùng while liệt kê các số hoàn hảo nhỏ hơn 10000. 20. Viết chương trình sử dụng while, if đổi số thập phân thành số La mã với số thập phân nhập vào từ bàn phím. 21. Viết chương trình nhập từ bàn phím một dãy số. Các số cách nhau bởi dấu phẩy. Tìm và in lên màn hình dãy chứa toàn số lẻ.

22. Viết chương trình chấp nhận đầu vào là một câu, đếm số chữ cái và chữ số trong câu đó. Giả sử đầu vào sau được cấp cho chương trình: hello world! 123 Thì đầu ra sẽ là: Số chữ cái là: 10 Số chữ số là: 3.

23. Viết chương trình chấp nhận đầu vào là một câu, đếm chữ hoa, chữ thường. 24. Viết chương trình nhập một số n có tối đa 2 chữ số. Hãy cho biết cách đọc ra dạng chữ. Ví dụ, n = 35 kết quả là ’Ba mươi lăm’. 25. Viết chương trình nhập vào một ngày (ngày, tháng, năm). Tìm ngày kế sau ngày vừa nhập theo định dạng (ngày/tháng/năm). 26. Viết chương trình nhập vào 2 giá trị a, b và phép toán ‘+’, ‘-’, ‘*’, ‘/’. Hãy xuất kết quả theo đúng phép toán đã nhập. 27. Viết chương trình nhập vào một tháng bất kỳ trong năm, xuất ra tháng đó thuộc quý mấy trong năm. 28. Viết chương trình nhập số tự nhiên n. Kiểm tra tính đúng đắn của biểu thức: 13 + 23 + 33 + . . . + n3 = (1 + 2 + 3 + . . . + n)2

29. Tiền điện được tính theo đơn giá bậc thang như sau: Bậc 1 (0 đến 50kWh): 1.678 đồng/kWh; Bậc 2 (51 đến 100kWh): 1.734 đồng/kWh; Bậc 3 (101 đến 200 kWh): 2.014 đồng/kWh; Bậc 4 (201 đến 300 kWh): 2.536 đồng/kWh; Bậc 5 (301 đến 400 kWh): 2.834 đồng/kWh; Bậc 6 (401 kWh trở lên): 2.927 đồng/kWh. Viết chương trình nhập số điện tiêu thụ nhập từ bàn phím, tính tiền điện phải trả. 30. Viết chương trình giải phương trình bậc 1: ax + b = 0. 31. Viết chương trình giải phương trình bậc 2: ax2 + bx + c = 0 (cid:40) 32. Viết chương trình giải và biện luận hệ phương trình bậc nhất hai ẩn . a1x + b1y = c1 a2x + b2y = c2 33. Viết chương trình nhập vào một số nguyên n, kiểm tra xem n có phải là số nguyên tố không?

2.5 Câu hỏi và bài tập 89

34. Viết chương trình in các số từ 1 đến n theo thứ tự tăng dần với n nhập từ bàn phím. 35. Viết chương trình in các số từ 1 đến n theo thứ tự giảm dần với n nhập từ bàn phím. 36. Viết chương trình in các số chẵn trong dãy từ 1 đến n với n nhập từ bàn phím. 37. Viết chương trình in các số lẻ trong dãy từ 1 đến n với n nhập từ bàn phím. 38. Viết chương trình in bảng số từ 1 đến 100 thỏa mãn điều kiện: Bảng số gồm 10 hàng và 10 cột, các giá trị trong một là liên tiếp nhau, các giá trị trong hàng hơn kém nhau 10.

39. Viết chương trình in ra màn hình bảng cửu chương nhân 2 đến 9 theo các cột. 40. Có 3 loại giấy bạc 500đ, 200đ và 50đ. Viết chương trình tìm tất cả các tổ hợp có thể có được của 3 loại giấy bạc trên khi đổi số tiền là 5750đ và n bất kỳ nhập từ bàn phím. 41. Bài toán dân gian: Trăm bò trăm cỏ. Bò đứng ăn năm. Bò năm ăn ba. Bò già ba con một bó. Hỏi có bao nhiêu bò mỗi loại. Viết chương trình tìm số bò đứng, bò nằm và bò già tương ứng.

42. Viết chương trình in một bảng số từ 1 đến 100 thỏa mãn điều kiện gồm 10 hàng và 10 cột, các giá trị trong cột là liên tiếp nhau, các giá trị trong hàng hơn kém nhau 10. 43. Viết chương trình nhập vào số n và in ra các hình tam giác sao tương ứng.

44. Viết chương trình nhập vào số n và in ra tam giác Pascal tương ứng.

45. Viết chương trình nhập vào số n và in núi số tương ứng.

Chương 2. Các cấu trúc điều khiển trong Python 90

8 + . . . + 1

n+1 với n nhập từ bàn phím.

46. Viết chương trình nhập 3 số nguyên a, b và n với a, b < n. Tính tổng các số nguyên dương nhỏ hơn n chia hết cho a nhưng không chia hết cho b. 47. Viết chương trình tìm và in lên màn hình tất cả các số nguyên trong phạm vi từ 10 đến 99 sao cho tích của 2 chữ số bằng 2 lần tổng của 2 chữ số đó.

6 + 1 4 + . . . với n nhập từ bàn phím. 4 + ... + n 3∗4 + 1

4 + 1 3 − 1 3 + 3 2∗3 + 1

5∗6 + . . . + 1

4∗5 + 1

(n−1)∗n với n nhập

48. Viết chương trình nhập một số nguyên dương n. Tính: S = 1 + 2 + . . . + n. 49. Viết chương trình nhập một số nguyên dương n. Tính: S = 12 + 22 + . . . + n2. 50. Viết chương trình nhập một số nguyên dương n. Tính: S = 1 + 1/2 + . . . + 1/n. 51. Viết chương trình nhập một số nguyên dương n. Tính: S = 1 ∗ 2 ∗ . . . ∗ n = n!. 52. Viết chương trình nhập một số nguyên dương n. Tính: S = 1! + 2! + . . . + n!. 53. Viết chương trình tính tổng: S(x, n) = x + x3 + x5 + . . . + x(2n+1) với n nhập từ bàn phím. 2 + 1 1 + 1 54. Viết chương trình tính tổng S = 1 n với n nhập từ bàn phím. 2 + 1 55. Viết chương trình tính tổng S = 1 1 − 1 2 + 2 56. Viết chương trình tính tổng S(n) = 1 1 + 1 57. Viết chương trình tính tổng S(n) = 1 từ bàn phím.

n với n nhập từ bàn phím. n! , với n nhập từ bàn phím. (2n+1)! với n nhập từ bàn phím. 2i−1 sao cho |ai| ≥ epsilon.

58. Viết chương trình tính tổng S(n) = 1√ + 1√ 3 2 59. Viết chương trình tính tổng S(x, n) = x + x2 60. Viết chương trình tính tổng S(x, n) = x + x3 3 + 1 61. Viết chương trình tính tổng S = 1 − 1 + . . . + 1√ + 1√ 4 3! + . . . + xn 2! + x3 5! + ... + x(2n+1) 3! + x5 5 − ... với |ai| = 1

1! + 1

2! + ... + 1

n! với sai số k

4 = 1 − 1

3 + 1

5 + ... + (−1)n.

1 2n+1

Độ chính xác epsilon theo yêu cầu nhập từ bàn phím. 62. Viết chương trình tính giá trị gần đúng số của số e ≈ 1 + 1 được nhập từ bàn phím. 63. Viết chương trình tìm tất cả các số có 3 chữ số abc sao cho tổng lập phương của các chữ số bằng chính số đó abc = 100a + 10b + c = a3 + b3 + c3. 64. Viết chương trình tính giá trị của số π theo công thức π

0

với độ chính xác epsilon theo yêu cầu nhập từ bàn phím. 1 (cid:82) xsin(x)dx. 65. Viết chương trình tính gần đúng tích phân xác định sau

k!(n−k)! (0 ≤ k ≤ n) với k, n ∈ Z nhập từ bàn phím. n = n! (n−k)! (1 ≤ k ≤ n) với k, n ∈ Z nhập từ bàn

66. Viết chương trình tính N! với N nhập từ bàn phím. n = n! 67. Viết chương trình tính tổ hợp Ck 68. Viết chương trình tính chỉnh hợp Ak phím.

2.5 Câu hỏi và bài tập 91

69. Viết chương trình kiểm tra một n nhập từ bàn phím số có phải số Palindrome không? Số Palidrome là số mà đọc theo chiều xuôi và chiều ngược thì đều như nhau. Ví dụ: 131, 151, 34543, 48984, ...

70. Viết chương trình đảo ngược một số nguyên N nhập từ bàn phím. 71. Viết chương trình hỏi người dùng cần tạo bao nhiêu số trong dãy Fibonacci và tạo chúng. Chuỗi Fibonacci là một dãy số trong đó số tiếp theo trong dãy là tổng của hai số trước đó. Ví dụ của một chuỗi Fibonacci như sau: 1, 1, 2, 3, 5, 8, 13,...

2

72. Viết chương trình nhập vào 3 số a, b, c nguyên bất kỳ. Kiểm tra xem có ứng với 3 cạnh của 1 tam giác hay không? Nếu đúng thì tính diện tích tam giác đó theo công thức S = (cid:112)p (p − a) (p − b) (p − c) với p = (a+b+c) .

73. Viết chương trình tìm ước số chung lớn nhất của hai số a và b nhập từ bàn phím. 74. Viết chương trình tìm bội số chung nhỏ nhất của hai số a và b nhập từ bàn phím. 75. Viết chương trình nhập vào số nguyên N trong hệ 10, hãy chuyển số N sang hệ nhị phân tương ứng.

76. Viết chương trình tính tổng các số nguyên tố nhỏ hơn N với N nhập từ bàn phím. 77. Viết chương trình nhập vào 2 số A, B (A < B) và liên tiếp các số đến khi nhập số -1 thì dừng lại. Tính trung bình số học của các phần tử được nhập liên tiếp từ bàn phím trong khoảng [A, B].

78. Viết chương trình nhập vào số n, kiểm tra xem n có phải là số hoàn hảo hay không? Biết rằng số hoàn hảo là số có tổng các ước số thực sự của n bằng n. Ví dụ các số hoàn hảo là 6, 28.

79. Số nguyên a (a >= 0) gồm có n chữ số a1, a2,..., an. Số a được gọi là số Disarium khi: a = a11 + a22 + a33 + ... + ann. Ví dụ: Số 135 là số Disarium vì: 135 = 11 + 32 + 53 = 1 + 9 + 125. Nhập 2 số a, b in ra dãy số Disarium trong [a,b]

80. Số nguyên a (a >= 0) gồm có n chữ số a1, a2,..., an. Số a được gọi là số Armstrong khi: a = a1n + a2n + a3n + ... + ann. Ví dụ: Số 153 là số Armstrong vì: 153 = 13 + 53 + 33. Nhập 2 số a, b in ra dãy số Disarium trong đoạn [a, b].

81. Viết chương trình và in giá trị theo công thức cho trước: Q = (bằng chữ: Q (cid:113) 2×C×D H

bằng căn bậc hai của [(2 nhân C nhân D) chia H]. Với giá trị cố định của C là 50, H là 30. D là dãy giá trị tùy biến, được nhập vào từ giao diện người dùng, các giá trị của D được phân cách bằng dấu phẩy. 82. Viết chương trình nhập một số nguyên dương n(n > 0). Hãy cho biết chữ số lớn nhất và nhỏ nhất của trong n? 83. Viết chương trình nhập một số nguyên dương n(n > 0). Hãy cho biết các chữ số trong n là tăng dần hay giảm dần. 4 đến hai số lẻ đằng sau dấu phảy. 84. Viết chương trình tìm giá trị gần đúng của 4√ 85. Viết chương trình nhập từ bàn phím bốn số thực a, b, c, d và tìm các nghiệm của phương trình bậc 3: ax3 + bx2 + cx + d = 0 với sai số không quá 0.001. 86. Viết chương trình nhập từ bàn phím số nguyên dương N không lớn hơn 20000000000

Chương 2. Các cấu trúc điều khiển trong Python 92

và thông báo ra màn hình số chữ số 0 tận cùng của N!.

87. Viết chương trình nhập từ bàn phím hai số nguyên dương N và M (M ̸= 1), hãy tìm và hiển thị ra màn hình số nguyên không âm K sao cho N! chia hết cho MK nhưng không chia hết cho MK+1. 88. Viết chương trình nhập vào số nguyên dương n, tính tổng các số chẵn từ 1 đến n và tổng các số lẻ từ 1 đến n. 89. Viết chương trình nhập một số nguyên dương, tìm chữ số lớn nhất trong số đó. Ví dụ: 25863 (cid:25) chữ số lớn nhất là 8. 90. Viết chương trình cho người dùng nhập một số nguyên dương. Đếm có bao nhiêu chữ số chẵn, bao nhiêu chữ số lẻ trong số đó. 91. Viết chương trình nhập vào số nguyên n, yêu cầu đếm xem chữ số a xuất hiện bao nhiêu lần trong n. 92. Viết chương trình sinh một số ngẫu nhiên từ 1 đến 100. Cho người chơi đoán số và đưa ra phản hồi: “Lớn hơn”, “Nhỏ hơn”, “Đúng rồi!” dùng vòng lặp while. 93. Viết chương trình nhập vào một số nguyên dương n. Phân tích n thành tích các thừa số nguyên tố. Ví dụ: 60 = 2 × 2 × 3 × 5. 94. Viết chương trình nhập hai số nguyên a < b, liệt kê tất cả các số nguyên tố trong khoảng [a, b].

95. Cho số nguyên dương n. Lặp lại phép biến đổi sau: Nếu n chẵn thì chia đôi n, nếu n lẻ thì n = n * 3 + 1. Hãy lặp lại đến khi n = 1. In ra số bước thực hiện và các giá trị trung gian (bài toán Collatz). 96. Viết chương trình vẽ hình xoắn ốc số nguyên, nhập n và vẽ ma trận xoắn ốc kích thước n x n, điền các số từ 1 đến n². 97. Bài toán "Số may mắn": Viết chương trình liệt kê tất cả các số nguyên có 4 chữ số sao cho yổng 2 chữ số đầu bằng tổng 2 chữ số cuối và số đó chia hết cho 11.

98. Mã hóa chữ cái theo số nguyên tố: Mỗi chữ cái từ A đến Z tương ứng với 26 số nguyên tố đầu tiên (A = 2, B = 3, ..., Z = 101). Viết chương trình nhập vào một chuỗi in hoa, mã hóa thành danh sách số nguyên tố tương ứng. Ngược lại: nhập chuỗi số, giải mã ra chữ cái. Gợi ý: Dùng danh sách ánh xạ (list, dict) và kiểm tra ký tự.

99. Kiểm tra Sudoku 4x4 hợp lệ: Nhập vào bảng 4 × 4 (mỗi ô là số từ 1-4) hãy kiểm tra xem có phải là một bảng Sudoku hợp lệ không (mỗi hàng, cột, và vùng 2 × 2 không trùng số).

100. Tính căn bậc hai nguyên gần nhất bằng giải thuật nhị phân: Viết hàm nhập vào số n ≥ 0, tính căn bậc hai nguyên gần nhất (làm tròn xuống), không dùng thư viện math. Gợi ý, dùng thuật toán Binary Search trong đoạn [0, n].

3. Lập trình có cấu trúc với Python

Mục tiêu: Kết thúc chương này, sinh viên có thể:

• Hiểu được cấu trúc hàm, cách thức hoạt động và gọi hàm. • Nắm vững và sử dụng thành thạo các hàm thông dụng. • Nắm vững và sử dụng thành thạo các thao tác xử lý chuỗi. • Nắm vững và sử dụng thành thạo các thao tác xử lý danh sách. • Nắm vững và sử dụng thành thạo các thao tác xử lý tập tin.

3.1 Hàm trong Python

3.1.1.1 Khái niệm về hàm

3.1.1 Khái niệm và cấu trúc hàm

Hàm là một đoạn chương trình có tên, đầu vào và đầu ra, có chức năng giải quyết một số vấn đề chuyên biệt cho chương trình chính, được gọi nhiều lần với các tham số khác nhau. Được sử dụng khi có nhu cầu tái sử dụng, sửa lỗi và cải tiến. Nói chung, các hàm được sử dụng trong Python để thực thi một chuỗi các lệnh liên tiếp. Tuy nhiên, cách sử dụng các hàm thì không giống với các vòng lặp. Các vòng lặp có thể lặp lại một chuỗi các chỉ thị với các lần lặp liên tiếp nhau. Nhưng việc gọi một hàm sẽ sinh ra một chuỗi các chỉ thị được thực thi tại vị trí bất kỳ trong chương trình. Các hàm có thể được gọi nhiều lần khi có yêu cầu. Giả sử một phần của mã lệnh trong một chương trình dùng để tính tỉ lệ phần trăm cho một vài con số. Nếu

Chương 3. Lập trình có cấu trúc với Python 94

sau đó, trong cùng chương trình, việc tính toán như vậy cần phải thực hiện trên những con số khác, thay vì phải viết lại các chỉ thị giống như trên, một hàm có thể được viết ra để tính tỉ lệ phần trăm của bất kỳ các con số. Sau đó chương trình có thể nhảy đến hàm đó, để thực hiện việc tính toán (trong hàm) và trở về nơi nó đã được gọi. Điều này sẽ được giải thích rõ ràng hơn khi thảo luận về cách hoạt động của các hàm.

3.1.1.2 Cấu trúc tổng quát của hàm

Một điểm quan trọng khác là các hàm thì dễ viết và dễ hiểu. Các hàm đơn giản có thể được viết để thực hiện các tác vụ xác định. Việc gỡ rối chương trình cũng dễ dàng hơn khi cấu trúc chương trình dễ đọc, nhờ vào sự đơn giản hóa hình thức của nó. Mỗi hàm có thể được kiểm tra một cách độc lập với các dữ liệu đầu vào, với dữ liệu hợp lệ cũng như không hợp lệ. Các chương trình chứa các hàm cũng dễ bảo trì hơn, bởi vì những sửa đổi, nếu yêu cầu, có thể được giới hạn trong các hàm của chương trình. Một hàm không chỉ được gọi từ các vị trí bên trong chương trình, mà các hàm còn có thể đặt vào một thư viện và được sử dụng bởi nhiều chương trình khác, vì vậy tiết kiệm được thời gian viết chương trình.

Hàm trong Python được khởi tạo bởi từ khóa def, được phần chia thành 2 loại: • Hàm dựng sẵn (built-in) hay hàm thư viện. • Hàm do người dùng định nghĩa (user-defined). Định nghĩa một hàm trong Python: Khi định nghĩa các hàm để cung cấp một tính năng nào đó, chúng ta cần theo cấu trúc sau:

Hình 3.1: Cấu trúc hàm trong Python

1 2 3 4

def ten_ham( cac_tham_so ): "function_docstring" function_suite return [bieu_thuc]

Cú pháp:

Trong đó: • Từ khóa def được sử dụng để bắt đầu phần định nghĩa hàm, xác định phần bắt đầu của khối hàm. def được theo sau bởi ten_ham được theo sau bởi các dấu ngoặc đơn (). • Các tham số được truyền vào bên trong các dấu ngoặc đơn. Ở cuối là dấu hai chấm. • Trước khi viết một code, một độ thụt dòng được cung cấp trước mỗi lệnh. Độ thụt dòng này nên giống nhau cho tất cả các lệnh bên trong hàm đó.

• Lệnh đầu tiên của hàm là tùy ý gọi là Documentation String của hàm đó. • Sau đó là lệnh để được thực thi.

3.1 Hàm trong Python 95

def printme( str ):

1 2 3 4

"Chuoi nay duoc truyen vao trong ham" print str return

3.1.1.3 Hàm dựng sẵn (Build-in function)

Ví dụ 3.1.1. Hàm sau nhận một chuỗi là tham số input và in nó trên màn hình chuẩn.

Python 3.12 có 69 hàm dựng sẵn (Built-in functions) được tích hợp sẵn trong trình thông dịch, cho phép sử dụng trực tiếp mà không cần nhập khẩu thêm thư viện. Một số hàm được sử dụng thường xuyên khi làm việc với Python như: print(), input(), int(), float(),...

Hình 3.2: Các hàm dựng sẵn trong Python

Bảng 3.1: Chức năng các hàm dựng sẵn trong Python

Tên hàm

Chức năng

abs() all() any() ascii() bin() bool() bytearray() bytes() callable() chr() classmethod()

Trả về giá trị tuyệt đối của một số Trả về True khi tất cả các phần tử trong iterable là đúng Kiểm tra bất kỳ phần tử nào của iterable là True Trả về string chứa đại diện (representation) có thể in Chuyển đổi số nguyên sang chuỗi nhị phân Chuyển một giá trị sang Boolean Trả về mảng kích thước byte được cấp Trả về đối tượng byte không đổi Kiểm tra xem đối tượng có thể gọi hay không Trả về một ký tự (một chuỗi) từ Integer Trả về một class method cho hàm

Chương 3. Lập trình có cấu trúc với Python 96

Tên hàm

Chức năng

compile() complex() delattr() dict() dir() divmod() enumerate() eval() exec() filter() float() format() frozenset() getattr() globals() hasattr() hash() help() hex() id() input() int() isinstance() issubclass() iter() len() list() locals() map() max() memoryview() min() next() object() oct() open() ord() pow() print() property() range()

Trả về đối tượng code Python Tạo một số phức Xóa thuộc tính khỏi đối tượng Tạo Dictionary Trả lại thuộc tính của đối tượng Trả về một Tuple của Quotient và Remainder Trả về đối tượng kê khai Chạy code Python trong chương trình Thực thi chương trình được tạo động Xây dựng iterator từ các phần tử True Trả về số thập phân từ số, chuỗi Trả về representation được định dạng của giá trị Trả về đối tượng frozenset không thay đổi Trả về giá trị thuộc tính được đặt tên của đối tượng Trả về dictionary của bảng sumbol toàn cục hiện tại Trả về đối tượng dù có thuộc tính được đặt tên hay không Trả về giá trị hash của đối tượng Gọi Help System được tích hợp sẵn Chuyển Integer thành Hexadecimal Trả về định danh của đối tượng Đọc và trả về chuỗi trong một dòng Trả về số nguyên từ số hoặc chuỗi Kiểm tra xem đối tượng có là Instance của Class không Kiểm tra xem đối tượng có là Subclass của Class không Trả về iterator cho đối tượng Trả về độ dài của đối tượng Tạo list trong Python Trả về dictionary của bảng sumbol cục bộ hiện tại Áp dụng hàm và trả về một list Trả về phần tử lớn nhất Trả về chế độ xem bộ nhớ của đối số Trả về phần tử nhỏ nhất Trích xuất phần tử tiếp theo từ Iterator Tạo một đối tượng không có tính năng (Featureless Object) Chuyển số nguyên sang bát phân Trả về đối tượng File Trả về mã Unicode code cho ký tự Unicode Trả về x mũ y In đối tượng được cung cấp Trả về thuộc tính property Trả về chuỗi số nguyên từ số bắt đầu đến số kết thúc

3.1 Hàm trong Python 97

Tên hàm

Chức năng

Trả về representation có thể in của đối tượng Trả về iterator đảo ngược của một dãy Làm tròn số thập phân Tạo một set các phần tử mới Đặt giá trị cho một thuộc tính của đối tượng Cắt đối tượng được chỉ định bằng range() Trả về list được sắp xếp Tạo static method từ một hàm Chuyển đối tượng đã cho thành chuỗi Thêm một mục vào Iterable Cho phép tham chiếu đến Parent Class bằng super Tạo một Tuple Trả về kiểu đối tượng Trả về thuộc tính __dict__ của class Trả về Iterator của Tuple

repr() reversed() round() set() setattr() slice() sorted() staticmethod() str() sum() super() tuple() type() vars() zip() __import__() Hàm nâng cao, được gọi bằng import

Chúng ta hãy xem xét một chương trình sử dụng một số trong số này.

def viduham(a,b): print("Begin") print(max(a,b)) print(abs(a),abs(b)) print(float(a),b) print(callable(a)) print(hash(a),hash(b)) print(len(’ab’)) print(type(a)) for i in range(2,4): print(i)

viduham(2,3)

1 2 3 4 5 6 7 8 9 10 11

Ví dụ 3.1.2. Hàm dựng sẵn.

1 2 3 4 5 6 7 8 9

Begin 3 2 3 2.0 3 False 2 3 2 2 3

Kết quả đầu ra sẽ là:

3.1.1.4 Hàm người dùng tự định nghĩa (User-Defined Functions)

Chương 3. Lập trình có cấu trúc với Python 98

Giống như bất kỳ ngôn ngữ lập trình nào khác, Python cho phép chúng ta xác định các hàm của riêng mình. Xây dựng một hàm bao gồm: khai báo kiểu hàm, đặt tên hàm, khai báo các đối và đưa ra câu lệnh cần thiết để thực hiện yêu cầu đề ra cho hàm. Một hàm được viết theo mẫu sau:

1 2 3 4 5

def cong(a, b): c = a + b return c x = cong(4, 5) print(x)

Ví dụ 3.1.3. Hàm cộng 2 số do người dùng tự định nghĩa.

Chương trình trên sẽ có output là 9. Chúng ta gọi hàm cong() và truyền vào 2 tham số a, b; với a = 4 và b = 5. Hàm cong sẽ trả về (return) kết quả a + b. Sau khi đã được định nghĩa, hàm có thể được gọi bất cứ vị trí nào trong chương trình mà không phải viết lại những dòng lệnh trong hàm.

3.1.2.1 Nguyên tắc hoạt động của hàm

3.1.2 Nguyên tắc hoạt động và lời gọi hàm

Hàm trong Python cũng như trong các ngôn ngữ lập trình khác, đều hoạt động theo nguyên tắc LIFO (Last In First Out).

def double(n): return 2*n

1 2 3 4

x=double(3) print(x)

Ví dụ 3.1.4. Minh họa nguyên tắc hoạt động của hàm.

Theo cơ chế LIFO thì các thao tác trong hàm trên sẽ xảy ra tuần tự như sau:

Hình 3.3: Nguyên tắc hoạt động của hàm trong Python

3.1.2.2 Lời gọi hàm

3.1 Hàm trong Python 99

Cách thực hiện lời gọi hàm thông qua gọi tên của hàm đồng thời truyền các đối số (hằng, biến, biểu thức) cho các tham số theo đúng thứ tự đã được khai báo trong hàm. Các biến hoặc trị này cách nhau bằng dấu phẩy (,), các đối số này được được đặt trong cặp dấu ngoặc đơn (). Cặp dấu ngoặc là cần thiết để nói với trình biên dịch là đây là một lời gọi hàm. Khi một tên hàm được sử dụng trong chương trình gọi, tên hàm có thể là một phần của một một lệnh hoặc chính nó là một câu lệnh.

Cú pháp: (<đối số 1>,...,<đối số n>); Một số điểm cần nhớ: • Một dấu chấm phẩy được dùng ở cuối câu lệnh khi một hàm được gọi, nhưng nó không được dùng sau một sự định nghĩa hàm.

• Cặp dấu ngoặc () là bắt buộc theo sau tên hàm, cho dù hàm có đối số hay không. • Hàm gọi đến một hàm khác được gọi là hàm gọi hay thủ tục gọi. Và hàm được gọi đến còn được gọi là hàm được gọi hay thủ tục được gọi. • Các hàm không trả về một giá trị số nguyên cần phải xác định kiểu của giá trị được trả về. Chỉ một giá trị có thể được trả về bởi một hàm. • Một chương trình có thể có một hoặc nhiều hàm.

# Phan dinh nghia ham o day def printme( str ):

"Chuoi nay duoc truyen vao trong ham" print str return;

# Bay gio chung ta co the goi ham printme printme("Loi goi dau tien toi custom func!") printme("Loi goi thu hai toi custom func")

1 2 3 4 5 6 7 8 9

Ví dụ 3.1.5. Lời gọi hàm.

Loi goi dau tien toi custom func! Loi goi thu hai toi custom func

1 2

Kết quả:

Hàm return(bieu_thuc) được sử dụng để gửi điều khiển quay trở lại người gọi với bieu_thuc đã cho. Trong trường hợp không cung cấp bieu_thuc, thì hàm return này sẽ trả về None. Nói cách khác, lệnh return được sử dụng để thoát khỏi định nghĩa hàm. Các ví dụ trên không trả về bất cứ giá trị nào. Chúng ta có thể trả về một giá trị từ một hàm như sau:

# Phan dinh nghia ham o day def sum(arg1, arg2):

1 2 3 4

# Cong hai tham so va tra ve ket qua." total = arg1 + arg2

Ví dụ 3.1.6. Câu lệnh return trong hàm.

print "Ben trong ham : ", total return total;

5 6 7 8 9 10

# Bay gio ban co the goi ham sum nay total = sum(10, 20); print "Ben ngoai ham : ", total

Chương 3. Lập trình có cấu trúc với Python 100

1 2

Ben trong ham : 30 Ben ngoai ham : 30

Kết quả là:

3.1.3 Phạm vi của biến và truyền tham số trong Python

Tất cả các biến trong một chương trình không phải là có thể truy cập tại tất cả vị trí ở trong chương trình đó. Điều này phụ thuộc vào nơi chúng ta đã khai báo một biến. Phạm vi biến quyết định nơi nào của chương trình có thể truy cập một định danh cụ thể. Trong Python, có hai khái niệm về phạm vi biến là biến toàn cục và biến cục bộ.

Ví dụ 3.1.7. Phân biệt biến toàn cục và biến cục bộ.

Sau khi thực hiện các câu lệnh trên, kết quả in ra là 5 vì những thay đổi trong hàm increment() không được lưu trữ lại vì tác động trên biến cục bộ.

1 2 3 4 5 6 7

g=5 def increment(): global g g=2 g=g+1 increment() print(g)

Ví dụ 3.1.8. Thiết lập chỉ định biến toàn cục thông qua từ khóa global.

3.1.3.1 Biến cục bộ (Local)

Sau khi thực hiện các câu lệnh trên, kết quả in ra là 3 vì biến g đã được chỉ định là biến toàn cục trong hàm increment() thông qua từ khóa global.

Các biến được khai báo bên trong một thân hàm là biến cục bộ. Tức là các biến cục bộ này chỉ có thể được truy cập ở bên trong hàm mà chúng ta đã khai báo, không thể được truy cập ở bên ngoài thân hàm đó.

Ví dụ 3.1.9. Biến cục bộ trong Python.

def msg(): a=10 print "Gia tri cua a la",a return

msg() print a #no se cho mot error vi bien la cuc bo

1 2 3 4 5 6

3.1 Hàm trong Python 101

>>> Gia tri cua a la 10 Traceback (most recent call last):

File "C:/Python310/vidu.py", line 7, in >module< print a #no se cho mot error vi bien la cuc bo

TenError: name ’a’ is not defined >>>

1 2 3 4 5 6 7

3.1.3.2 Biến toàn cục (Global)

Kết quả sẽ cho một lỗi vì biến là cục bộ.

Biến toàn cục được định nghĩa bên ngoài hàm được gọi là biến toàn cục. Biến toàn cục có thể được truy cập bởi tất cả các hàm ở khắp nơi trong chương trình. Do đó phạm vi của biến toàn cục là rộng nhất.

b=20 def msg(): a=10 print "Gia tri cua a la",a print "Gia tri cua b la",b return

1 2 3 4 5 6 7 8 9

msg() print b

Ví dụ 3.1.10. Biến toàn cục trong Python.

1 2 3 4 5

>>> Gia tri cua a la 10 Gia tri cua b la 20 20 >>>

Kết quả là:

g=5 def increment():

1 2 3 4 5

g=g+1 increment() print(g)

Ví dụ 3.1.11. Lỗi trong truy cập biến toàn cục.

Kết quả: g dòng 3 báo lỗi, vì g ở trong hàm không có lấy g ở ngoài (khai báo ở dòng 1).

Chương 3. Lập trình có cấu trúc với Python 102

3.1.4.1 Phân loại các tham số hàm

3.1.4 Tham số hàm

3.1.4.2 Tham số bắt buộc

Khi định nghĩa một hàm, chúng ta có thể xác định một giá trị mặc định cho mỗi tham số cuối cùng. Giá trị này sẽ được sử dụng nếu tham số tương ứng là để trống bên trái khi gọi hàm đó. Việc này được thực hiện bởi sử dụng toán tử gán và gán các giá trị cho các tham số trong định nghĩa hàm. Nếu một giá trị cho tham số đó không được truyền khi hàm được gọi, thì giá trị mặc định đã cung cấp sẽ được sử dụng, nhưng nếu một giá trị đã được xác định, thì giá trị mặc định này bị bỏ qua và, thay vào đó, giá trị đã truyền được sử dụng. Python hỗ trợ các kiểu tham số chính thức sau: Tham số bắt buộc, tham số mặc định, tham số từ khóa (tham số được đặt tên), số tham số thay đổi.

Các tham số bắt buộc trong Python là các tham số được truyền tới một hàm theo một thứ tự chính xác. Ở đây, số tham số trong lời gọi hàm nên kết nối chính xác với phần định nghĩa hàm.

#Phan dinh nghia cua ham sum def sum(a,b):

"Ham co hai tham so" c=a+b print c sum(10,20) sum(20)

1 2 3 4 5 6 7

Ví dụ 3.1.12. Tham số bắt buộc trong Python.

>>> 30 Traceback (most recent call last):

File "C:/Python310/thamso.py", line 8, in >module

1 2 3 4 5 6

TypeError: sum() takes exactly 2 arguments (1 given) >>>

Kết quả thực thi sẽ cho một lỗi như sau:

Giải thích: 1. Trong trường hợp đầu tiên, khi hàm sum() được gọi đã được truyền hai giá trị là 10 và 20, đầu tiên Python so khớp với phần định nghĩa hàm, sau đó 10 và 20 được gán tương ứng cho a và b. Do đó hàm sum() được tính toán và được in.

3.1.4.3 Tham số mặc định

2. Trong trường hợp thứ hai, khi chúng ta chỉ truyền cho hàm sum() một giá trị là 20, giá trị này được truyền tới phần định nghĩa hàm. Tuy nhiên phần định nghĩa hàm chấp nhận hai tham số trong khi chỉ có một giá trị được truyền, do đó sẽ tạo ra một lỗi như trên.

Tham số mặc định trong Python là tham số mà cung cấp các giá trị mặc định cho các tham số được truyền trong phần định nghĩa hàm, trong trường hợp mà giá trị không được cung cấp trong lời gọi hàm.

3.1 Hàm trong Python 103

#Phan dinh nghia ham def msg(Id,Ten,Age=18):

"In gia tri da truyen" print Id print Ten print Tuoi return #Function call msg(Id=100,Ten=’Dac-Nhuong Le’,Tuoi=40) msg(Id=101,Ten=’Sinh Vien’)

1 2 3 4 5 6 7 8 9 10

Ví dụ 3.1.13. Tham số mặc định trong Python.

>>> 100 Dac-Nhuong Le 40 101 Sinh Vien 18 >>>

1 2 3 4 5 6 7 8

Kết quả:

Giải thích: 1. Trong trường hợp đầu tiên, khi hàm msg() được gọi đang truyền ba giá trị là 100, Dac-Nhuong Le, và 40, thì các giá trị này sẽ được gán tương ứng cho các tham số và do đó chúng được in ra tương ứng.

3.1.4.4 Tham số từ khóa

2. Trong trường hợp thứ hai, khi chúng ta chỉ truyền hai tham số cho hàm msg() được gọi là 101 và Sinh Vien, thì các giá trị này được gán tương ứng cho ID và Ten. Không có giá trị nào được gán cho tham số thứ ba trong lời gọi hàm, và vì thế hàm sẽ lấy giá trị mặc định là 18.

Sử dụng tham số từ khóa trong Python, tham số được truyền trong lời gọi hàm được kết nối với phần định nghĩa hàm dựa trên tên của tham số. Với trường hợp này, vị trí của các tham số trong lời gọi hàm là tùy ý.

def msg(id,name):

"In gia tri da truyen" print id print ten return

msg(id=100,ten=’Dac-Nhuong Le’) msg(ten=’Sinh Vien’,id=101)

1 2 3 4 5 6 7

Ví dụ 3.1.14. .

Kết quả:

1 2 3 4 5 6

>>> 100 Dac-Nhuong Le 101 Sinh Vien >>>

Chương 3. Lập trình có cấu trúc với Python 104

Giải thích: 1. Trong trường hợp đầu tiên, trong lời gọi hàm msg(), chúng ta đã truyền hai giá trị và truyền vị trí giống như của chúng trong phần định nghĩa hàm. Sau khi so khớp với phần định nghĩa hàm, thì các giá trị này được truyền tương ứng với các tham số trong phần định nghĩa hàm. Điều này được thực hiện dựa trên tên tham số.

3.1.4.5 Hàm với số tham số thay đổi

2. Trong trường hợp thứ hai, trong lời gọi hàm msg(), chúng ta cũng cũng truyền hai giá trị nhưng với vị trí khác với phần định nghĩa hàm. Thì ở đây, dựa vào tên của tham số, các giá trị này cũng được truyền tương ứng cho các tham số trong phần định nghĩa hàm.

def tenham([tham_so_chinh_thuc,] *var_args_tuple ):

"function_docstring" function_suite return [bieu_thuc]

1 2 3 4

Chúng ta có thể cần xử lý một hàm mà có số tham nhiều hơn đã xác định trong khi định nghĩa hàm. Những tham số này được gọi là các tham số có số tham số thay đổi (variable-length args) và không được đặt tên trong định nghĩa hàm, không giống như các tham số bắt buộc và tham số mặc định. Cú pháp cho một hàm có số thay đổi là:

Một dấu * được đặt trước tên biến để giữ các giá trị của các tham số loại này. Tuple này vẫn là trống nếu không có tham số bổ sung nào được xác định trong khi gọi hàm.

# Phan dinh nghia ham o day def printinfo( arg1, *vartuple ): "In mot tham so da truyen" print "Ket qua la: " print arg1 for var in vartuple:

print var

return;

1 2 3 4 5 6 7 8 9 10 11 12

# Bay gio chung ta co the goi ham printinfo printinfo( 10 ) printinfo( 70, 60, 50 )

Ví dụ 3.1.15. Hàm với số tham số thay đổi trong Python.

Kết quả:

Ket qua la: 10 Ket qua la: 70 60 50

1 2 3 4 5 6

3.1.4.6 Phân biệt argument và parameter

3.1 Hàm trong Python 105

Phân biệt argument và parameter trong Python, có hai kiểu dữ liệu được truyền trong hàm: • Kiểu dữ liệu đầu tiên là dữ liệu được truyền trong lời gọi hàm. Dữ liệu này được gọi là argument. Argument có thể là hằng, biến hoặc biểu thức. • Kiểu dữ liệu thứ hai là dữ liệu được nhận trong phần định nghĩa hàm. Dữ liệu này được gọi là parameter. Parameter phải là biến để giữ các giá trị đang đến.

def addition(x,y): print x+y

x=15 addition(x,10) addition(x,x) y=20 addition(x,y)

1 2 3 4 5 6 7

Ví dụ 3.1.16. Truyền tham số cho hàm.

>>> 25 30 35 >>>

1 2 3 4 5

3.1.4.7 Phân biệt tham chiếu và tham trị

Kết quả:

Tất cả parameter (argument) trong Python được truyền bởi tham chiếu. Nghĩa là nếu chúng ta thay đổi những gì mà một parameter tham chiếu tới bên trong một hàm, thì thay đổi này cũng phản ánh trong hàm đang gọi.

# Phan dinh nghia ham o day def changeme( mylist ):

"Thay doi list da truyen cho ham nay" mylist.append([1,2,3,4]); print "Cac gia tri ben trong ham la: ", mylist return

# Bay gio chung ta co the goi ham changeme function

1 2 3 4 5 6 7 8

Ví dụ 3.1.17. Truyền tham chiếu trong hàm.

9 10 11

mylist = [10,20,30]; changeme( mylist ); print "Cac gia tri ben ngoai ham la: ", mylist

Chương 3. Lập trình có cấu trúc với Python 106

1 2

Cac gia tri ben trong ham la: [10, 20, 30, [1, 2, 3, 4]] Cac gia tri ben ngoai ham la: [10, 20, 30, [1, 2, 3, 4]]

Ở đây, chúng ta đang duy trì tham chiếu của đối tượng đang truyền và đang phụ thêm các giá trị trong cùng đối tượng đó. Vì thế đoạn code này sẽ cho kết quả:

Chúng ta xét thêm một ví dụ nữa, tại đây tham số đang được truyền bởi tham chiếu và tham chiếu đang được ghi đè bên trong hàm được gọi.

# Phan dinh nghia ham o day def changeme( mylist ):

"Thay doi list da truyen cho ham nay" mylist = [1,2,3,4]; # Lenh nay gan mot tham chieu moi cho mylist print "Cac gia tri ben trong ham la: ", mylist return

# Bay gio ban co the goi ham changeme mylist = [10,20,30]; changeme( mylist ); print "Cac gia tri ben ngoai ham la: ", mylist print "Cac gia tri ben ngoai ham la: ", mylist

1 2 3 4 5 6 7 8 9 10 11 12

Ví dụ 3.1.18. Truyền tham trị trong hàm.

1 2

Cac gia tri ben trong ham la: [1, 2, 3, 4] Cac gia tri ben ngoai ham la: [10, 20, 30]

3.1.4.8 Hàm nặc danh Lambda

Tham số mylist là cục bộ (local) với hàm changeme. Việc thay đổi mylist bên trong hàm này không ảnh hưởng tới mylist. Và cuối cùng code trên sẽ cho kết quả:

Hàm nặc danh (hàm vô danh), hiểu theo cách đơn giản là hàm không có tên và chúng không được khai báo theo cách chính thức bởi từ khóa def. Để khai báo hàm này, chúng ta sử dụng từ khóa lambda. Lambda nhận bất kỳ lượng tham số nào và chỉ trả về một giá trị trong dạng một biểu thức đã được ước lượng. Chúng ta không thể gọi trực tiếp gọi hàm nặc danh để in bởi vì labda cần một biểu thức. Ngoài ra, các hàm lambda có namespace cục bộ của chúng.

Hình 3.4: Biểu thức Lambda trong Python

Trong đó:

3.1 Hàm trong Python 107

• lambda: là từ khóa • paramaterlist: tập hợp các parameter mà chúng ta muốn định nghĩa • expression: biểu thức đơn trong Python (Không nhập complex) Cú pháp của hàm lamda: lambda [arg1 [,arg2,.....argn]]:bieu_thuc

square=lambda x1: x1*x1 #Phan dinh nghia ham print "Binh phuong cua so la",square(10)

#Goi square nhu la mot ham

1 2

Ví dụ 3.1.19. Định nghĩa hàm nặc danh.

>>> Binh phuong cua so la 100 >>>

1 2 3

Kết quả:

def handle(f,x):

return f(x)

1 2

Ví dụ 3.1.20. Hàm nặc danh tùy ý thao tác.

ret1=handle(lambda x:x%2==0,7) ret2=handle(lambda x:x%2!=0,7)

1 2

Ta thấy đối số đầu tiên là một hàm f nào đó. Từ handle này, ta có thể gọi tùy ý các giao tác:

def handle(f,x):

return f(x)

sum = handle(lambda x,y:x+y,7,9) print(sum)

1 2 3 4

Trước dấu 2 chấm là từ khóa lambda, đằng sau nó là số lượng các biến được khai báo trong handle (tính sau chữ f). Tức là nếu ta handle(f,x,y) thì viết lambda x, y:

Vì lambda expression không nhận cách viết complex, nếu muốn complex ta nên định nghĩa các hàm độc lập rồi truyền vào cho lamba.

def handle(f,x):

return f(x) def soChan(x): return x%2

def soLe(x):

return x%2=1 def soNguyenTo(x):

dem=0 for i in range(1,x+1):

if x%i is 0:

dem = dem +1

return dem==2

1 2 3 4 5 6 7 8 9 10 11 12

Ví dụ 3.1.21. Hàm nặc danh thay đổi theo các hàm khác nhau.

Chương 3. Lập trình có cấu trúc với Python 108

retl=handle (soChan, 6) print (ret1) ret2=handle (lambda x:soChan (x),6) print (ret2) ret3-handle (sole, 6) print (ret3) ret4-handle (lambda x: soLe (x), 7) print (ret4) ret5-handle (soNguyenTo,5) print (ret5) ret6-handle (lambda x: soNguyenTo (x), 9) print (ret6)

1 2 3 4 5 6 7 8 9 10 11

Ở bên ta có 4 hàm, trong đó soChan, soLe, soNguyenTo sẽ được gọi vào handle. Chúng ta có thể sử dụng hàm handle như sau:

True True False True True False False 16

1 2 3 4 5 6 7 8

Kết quả:

3.1.5 Viết tài liệu cho hàm

Python hỗ trợ ta bổ sung tài liệu cho hàm, việc này rất thuận lợi cho đối tác sử dụng các function do người lập trình viết ra. Dựa vào những tài liệu này mà đối tác có thể dễ dàng biết cách sử dụng. Chúng ta có thể sử dụng 3 dấu nháy kép hoặc 3 dấu nháy đơn để viết tài liệu cho hàm. Tuy nhiên theo kinh nghiệm thì người dùng nên dùng 3 dấu nháy kép. Các ghi chú (tài liệu) phải được viết ở những dòng đầu tiên khi khai báo hàm.

def gcd (nl, n2): """ Ham nay dung de tim uoc so chung lon nhat cua 2 so n1 va n2"""

min = nl if nl < n2 else n2 largest_factor = 1 for i in range (1, min + 1):

if nl % i == 0 and n2 % i == 0:

largest_factor = i

return largest_factor

"""Giai phuong trinh bac 1 ax+b=0""" def ptbl (a,b):

if a ==0 and b==0:

return "Vo so nghiem"

elif a==0 and b!=0:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

Ví dụ 3.1.22. Tạo file DocumentFunction.py có 2 hàm gcd và ptb1.

return "Vo nghiem"

else:

15 16 17

return "x={0}".format (round(-b/a, 2))

3.1 Hàm trong Python 109

Chúng ta chạy command line để xem cách lấy tài liệu cho các hàm trên bằng cách vào menu Tools/Python Console.... Muốn xem tài liệu của hàm nào thì thiết lập:

• from DocumentFunction import * • Gõ lệnh: help(function name)

Hình 3.5: Viết tài liệu cho hàm trong Python

3.1.6.1 Khái niệm và các bước giải bài toán đệ quy

3.1.6 Hàm đệ qui

Chúng ta thấy, trong nhiều ví dụ của các hàm có tham trỏ đến các hàm khác, trường hợp đặc biệt các hàm có thể tham chiếu đến chính hàm đó ta gọi đó là tính đệ quy. Ta nói một đối tượng là đệ quy nếu nó được định nghĩa qua chính nó hoặc một đối tượng khác cùng dạng với chính nó bằng quy nạp. Ví dụ, trong một ngôi nhà có treo bức ảnh về chính ngôi nhà đó, trong bức ảnh lại có ngôi nhà, và trong đó lại có bức ảnh chính ngôi nhà,...

Hình 3.6: Hình ảnh biểu diễn đệ qui

Đệ quy (Recursion): Ta nói một đối tượng là đệ quy nếu nó được định nghĩa qua chính nó hoặc một đối tượng khác cùng dạng với chính nó bằng quy nạp. Nếu lời giải bài toán P được thực hiện bằng lời giải bài toán P’ có dạng giống như P thì ta nói đó là lời giải đệ quy. Thuật toán tương ứng với lời giải như vậy gọi là thuật toán đệ quy. Điều quan trọng ở đây tuy P’ là giống với P nhưng theo một nghĩa nào đó thì P’ phải "nhỏ hơn" P.

Cho S(n) = 1 + 2 + 3 + ... + n. Chúng ta sẽ tính S(10) và S(11) như sau: Một hàm hay thủ tục đệ quy gồm hai phần: • Phần suy biến (neo: Anchor): Phần này được thực hiện khi bài toán quá đơn giản có thể giải trực tiếp mà không cần phải nhờ đến một thuật toán nào.

Chương 3. Lập trình có cấu trúc với Python 110

Hình 3.7: Tính S(n) = 1 + 2 + 3 + ... + n theo đệ quy

• Phần đệ quy (Hay phần quy nạp): Trong trường hợp bài toán không thể giải bằng phần neo, ta xác định những bài toán con và gọi đệ quy giải những bài toán con đó. Khi đã có lời giải của những bài toán con rồi thì phối hợp lại để giải bài toán đang quan tâm. Phần đệ quy thể hiện tính "quy nạp" của lời giải. Phần neo cũng rất quan trọng bởi nó quyết định tới tính hữu hạn dừng của lời giải. Các bước giải bài toán đệ quy như sau:

3.1.6.2 Phân loại hàm đệ qui

Hình 3.8: Các bước giải bài toán đệ quy

Một hàm được gọi là đệ quy nếu bên trong thân của hàm đó có lời gọi hàm lại chính nó một cách trực tiếp hay gián tiếp.

Phân loại đệ quy: 1. Đệ quy tuyến tính: Trong thân hàm có duy nhất một lời gọi hàm gọi lại chính nó một cách tường minh.

2. Đệ quy nhị phân: Trong thân hàm có hai lời gọi hàm đến chính nó một cách tường minh. 3. Đệ quy hỗ tương: Trong thân hàm này có lời gọi hàm tới hàm kia và bên trong thân hàm kia có lời gọi hàm tới hàm này.

3.1 Hàm trong Python 111

Hình 3.9: Đệ quy trực tiếp và đệ quy gián tiếp

4. Đệ quy phi tuyến: Trong thân hàm có lời gọi hàm lại chính nó được đặt bên trong thân vòng lặp.

def Tong(n): if n==0:

return 0

else:

1 2 3 4 5

return Tong(n-1)+n

Ví dụ 3.1.23. Đệ quy tuyến sinh: Tính S(n) = 1 + 2 + .. + n. Ta có, công thức truy hồi S(n) = S(n − 1) + n và điều kiện dừng S(0)=0.

def Fibo(n):

if n==0 or n==1: return 1

else:

1 2 3 4 5

return Fibo(n-1)+Fibo(n-2)

Ví dụ 3.1.24. Đệ quy nhị phân: Tính số hạng thứ n của dãy Fibonnaci F(0) = F(1) = 0, F(n) = F(n − 1) + F(n − 2).

def xn(n):

if n==0:

return 1

else:

return xn(n-1)+yn(n-1)

def yn(n):

if n==0:

return 0

else:

1 2 3 4 5 6 7 8 9 10 11

return 3*xn(n-1)+2*yn(n-1)

Ví dụ 3.1.25. Đệ quy hỗ tương: Tính số hạng thứ n của dãy số x(0) = 1, y(0) = 0, x(n) = x(n − 1) + y(n − 1), y(n) = 3x(n − 1) + 2y(n − 1).

Ví dụ 3.1.26. Đệ quy phi tuyến: Tính số hạng thứ n của dãy số x(0) = 1, x(n) = n2x(0) + (n − 1)2x(1) + ... + 12x(n − 1).

def xn(n):

if n==0:

return 1

s=0 for i in range(1,n+1): s=s+i*i*xn(n-1)

1 2 3 4 5 6 7

return s

Chương 3. Lập trình có cấu trúc với Python 112

3.2 Xử lý chuỗi (string)

3.2.1 Khái niệm chuỗi

1 2

print("Hello") print(’Phat trien ung dung voi Python’)

Kiểu dữ liệu chuỗi (string) trong Python là một trong các kiểu phổ biến nhất trong Python. Chuỗi ký tự trong python được bao quanh bởi dấu ngoặc kép đơn hoặc dấu ngoặc kép. Python coi các lệnh trích dẫn đơn và kép là như nhau. Ví dụ, chuỗi ’Hello’ tương đương với chuỗi "Hello". Chúng ta có thể hiển thị một chuỗi trong Python bằng hàm print().

Gán chuỗi cho một biến: Việc gán một chuỗi cho một biến được thực hiện với tên biến theo sau là dấu bằng và chuỗi.

1 2

str1 = "Hello World!" print(str1)

Ví dụ 3.2.1. Gán chuỗi cho một biến.

Chuỗi đa dòng: Chúng ta có thể gán một chuỗi nhiều dòng cho một biến bằng cách sử dụng 3 dấu ngoặc kép hoặc 3 dấu nháy đơn.

str1 = """Vi du nhap chuoi nhieu dong trong Python day la dong thu 2 day la dong thu 3 day la dong thu 4""" print(str1)

1 2 3 4 5

Ví dụ 3.2.2. Nhập chuỗi đa dòng với 3 dấu ngoặc kép.

str1 = ’’’Vi du nhap chuoi nhieu dong trong Python day la dong thu 2 day la dong thu 3 day la dong thu 4’’’ print(str1)

1 2 3 4 5

Ví dụ 3.2.3. Nhập chuỗi đa dòng với 3 dấu ngoặc đơn.

3.2 Xử lý chuỗi (string) 113

3.2.2 Cấu trúc của chuỗi và truy cập

Chuỗi là một mảng, các chuỗi trong Python là mảng các byte đại diện cho các ký tự unicode. Tuy nhiên, Python không có kiểu dữ liệu ký tự, một ký tự đơn giản chỉ là một chuỗi có độ dài bằng 1. Dấu ngoặc vuông [] có thể được sử dụng để truy cập các phần tử của chuỗi. Ký tự đầu tiên có chỉ số là 0.

1 2

str1 = "Hello World!" print(str1[0])

Ví dụ 3.2.4. Truy cập phần tử của chuỗi.

Kết quả: H

Truy cập các giá trị trong string: Dấu ngoặc vuông [] có thể được sử dụng để truy cập các phần tử của chuỗi. Ký tự đầu tiên có chỉ số là 0.

1 2 3 4 5 6

str = "HELLO" print(str[0]) print(str[1]) print(str[2]) print(str[3]) print(str[4])

Ví dụ 3.2.5. Truy cập các giá trị trong string.

Kết quả: Trả về một chuỗi con từ vị trí 0 đến 4 của chuỗi đã cho str = "HELLO".

Chỉ định chỉ mục bắt đầu và chỉ mục kết thúc, được phân tách bằng dấu hai chấm, để trả về một phần của chuỗi.

1 2 3 4 5 6 7

str = "HELLO" print(str[:]) print(str[0:]) print(str[:5]) print(str[:3]) print(str[0:2]) print(str[1:4])

Ví dụ 3.2.6. Chỉ định chỉ mục bắt đầu và chỉ mục kết thúc chuỗi.

Kết quả:

Chương 3. Lập trình có cấu trúc với Python 114

Truy cập chuỗi bằng chỉ mục âm: Sử dụng các chỉ mục âm để lấy ra chuỗi con bắt đầu từ cuối chuỗi.

1 2

str1 = "Hello World!" print(str1[-5:-2])

Ví dụ 3.2.7. Truy cập chuỗi bằng chỉ mục âm.

Kết quả: orl

Chiều dài chuỗi trong Python: Sử dụng hàm len() để tính chiều dài chuỗi trong Python.

1 2

a = "Hello World!" print(len(a))

Ví dụ 3.2.8. Xác định chiều dài chuỗi trong Python.

Kết quả: 12

Kiểm tra sự tồn tại của chuỗi trong chuỗi: Để kiểm tra xem một cụm từ hoặc ký tự nào đó có trong một chuỗi hay không, chúng ta có thể sử dụng các từ khóa in hoặc not in.

str1 = "Phat trien ung dung voi Python." x = "Python" in str1 print(x)

1 2 3

Ví dụ 3.2.9. Kiểm tra xem cụm từ "python" có tồn tại trong chuỗi sau không?

Kết quả: True

str1 = "Phat trien ung dung voi Python." x = "Python" not in str1 print(x)

1 2 3

Ví dụ 3.2.10. Kiểm tra xem cụm từ "python" không tồn tại trong chuỗi sau không?

Kết quả: False

Nối chuỗi trong Python: Để nối hoặc kết hợp hai chuỗi với nhau chúng ta có thể sử dụng toán tử +.

1 2 3 4

a = "Hello " b = "Python " c = a + b print(c)

Ví dụ 3.2.11. Nối biến a với biến b thành biến c.

115 3.2 Xử lý chuỗi (string)

Kết quả: Hello Python

n = 3 txt = "Hello Python " + 3 print(txt)

1 2 3

Định dạng chuỗi trong Python: Trong Python, chúng ta không thể kết hợp các chuỗi và số như thế này:

Chúng ta có thể kết hợp chuỗi và số bằng cách sử dụng hàm format().

n = 3 txt = "Hello Python {}" print(txt.format(n))

1 2 3

Ví dụ 3.2.12. Sử dụng hàm format() để chèn số vào chuỗi.

Kết quả: Hello Python 3

Chúng ta có thể nhập bất kỳ số lượng đối số cho hàm format(), chúng sẽ được thay thế dấu {} tương ứng.

1 2

txt = "Xin chao, toi la {}, {} tuoi, den tu {}" print(txt.format("Dac-Nhuong Le", 40, "Hai Phong"))

Ví dụ 3.2.13. Sử dụng hàm format() để chèn bất kỳ số lượng đối số nào vào chuỗi.

Kết quả: Xin chao, toi la Dac-Nhuong Le, 40 tuoi, den tu Hai Phong

Chuỗi dạng Unicode trong Python: Các chuỗi thông thường trong Python được lưu trữ nội tại dưới dạng ASCII 8 bit, trong khi các chuỗi Unicode được lưu trữ dưới dạng Unicode 16 bit. Điều này cho phép để có một tập hợp các ký tự đa dạng hơn, bao gồm các ký tự đặc biệt từ hầu hết các ngôn ngữ trên thế giới. Các chuỗi dạng Unicode sử dụng tiền tố u, trong khi các chuỗi thô sử dụng tiền tố r.

1

print (u’Hello World!’)

Ví dụ 3.2.14. Xuất chuỗi dưới dạng unicode.

Kết quả: Hello World!

3.2.3 Các hàm cơ bản xử lý chuỗi trong Python

Chuỗi trong Python được xem là đối tượng, cung cấp một số hàm rất quan trọng thông qua cấu trúc sau:

Hình 3.10: Cấu trúc đối tượng của chuỗi trong Python

Chương 3. Lập trình có cấu trúc với Python 116

Các hàm sử lý chuỗi trong Python cung cấp các công cụ mạnh mẽ để cắt, ghép, thay thế, và biến đổi chuỗi theo nhu cầu của người lập trình. Bằng cách sử dụng các phương thức và phép toán đơn giản, chúng ta có thể thực hiện nhiều tác vụ khác nhau như tìm kiếm ký tự, đếm độ dài, chuyển đổi chữ hoa/chữ thường, và nhiều hơn nữa.

Bảng 3.2: Một số hàm xử lý chuỗi thông dụng trong Python

Tên hàm

Chức năng

Chuyển đối tất cả chữ thường trong chuỗi sang kiểu chữ hoa Chuyển đối tất cả chữ hoa trong chuỗi sang kiểu chữ thường Viết hoa chữ cái đầu tiên của chuỗi Căn lề phải và căn lề trái Căn giữa Xóa khoảng trắng dư thừa Kiểm tra Chuỗi có phải bắt đầu là ký tự ? Kiểm tra Chuỗi có phải kết thúc là ký tự ? Đếm số lần xuất hiện trong Chuỗi Tìm kiếm chuỗi con Định dạng Chuỗi Trả về số lượng ký tự trong chuỗi, dùng index để lấy ký tự ra: str[index]

upper() lower() capitalize() rjust(), ljust() center(width, fillchar) strip() startswith() endswith() count() find() format() __len__()

• Hàm strip(): Hàm này loại bỏ bất kỳ khoảng trắng từ đầu hoặc cuối cùng.

1 2

a = " Hello World! " print(a.strip())

Ví dụ 3.2.15. Hàm strip() xóa khoảng trắng dư thừa.

Kết quả: Hello World!

• Hàm lower(): Hàm trả về chuỗi chữ thường.

1 2

a = "Hello World!" print(a.lower())

Ví dụ 3.2.16. Hàm lower().

Kết quả: hello world!

• Hàm upper(): Hàm trả về chuỗi chữ hoa.

1 2

a = "Hello World!" print(a.upper())

Ví dụ 3.2.17. Hàm upper().

Kết quả: HELLO WORLD!

• Hàm replace(): Hàm thay thế một chuỗi bằng một chuỗi khác.

3.2 Xử lý chuỗi (string) 117

1 2

a = "Hello World!" print(a.replace("l", "t"))

Ví dụ 3.2.18. Hàm replace().

Kết quả: Hetto Wortd!

• Hàm split(): Hàm tách chuỗi thành các chuỗi con.

1 2

a = "Hello World!" print(a.split(","))

Ví dụ 3.2.19. Hàm split() tách chuỗi thành các chuỗi con.

Kết quả: [’Hello’, ’ World!’]

• Hàm center(width, fillchar): Trả về một chuỗi mới, trong đó chuỗi ban đầu đã được cho vào trung tâm và hai bên đó là các fillchar sao cho tổng số ký tự của chuỗi mới là width

• Hàm count(str,beg= 0,end=len(string)): Đếm xem chuỗi str này xuất hiện bao nhiêu lần trong chuỗi string hoặc chuỗi con của string nếu chúng ta cung cấp chỉ mục ban đầu start và chỉ mục kết thúc end.

• Hàm endswith(suffix,beg=0,end=len(string)): Xác định xem nếu chuỗi string hoặc chuỗi con đã cho của string (nếu chúng ta cung cấp chỉ mục bắt đầu beg và chỉ mục kết thúc end) kết thúc với hậu tố suffix thì trả về true, nếu không thì phương thức này trả về false • Hàm expandtabs(tabsize=8): Mở rộng các tab trong chuỗi tới số khoảng trống đã cho; mặc định là 8 space cho mỗi tab nếu chúng ta không cung cấp tabsize.

• Hàm find(str,beg=0,end=len(string)): Xác định xem chuỗi str có xuất hiện trong chuỗi string hoặc chuỗi con đã cho của string (nếu chúng ta cung cấp chỉ mục bắt đầu beg và chỉ mục kết thúc end), nếu xuất hiện thì trả về chỉ mục của str, còn không thì trả về -1. • Hàm index(str,beg=0,end=len(string)): Tương tự như find(), nhưng tạo ra một ngoại lệ nếu str là không được tìm thấy. • Hàm isalnum(): Trả về true nếu chuỗi có ít nhất một ký tự và tất cả ký tự là chữ-số. Nếu không hàm sẽ trả về False. • Hàm isalpha(): Trả về true nếu chuỗi có ít nhất 1 ký tự và tất cả ký tự là chữ cái. Nếu không phương thức sẽ trả về False

• Hàm isdigit(): Trả về true nếu chuỗi chỉ chứa các chữ số, nếu không là False. • Hàm islower(): Trả về true nếu tất cả ký tự trong chuỗi là ở dạng chữ thường, nếu không là False. • Hàm isnumeric(): Trả về true nếu một chuỗi dạng Unicode chỉ chứa các ký tự số, nếu không là False. • Hàm isspace(): Trả về true nếu chuỗi chỉ chứa các ký tự khoảng trắng whitespace, nếu không là False.

Chương 3. Lập trình có cấu trúc với Python 118

• Hàm istitle(): Trả về true nếu chuỗi là ở dạng titlecase, nếu không là False. • Hàm isupper(): Trả về true nếu tất cả ký tự trong chuỗi là chữ hoa. • Hàm join(seq): Nối chuỗi các biểu diễn chuỗi của các phần tử trong dãy seq thành một chuỗi.

• Hàm len(string): Trả về độ dài của chuỗi. • Hàm ljust(width[, fillchar]): Trả về một chuỗi mới, trong đó có chuỗi ban đầu được căn chỉnh vào bên trái và bên phải là các fillchar sao cho tổng số ký tự là width.

• Hàm lower(): Chuyển đối tất cả chữ hoa trong chuỗi sang kiểu chữ thường. • Hàm lstrip(): Xóa tất cả các khoảng trống trắng ban đầu (leading) trong chuỗi. • Hàm max(str): Trả về ký tự chữ cái lớn nhất từ chuỗi str đã cho. • Hàm min(str): Trả về ký tự chữ cái nhỏ nhất từ chuỗi str đã cho. • Hàm replace(old, new [, max]): Thay thế tất cả sự xuất hiện của old trong chuỗi với new với số lần xuất hiện max (nếu cung cấp) • Hàm rfind(str, beg=0,end=len(string)): Tương tự hàm find(), nhưng trả về chỉ mục cuối cùng • Hàm rindex( str, beg=0, end=len(string)): Giống index(), nhưng trả về chỉ mục cuối cùng nếu tìm thấy

• Hàm rjust(width,[, fillchar]): Trả về một chuỗi mới, trong đó có chuỗi ban đầu được căn chỉnh vào bên phải và bên trái là các fillchar sao cho tổng số ký tự là width.

• Hàm rstrip(): Xóa bỏ tất cả các khoảng trống trắng ở cuối (trailing) của chuỗi • Hàm split(str="",num=string.count(str)): Chia chuỗi theo delimeter đã cho (là space nếu không được cung cấp) và trả về danh sách các chuỗi con; nếu chúng ta cung cấp num thì chia chuỗi thành num chuỗi con.

• Hàm splitlines( num=string.count(’\n’)): Trả về một List gồm tất cả các dòng trong chuỗi, và tùy ý xác định các ngắt dòng (nếu num được cung cấp và là True). • Hàm startswith(str, beg=0,end=len(string)): Xác định xem chuỗi hoặc chuỗi con (nếu chúng ta cung cấp chỉ mục bắt đầu beg và chỉ mục kết thúc end) có bắt đầu với chuỗi con str không, nếu có trả về true, nếu không là False. • Hàm strip([chars]): Thực hiện cả hai phương thức lstrip() và rstrip() trên chuỗi

• Hàm swapcase(): Đảo ngược kiểu của tất cả ký tự trong chuỗi • Hàm title(): Trả về một bản sao của chuỗi trong đó tất cả ký tự đầu tiên của tất cả các từ là ở kiểu chữ hoa.

• Hàm upper(): Chuyển đổi các chữ thường trong chuỗi thành chữ hoa. • Hàm zfill (width): Trả về một chuỗi mới, trong đó bao gồm chuỗi ban đầu và được đệm thêm với các số 0 vào bên trái sao cho tổng ký tự là width • Hàm isdecimal(): Trả về True nếu một chuỗi dạng Unicode chỉ chứa các ký tự thập phân, nếu không là False.

3.3 Xử lý danh sách (list) 119

3.3 Xử lý danh sách (list)

Mảng trong Python được dùng khá phổ biến. Tạo mảng trong Python là một tập hợp mục được lưu trữ tại các vị trí bộ nhớ liền kề. Ý tưởng ở đây là lưu trữ nhiều mục cùng loại với nhau. Hành động này hỗ trợ người dùng tính toán vị trí của từng phần tử dễ dàng hơn bằng cách thêm một giá trị bù vào giá trị cơ sở, tức là vị trí bộ nhớ của phần tử đầu tiên trong mảng (thường được biểu thị bằng tên của mảng).

Hiểu đơn giản, chúng ta có thể tưởng tượng mảng trong Python là một dãy cầu thang nơi mà mỗi bậc được đặt một giá trị. Tại đây, chúng ta có thể xác định vị trí của bất kỳ người chúng ta bằng cách đếm số bậc chứa giá trị. Mảng có thể được môđun tên array xử lý trong Python. Chúng có thể hữu ích khi chúng ta chỉ phải xử lý một giá trị kiểu dữ liệu. Một người dùng có thể xem list là mảng. Tuy nhiên, họ không thể giới hạn kiểu thành phần được lưu trong danh sách. Nếu tạo mảng bằng môđun array, toàn bộ thành phần của mảng phải thuộc cùng một kiểu. Trong ngôn ngữ lập trình Python có bốn kiểu dữ liệu collection (Arrays):

• List: Là một collection có thứ tự, có thể thay đổi. Cho phép chứa dữ liệu trùng lặp. • Tuple: Là một collection có thứ tự, không thể thay đổi. Cho phép chứa dữ liệu trùng lặp. • Set: Là một collection không có thứ tự, không có chỉ mục. Không cho phép chứa dữ liệu trùng lặp. • Dictionary: Là một collection không có thứ tự, có thể thay đổi và lập chỉ mục. Không có thành viên trùng lặp.

3.3.1 Khái niệm List

Kiểu dữ liệu List trong Python là một collection lưu trữ các phần tử theo tứ tự đã cho, có thể thay đổi. Cho phép chứa dữ liệu trùng lặp. List có cấu trúc dữ liệu mà có khả năng lưu giữ các kiểu dữ liệu khác nhau.

Hình 3.11: Cấu trúc danh sách (list)

List trong Python được viết với dấu ngoặc vuông []. Tương tự như chỉ mục của chuỗi, chỉ mục của List bắt đầu từ 0.

1 2 3

list1 = [’java’, ’python’, 1997, 2000]; list2 = [1, 2, 3, 4, 5 ]; list3 = ["a", "b", "c", "d"];

Ví dụ 3.3.1. Gán giá trị cho các phần tử trong List.

Chương 3. Lập trình có cấu trúc với Python 120

3.3.2 Truy cập các phần tử của List

Để truy cập các phần tử trong List, chúng ta sử dụng cú pháp sau:

1 2

list1 = [’java’, ’python’, ’php’, ’c++’] print(list1[1])

Ví dụ 3.3.2. Truy cập các phần tử của List.

Kết quả: python

Chỉ mục âm: Lập chỉ mục âm có nghĩa là bắt đầu từ cuối, -1 đề cập đến mục cuối cùng, -2 đề cập đến mục cuối cùng thứ hai,...

1 2

list1 = [’java’, ’python’, ’php’, ’c++’] print(list1[-1])

Ví dụ 3.3.3. Truy cập thông qua chỉ mục âm của List.

Kết quả: c++

Phạm vi chỉ mục: Chúng ta có thể chỉ định một phạm vi chỉ mục bằng cách chỉ định nơi bắt đầu và nơi kết thúc phạm vi. Khi chỉ định một phạm vi, giá trị trả về sẽ là một List mới với các mục được chỉ định.

1 2

fruits = ["apple", "banana", "guava", "orange", "kiwi", "melon", "mango"] print(fruits[2:5])

Ví dụ 3.3.4. Truy cập thông qua phạm vi chỉ mục của List.

Kết quả: [’guava’, ’orange’, ’kiwi’]

1 2

fruits = ["apple", "banana", "guava", "orange", "kiwi", "melon", "mango"] print(fruits[:4])

Ví dụ 3.3.5. Loại bỏ giá trị bắt đầu, phạm vi sẽ bắt đầu ở mục đầu tiên.

Kết quả: [’apple’, ’banana’, ’guava’, ’orange’]

1 2

fruits = ["apple", "banana", "guava", "orange", "kiwi", "melon", "mango"] print(fruits[3:])

Ví dụ 3.3.6. Loại bỏ giá trị cuối, phạm vi sẽ đi đến cuối danh sách.

Kết quả: [’orange’, ’kiwi’, ’melon’, ’mango’]

Phạm vi của các chỉ mục âm: Chỉ định các chỉ mục âm nếu chúng ta muốn bắt đầu tìm kiếm từ cuối danh sách.

1 2

fruits = ["apple", "banana", "guava", "orange", "kiwi", "melon", "mango"] print(fruits[-4:-1])

Ví dụ 3.3.7. Trả về các mục từ chỉ mục -4 (bao gồm) đến chỉ mục -1 (không bao gồm).

Kết quả: [’orange’, ’kiwi’, ’melon’]

3.3 Xử lý danh sách (list) 121

3.3.3 Các thao tác cơ bản trên list trong Python

Chúng ta có thể thực hiện các hoạt động nối 2 list với toán tử + hoặc hoạt động lặp với * như trong các chuỗi. Điểm khác biệt là ở đây nó tạo một list mới, không phải là một chuỗi. Thay đổi giá trị của item: Để thay đổi giá trị của một item được chỉ định, chúng ta dùng chỉ số và toán tử gán =.

1 2 3

fruits = ["apple", "banana", "guava"] fruits[1] = "*orange*" print(fruits)

Ví dụ 3.3.8. Thay đổi giá trị của item trong list.

Kết quả: [’apple’, ’*orange*’, ’guava’]

Duyệt các phần tử của một list: Chúng ta có thể duyệt các phần tử của một List bằng cách sử dụng vòng lặp for.

fruits = ["apple", "banana", "guava"] for x in fruits: print(x)

1 2 3

Ví dụ 3.3.9. Duyệt các phần tử của một list dùng for.

apple banana guava

1 2 3

Kết quả:

Kiểm tra sự tồn tại của một item trong list: Sử dụng từ khóa in để kiểm tra sử tồn tại của một item trong một list trong Python.

fruits = ["apple", "banana", "guava"]; x = "banana" in fruits; if (x == True):

print("\"banana\" co ton tai trong list");

else:

1 2 3 4 5 6

print("\"banana\" khong ton tai trong list");

Ví dụ 3.3.10. Thay đổi giá trị của item trong list.

Kết quả: "banana" co ton tai trong list

Độ dài của một list trong Python: Để xác định danh sách có bao nhiêu item, chúng ta có thể sử dụng hàm len().

1 2

fruits = ["apple", "banana", "guava"]; print("So item cua list fruts la: ", len(fruits));

Ví dụ 3.3.11. Xác định độ dài của list sử dụng hàm len().

Kết quả: So item cua list fruts la: 3

Chương 3. Lập trình có cấu trúc với Python 122

Thêm phần tử mới List trong Python: Để thêm một item (phần tử) vào cuối danh sách, hãy sử dụng phương thức append().

fruits = ["apple", "banana", "guava"]; fruits.append("kiwi"); print(fruits);

1 2 3

Ví dụ 3.3.12. Thêm phần tử mới ở cuối List.

Kết quả: [’apple’, ’banana’, ’guava’, ’kiwi’]

Để thêm item tại chỉ mục đã chỉ định, hãy sử dụng phương thức insert():

1 2 3

fruits = ["apple", "banana", "guava"]; fruits.insert(2, "kiwi"); print(fruits);

Ví dụ 3.3.13. Thêm phần tử mới ở chỉ mục chỉ định trong list.

Kết quả: [’apple’, ’banana’, ’kiwi’, ’guava’]

Xóa phần tử khỏi list trong Python: Có một số phương pháp để xóa các phần tử khỏi một list như sau: • Xóa phần tử bằng phương thức remove()

1 2 3

fruits = ["apple", "banana", "guava"]; fruits.remove("banana") print(fruits);

Ví dụ 3.3.14. Xóa phần tử bằng phương thức trong List dùng phương thức remove().

Kết quả: [’apple’, ’guava’]

• Xóa phần tử bằng phương thức pop() chỉ xóa phần tử cuối cùng của list.

1 2 3

fruits = ["apple", "banana", "guava"]; fruits.pop(); print(fruits);

Ví dụ 3.3.15. Xóa phần tử bằng phương thức trong List dùng phương thức pop().

Kết quả: [’apple’, ’banana’]

• Xóa phần tử bằng lệnh del: Lệnh del được sử dụng để xóa phần tử có chỉ mục cụ thể.

1 2 3

fruits = ["apple", "banana", "guava"]; del fruits[0] print(fruits);

Ví dụ 3.3.16. Xóa phần tử bằng lệnh del.

Kết quả: [’banana’, ’guava’]

• Xóa phần tử bằng phương thức clear().

3.3 Xử lý danh sách (list) 123

1 2 3

fruits = ["apple", "banana", "guava"]; fruits.clear() print(fruits);

Ví dụ 3.3.17. Xóa phần tử bằng phương thức clear().

Kết quả: []

Copy list trong Python: Chúng ta không thể copy list chỉ bằng cách nhập list2 = list1, bởi vì: list2 sẽ chỉ là một tham chiếu đến list1 và những thay đổi trong list1 cũng sẽ tự động được thực hiện trong list2. Để copy list, python cung cấp phương thức copy().

fruits = ["apple", "banana", "guava"]; listCopy1 = fruits; listCopy2 = fruits.copy(); fruits.append("kiwi"); # thay doi list ban dau print("Bi thay doi theo list ban dau: ", listCopy1); print("Khong bi thay doi theo list ban dau:", listCopy2);

1 2 3 4 5 6

Ví dụ 3.3.18. Copy list trong Python dùng phương thức copy().

Bi thay doi theo list ban dau: [’apple’, ’banana’, ’guava’, ’kiwi’] Khong bi thay doi theo list ban dau: [’apple’, ’banana’, ’guava’]

1 2

Kết quả:

Một cách khác để tạo một bản sao là sử dụng phương thức tích hợp sẵn list().

fruits = ["apple", "banana", "guava"]; listCopy1 = fruits; listCopy2 = list(fruits) fruits.append("kiwi"); # thay doi list ban dau print("Bi thay doi theo list ban dau: ", listCopy1); print("Khong bi thay doi theo list ban dau:", listCopy2);

1 2 3 4 5 6

Ví dụ 3.3.19. Copy list trong Python dùng phương thức list().

Bi thay doi theo list ban dau: [’apple’, ’banana’, ’guava’, ’kiwi’] Khong bi thay doi theo list ban dau: [’apple’, ’banana’, ’guava’]

1 2

Kết quả:

Nối 2 list trong Python: Một trong những cách dễ nhất để nối 2 list là sử dụng toán tử +.

list1 = ["a", "b" , "c"] list2 = [1, 2, 3]

list3 = list1 + list2 print(list3)

1 2 3 4 5

Ví dụ 3.3.20. Nối 2 list trong Python dùng toán tử +.

Kết quả: [’a’, ’b’, ’c’, 1, 2, 3]

Chương 3. Lập trình có cấu trúc với Python 124

Hoặc chúng ta cũng có thể duyệt từng phần tử của một list và sử dụng hàm append() để nối vào cuối của list thứ 2.

list1 = ["a", "b" , "c"] list2 = [1, 2, 3]

for x in list2:

list1.append(x)

1 2 3 4 5 6 7

print(list1)

Ví dụ 3.3.21. Nối 2 list trong Python dùng hàm append().

Kết quả: [’a’, ’b’, ’c’, 1, 2, 3]

Constructor List(): Chúng ta có thể sử dụng constructor list() để tạo một danh sách mới.

1 2

fruits = list(("apple", "banana", "guava")); print(fruits)

Ví dụ 3.3.22. Nối 2 list trong Python dùng hàm append().

Kết quả: [’apple’, ’banana’, ’guava’]

Lưu ý trong ví dụ này, chúng ta sử dụng 2 dấu ngoặc đơn ((, giống như chúng ta chuyển đổi một dictionary thành một List. Ngoài các phương thức kể trên, Python còn xây dựng sẵn rất nhiều hàm và phương thức để sử dụng khi làm việc với List trong Bảng 3.3 và Bảng 3.4.

Bảng 3.3: Danh sách các hàm xử lý list trong Python

Tên hàm

Chức năng

Trả về độ dài của list. Trả về phần tử có giá trị lớn nhất trong list. Trả về phần tử có giá trị nhỏ nhất trong list. Chuyển đổi một tuple thành list.

Hàm len(list) Hàm max(list) Hàm min(list) Hàm list(seq)

Bảng 3.4: Danh sách các phương thức lý list trong Python

Tên phương thức

Chức năng

Thêm đối tượng obj vào cuối list Đếm xem có bao nhiêu lần mà obj xuất hiện trong list Thêm các nội dung của seq vào cuối list Trả về chỉ mục thấp nhất trong list mà tại đó obj xuất hiện Chèn đối tượng obj vào trong list tại index đã cho Xóa và trả về phần tử cuối cùng hoặc đối tượng có chỉ mục đã cung cấp Xóa đối tượng obj từ list Đảo ngược thứ tự các đối tượng trong list Sắp xếp các đối tượng của list, sử dụng hàm so sánh nếu được cung cấp

list.append(obj) list.count(obj) list.extend(seq) list.index(obj) list.insert(index, obj) list.pop(obj=list[-1]) list.remove(obj) list.reverse() list.sort([func])

3.4 Xử lý bộ (Tulpe) 125

3.4 Xử lý bộ (Tulpe)

3.4.1 Khái niệm và cấu trúc của Tulpe

Kiểu dữ liệu Tuple trong python là một collection có thứ tự, không thể thay đổi. Cho phép chứa dữ liệu trùng lặp.

Tuple sử dụng các dấu ngoặc đơn, Không giống như List sử dụng các dấu ngoặc vuông. Các đối tượng trong tuple được phân biệt bởi dấu phảy và được bao quanh bởi dấu ngoặc đơn (). Giống như chỉ mục của chuỗi, chỉ mục của tuple bắt đầu từ 0.

1 2

fruits = ("apple", "banana", "guava") print(fruits)

Ví dụ 3.4.1. Thiết lập kiểu tulpe.

1

tup1 = ();

Một tuple trống không chứa phần tử nào, ví dụ:

1 2 3 4

tupl1 = ("apple", "banana", "guava") tupl2 = ("kiwi", "cherry") fruits = (tupl1, tupl2) print (fruits)

Các tuple cũng có thể được lồng vào nhau, ví dụ:

Kết quả: ((’apple’, ’banana’, ’guava’), (’kiwi’, ’cherry’))

3.4.2 Truy cập các giá trị trong tuple trong Python

Chúng ta có thể truy cập các giá trị của tuple bằng cách tham bằng cách sử dụng chỉ mục, bên trong dấu ngoặc vuông.

1 2

fruits = ("apple", "banana", "guava", "kiwi", "cherry") print (fruits[1])

Ví dụ 3.4.2. Truy cập các giá trị trong tuple sử dụng chỉ mục.

Kết quả: banana

Chỉ mục âm: Lập chỉ mục âm có nghĩa là bắt đầu từ cuối, -1 đề cập đến mục cuối cùng, -2 đề cập đến mục cuối cùng thứ hai,...

1 2

fruits = ("apple", "banana", "guava", "kiwi", "cherry") print (fruits[-1])

Ví dụ 3.4.3. Truy cập chỉ mục âm.

Kết quả: cherry

Phạm vi chỉ mục: Chúng ta có thể chỉ định một phạm vi chỉ mục bằng cách chỉ định nơi bắt đầu và nơi kết thúc phạm vi. Khi chỉ định một phạm vi, giá trị trả về sẽ là một tuple mới với các mục được chỉ định.

Chương 3. Lập trình có cấu trúc với Python 126

1 2

fruits = ("apple", "banana", "guava", "kiwi", "cherry", "orange", "lemon") print (fruits[2:5])

Ví dụ 3.4.4. Trả lại giá trị thứ ba, thứ tư và thứ năm trong tuple.

Kết quả: (’guava’,’kiwi’,’cherry’)

Phạm vi của các chỉ mục âm: Chỉ định các chỉ mục âm nếu chúng ta muốn bắt đầu tìm kiếm từ cuối tuple.

1 2

fruits = ("apple", "banana", "guava", "kiwi", "cherry", "orange", "lemon") print (fruits[-5:-2])

Ví dụ 3.4.5. Truy cập thông qua chỉ mục âm trong tuple.

Kết quả: (’guava’,’kiwi’,’cherry’)

3.4.3 Các hàm cơ bản xử lý Tulpe trong Python

Thay đổi giá trị Tuple: Khi một tuple được tạo, chúng ta không thể thay đổi giá trị của nó. Tuple là không thể thay đổi hoặc bất biến. Có một cách giải quyết là chuyển đổi tuple thành một list, thay đổi list và chuyển đổi lại thành tuple.

x = ("apple", "banana", "cherry") y = list(x) y[1] = "kiwi" x = tuple(y) print(x)

1 2 3 4 5

Ví dụ 3.4.6. Thay đổi giá trị tuple thông qua chuyển thành list.

Kết quả: (’apple’, ’kiwi’, ’cherry’)

Duyệt các giá trị của một Tuple: Chúng ta có thể duyệt qua các giá trị của một tuple trong Python bằng cách sử dụng vòng lặp for.

fruits = ("apple", "banana", "cherry") for x in fruits: print(x)

1 2 3

Ví dụ 3.4.7. Duyệt các giá trị của một Tuple dùng for.

1 2 3

apple banana cherry

Kết quả:

Kiểm tra xem nếu giá trị tồn tại trong Tuple: Sử dụng từ khóa in để kiểm tra xem giá trị đã cho có tồn tại trong Tuple hay không.

Ví dụ 3.4.8. Kiểm tra xem nếu giá trị tồn tại trong Tuple.

1 2 3

fruits = ("apple", "banana", "cherry") x = "banana" in fruits print(x)

3.4 Xử lý bộ (Tulpe) 127

Kết quả: True

Chiều dài tuple trong Python: Để xác định có bao nhiêu giá trị trong một tuple, sử dụng hàm len().

1 2

fruits = ("apple", "banana", "cherry") print(len(fruits))

Ví dụ 3.4.9. Xác định chiều dài tuple trong Python.

Kết quả: 3

Thêm các phần tử vào tuple trong Python: Khi một tuple được tạo, chúng ta không thể thêm các mục vào nó. Tuples là không thể thay đổi.

1 2 3

fruits = ("apple", "banana", "cherry") fruits[3] = "kiwi" print(len(fruits))

Ví dụ 3.4.10. Không thể thêm các phần tử vào tuple.

Kết quả: TypeError: ’tuple’ object does not support item assignment

Tạo tuple với một phần tử duy nhất: Với một tuple chỉ có duy nhất một giá trị, thì phải có một dấu phảy ở cuối.

tuple1 = ("apple",) print(type(tuple1))

#khong phai la mot tuple tuple2 = ("apple") print(type(tuple2))

1 2 3 4 5 6

Ví dụ 3.4.11. Không thể thêm các phần tử vào tuple.

1 2

Kết quả:

Xóa các phần tử của Tuple trong Python: Chúng ta không thể xóa các phần tử trong một tuple.

1 2 3

fruits = ("apple", "banana", "cherry") del fruits print(fruits)

Ví dụ 3.4.12. Không thể xóa các phần tử vào tuple.

Chương 3. Lập trình có cấu trúc với Python 128

Kết quả: NameError: name ’fruits’ is not defined

Nối 2 Tuple trong Python: Chúng ta có thể sử dụng toán tử cộng để nối nhiều tuple trong Python.

tuple1 = ("a", "b" , "c") tuple2 = (1, 2, 3)

1 2 3 4 5

tuple3 = tuple1 + tuple2 print(tuple3)

Ví dụ 3.4.13. Nối 2 Tuple trong Python.

Kết quả: (’a’, ’b’, ’c’, 1, 2, 3)

Constructor tuple(): Cũng có thể sử dụng constructor tuple() để tạo một tuple.

1 2

fruits = tuple(("apple", "banana", "cherry")) print(fruits)

Ví dụ 3.4.14. Nối 2 Tuple trong Python.

Kết quả: (’apple’, ’banana’, ’cherry’)

Một số phương thức khác xử lý tuple trong Python:

Bảng 3.5: Một số phương thức khác xử lý tuple trong Python

Tên hàm

Chức năng

Trả về độ dài của tuple. Trả về item có giá trị lớn nhất từ một tuple đã cho. Trả về item có giá trị nhỏ nhất từ một tuple đã cho. Chuyển đổi một dãy thành tuple.

len(tuple) max(tuple) min(tuple) tuple(seq)

Tại sao chúng ta sử dụng tuple? Bởi vì chương trình xử lý các tuple là nhanh hơn các List, làm cho dữ liệu an toàn hơn bởi vì tuple là không thay đổi (immutable) nên không thể bị thay đổi. Các tuple được sử dụng để định dạng String.

3.5 Xử lý Dictionary

3.5.1 Khái niệm và cấu trúc của Dictionary

Kiểu dữ liệu Dictionary trong Python là một tập hợp các cặp key-value không có thứ tự, có thể thay đổi và lập chỉ mục (truy cập phần tử theo chỉ mục). Dictionary được khởi tạo với các dấu ngoặc nhọn {} và chúng có các khóa và giá trị (key-value). Mỗi cặp key-value được xem như là một item. Key mà đã truyền cho item đó phải là duy nhất, trong khi đó value có thể là bất kỳ kiểu giá trị nào. Key phải là một kiểu dữ liệu không thay đổi (immutable) như chuỗi, số hoặc tuple.

3.5 Xử lý Dictionary 129

Hình 3.12: So sánh cấu trúc Dictionary và List

Key và value được phân biệt riêng rẽ bởi một dấu hai chấm (:). Các item phân biệt nhau bởi một dấu phảy (,). Các item khác nhau được bao quanh bên trong một cặp dấu ngoặc móc đơn tạo nên một Dictionary trong Python.

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972}

print(dictCar)

1 2 3 4 5

Ví dụ 3.5.1. Khai báo kiểu Dictionary.

Kết quả: {’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 1972}

3.5.2 Truy cập các item của Dictionary trong Python

Chúng ta có thể truy cập các item của Dictionary bằng cách sử dụng khóa của nó, bên trong dấu ngoặc vuông.

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972}

1 2 3 4 5

print(dictCar["model"])

Ví dụ 3.5.2. Truy cập kiểu Dictionary dùng khóa.

Kết quả: Honda Civic

Ngoài ra, chúng ta cũng có thể sử dụng hàm get() để truy cập item của Dictionary trong Python như trong ví dụ sau.

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6

} print(dictCar.get("model"))

Ví dụ 3.5.3. Truy cập kiểu Dictionary sử dụng hàm get().

Kết quả: Honda Civic

Chương 3. Lập trình có cấu trúc với Python 130

3.5.3 Các hàm cơ bản xử lý Dictionary trong Python

Thay đổi giá trị của một Dictionary trong Python: Chúng ta có thể thay đổi giá trị của một item cụ thể bằng khóa của nó:

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6 7

} dictCar["year"] = 2020 print(dictCar)

Ví dụ 3.5.4. Thay đổi giá trị của một Dictionary thông qua khóa.

Kết quả: {’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 2020}

Duyệt các item của Dictionary trong Python: Chúng ta có thể duyệt qua một Dictionary bằng cách sử dụng vòng lặp for. Khi duyệt một Dictionary bằng vòng lặp for, giá trị trả về là các khóa, khi đó ta có thể dùng hàm get() để lấy giá trị của khóa.

ictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

} for x in dictCar:

1 2 3 4 5 6 7

print(x, ": ", dictCar.get(x))

Ví dụ 3.5.5. Duyệt các item của Dictionary dùng vòng lặp for.

1 2 3

brand : Honda model : Honda Civic year : 1972

Kết quả:

Chúng ta cũng có thể sử dụng hàm values() để trả về các giá trị của Dictionary:

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

} for x in dictCar.values():

1 2 3 4 5 6 7

print(x)

Ví dụ 3.5.6. Duyệt các item của Dictionary dùng hàm values().

1 2 3

brand : Honda model : Honda Civic year : 1972

Kết quả:

3.5 Xử lý Dictionary 131

Kiểm tra nếu key tồn tại: Để xác định xem một khóa (key) được chỉ định có tồn tại trong từ điển hay không, hãy sử dụng từ khóa in.

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

} if "model" in dictCar:

print("Khoa \"model\" co ton tai.")

else:

print("Khoa \"model\" khong ton tai.")

1 2 3 4 5 6 7 8 9

Ví dụ 3.5.7. Duyệt các item của Dictionary dùng hàm values().

Kết quả: Khoa "model" co ton tai.

Độ dài của một Dictionary trong Python: Để xác định có bao nhiêu item (cặp khóa-giá trị) trong Dictionary chúng ta sử dụng hàm len().

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6

} print(len(dictCar))

Ví dụ 3.5.8. Duyệt các item của Dictionary dùng hàm values().

Kết quả: 3

Thêm các item vào Dictionary: Để thêm một item vào Dictionary được thực hiện bằng cách sử dụng khóa mới và gán giá trị cho nó.

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6 7

} dictCar["color"] = "yellow" print(dictCar)

Ví dụ 3.5.9. Duyệt các item của Dictionary dùng hàm values().

1

{’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 1972, ’color’: ’yellow’}

Kết quả:

Xóa item của Dictionary: Có nhiều phương pháp để loại bỏ các item của một Dictionary. • Xóa item của Dictionary bằng hàm pop()

Ví dụ 3.5.10. Hàm pop() xóa item với key được chỉ định.

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6 7

} dictCar.pop("model") print(dictCar)

Chương 3. Lập trình có cấu trúc với Python 132

Kết quả: {’brand’: ’Honda’, ’year’: 1972}

• Xóa item của Dictionary bằng hàm popitem()

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6 7

} dictCar.popitem() print(dictCar)

Ví dụ 3.5.11. Hàm popitem() xóa item cuối cùng.

Kết quả: {’brand’: ’Honda’, ’model’: ’Honda Civic’}

• Xóa item của Dictionary bằng từ khóa del

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6 7

} del dictCar["model"] print(dictCar)

Ví dụ 3.5.12. Lệnh del sẽ xóa item với key được chỉ định.

Kết quả: {’brand’: ’Honda’, ’year’: 1972}

• Xóa item của Dictionary bằng hàm clear()

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6 7

} dictCar.clear() print(dictCar)

Ví dụ 3.5.13. Hàm clear() xóa toàn bộ các item của Dictionary.

Kết quả: {}

3.5 Xử lý Dictionary 133

Sao chép Dictionary trong Python: Chúng ta không thể sao chép từ điển chỉ bằng cách gán dict2 = dict1, bởi vì dict2 sẽ chỉ là một tham chiếu đến dict1 và những thay đổi được thực hiện dict1 cũng sẽ tự động được thực hiện dict2. Có nhiều cách để tạo một bản sao, một trong các cách đó là sử dụng hàm copy() được xây dựng trong Dictionary.

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

1 2 3 4 5 6 7 8 9 10

} dict1 = dictCar # su dung toan tu = dict2 = dictCar.copy() # su dung ham copy() dictCar["color"] = "yellow" # thay doi dictCar print("dict1: ", dict1) print("dict2: ", dict2)

Ví dụ 3.5.14. Sao chép Dictionary trong Python dùng hàm copy().

1 2

dict1: {’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 1972, ’color’: ’yellow’} dict2: {’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 1972}

Kết quả:

Một cách khác để tạo một bản sao là sử dụng hàm tích hợp sẵn dict().

dictCar = {

"brand": "Honda", "model": "Honda Civic", "year": 1972

# su dung toan tu =

1 2 3 4 5 6 7 8 9 10

} dict1 = dictCar dict2 = dict(dictCar) # su dung ham dict() dictCar["color"] = "yellow" # thay doi dictCar print("dict1: ", dict1) print("dict2: ", dict2)

Ví dụ 3.5.15. Sao chép Dictionary trong Python dùng hàm dict().

1 2

dict1: {’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 1972, ’color’: ’yellow’} dict2: {’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 1972}

Kết quả:

Dictionary lồng nhau trong Python: Một Dictionary cũng có thể chứa nhiều Dictionary, điều này được gọi là từ điển lồng nhau.

myfamily = {

"child1" : {

1 2 3

"name" : "Nhuong",

Ví dụ 3.5.16. Tạo Dictionary lồng nhau.

"birthday" : 1983

}, "child2" : {

"name" : "Dien", "birthday" : 2010

}, "child3" : {

"name" : "Diep", "birthday" : 2016

}

4 5 6 7 8 9 10 11 12 13 14 15

} print(myfamily)

Chương 3. Lập trình có cấu trúc với Python 134

1 2 3

{’child1’: {’name’: ’Nhuong’, ’birthday’: 1983}, ’child2’: {’name’: ’Dien’, ’birthday’: 2010}, ’child3’: {’name’: ’Diep’, ’birthday’: 2016}}

Kết quả:

Với một khai báo khác rõ ràng, dể hiểu hơn, ví dụ trên tương đương với ví dụ sau:

child1 = {

"name" : "Nhuong", "birthday" : 1983

} child2 = {

"name" : "Dien", "birthday" : 2010

} child3 = {

"name" : "Diep", "birthday" : 2016

}

myfamily = {

"child1" : child1, "child2" : child2, "child3" : child3

}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

print(myfamily)

Ví dụ 3.5.17. .

1 2 3

{’child1’: {’name’: ’Nhuong’, ’birthday’: 1983}, ’child2’: {’name’: ’Dien’, ’birthday’: 2010}, ’child3’: {’name’: ’Diep’, ’birthday’: 2016}}

Kết quả:

Constructor dict() trong Python: Chúng ta có thể sử dụng constructor dict() để tạo một Dictionary mới.

3.6 Xử lý tập hợp (Set) 135

1 2

dictCar = dict(brand="Honda", model="Honda Civic", year=1972) print(dictCar)

Ví dụ 3.5.18. Sử dụng constructor dict() để tạo một Dictionary mới.

1

{’brand’: ’Honda’, ’model’: ’Honda Civic’, ’year’: 1972}

Kết quả:

Các hàm và phương thức đã được xây dựng sẵn cho Dictionary trong Python được cho trong Bảng 3.6 và Bảng 3.7.

Bảng 3.6: Một số hàm xử lý Dictionary khác trong Python

Tên hàm

Chức năng

Độ dài của dict. Nó sẽ là số item trong Dictionary này. Tạo ra một biểu diễn chuỗi có thể in được của một dict. Trả về kiểu của biến đã truyền. Nếu biến truyền là Dictionary, thì trả về kiểu Dictionary.

len(dict) str(dict) type(variable)

Bảng 3.7: Một số phương thức khác xử lý Dictionary trong Python

Tên phương thức

Chức năng

dict.clear() dict.copy() fromkeys(seq,value1)/ fromkeys(seq)

Xóa tất cả phần tử của dict. Trả về bản sao của dict. Được sử dụng để tạo một Dictionary mới từ dãy seq và value1. Dãy seq tạo nên các key và tất cả các key chia sẻ các giá trị từ value1. Nếu value1 không được cung cấp thì value các key được thiết lập là None. Trả về giá trị của key đã cho. Nếu key không có mặt thì trả về None. Trả về true nếu key là có mặt trong Dictionary, nếu không là false. Trả về tất cả các cặp (key-value) của một Dictionary. Trả về tất cả các key của một Dictionary. Thiết lập dict[key]=default nếu key là không tồn tại trong dict.

Được sử dụng để thêm các item của dictionary 2 vào Dictionary đầu tiên. Trả về tất cả các value của một Dictionary.

dict.get(key,default=None) dict.has-key(key) dict.items() dict.keys() dict.setdefault(key ,default=None) dict.update(dict2) dict.values()

3.6 Xử lý tập hợp (Set)

3.6.1 Khái niệm và cấu trúc của tập hợp

Kiểu dữ liệu Set trong Python là một collection không có thứ tự, không có chỉ mục. Không cho phép chứa dữ liệu trùng lặp. Set trong Python được khai báo với các dấu ngoặc nhọn {}.

1 2

setFruits = {"apple", "cherry", "banana"} print(setFruits)

Ví dụ 3.6.1. Khai báo tập hợp trong Python.

Chương 3. Lập trình có cấu trúc với Python 136

3.6.2 Truy cập các giá trị của tập hợp trong Python

Chúng ta không thể truy cập các phần tử trong một Set bằng cách sử dụng chỉ mục vì Set không lưu trữ các phần tử theo thứ tự nhập ban đầu. Thay vào đó, chúng ta có thể sử dụng vòng lặp for để truy cập các phần tử của một Set.

setFruits = {"apple", "cherry", "banana"} for x in setFruits:

1 2 3

print(x)

Ví dụ 3.6.2. Duyệt các phần tử của một Set và in các giá trị ra màn hình.

apple cherry banana

1 2 3

Kết quả:

Để kiểm tra xem phần tử có tồn tại trong Set hay không ta có thể sử dụng từ khóa in.

1 2 3

setFruits = {"apple", "cherry", "banana"} x = "apple" in setFruits print(x)

Ví dụ 3.6.3. Duyệt các phần tử của một Set và in các giá trị ra màn hình.

Kết quả: True

3.6.3 Các hàm xử lý tập hợp trong Python

- Thay đổi các giá trị của một item trong Set: Khi một set được tạo ra, chúng ta không thể thay đổi các item của nó, nhưng chúng ta có thể thêm các item mới. Thêm các item vào một set trong Python, chúng ta sử dụng hàm add().

1 2 3

setFruits = {"apple", "cherry", "banana"} setFruits.add("kiwi") print(setFruits)

Ví dụ 3.6.4. Sử dụng hàm add() để thêm một item vào một set.

1

{’banana’, ’kiwi’, ’apple’, ’cherry’}

Kết quả:

Để thêm nhiều item vào một set, sử dụng hàm update().

1 2 3

setFruits = {"apple", "cherry", "banana"} setFruits.update(["orange", "mango", "grapes"]) print(setFruits)

Ví dụ 3.6.5. Sử dụng hàm update() để thêm nhiều item vào một set.

Kết quả:

1

{’grapes’, ’orange’, ’mango’, ’cherry’, ’apple’, ’banana’}

3.6 Xử lý tập hợp (Set) 137

- Độ dài của một Set trong Python: Hàm len() được sử dụng để xem có bao nhiêu item trong một set.

1 2

setFruits = {"apple", "cherry", "banana"} print(len(setFruits))

Ví dụ 3.6.6. Sử dụng hàm len() xem có bao nhiêu item trong một set.

Kết quả: 3

- Xóa một phần tử từ Set trong Python: Để xóa một phần tử trong một set, chúng ta sử dụng hàm remove() hoặc discard().

setFruits = {"apple", "cherry", "banana"} setFruits.remove("banana") print(setFruits)

1 2 3

Ví dụ 3.6.7. Xóa phần tử "banana" bằng hàm remove().

Kết quả: {’cherry’, ’apple’}

setFruits = {"apple", "cherry", "banana"} setFruits.discard("banana") print(setFruits)

1 2 3

Ví dụ 3.6.8. Xóa phần tử "banana" bằng hàm discard().

Kết quả: {’cherry’, ’apple’}

- Sử dụng hàm pop(): Chúng ta cũng có thể sử dụng hàm pop() để xóa một phần tử, nhưng phương thức này sẽ xóa phần tử cuối cùng. Nhưng set không có thứ tự, vì vậy chúng ta sẽ không biết mục nào bị xóa. Giá trị trả về của hàm pop() là phần tử bị xóa.

setFruits = {"apple", "cherry", "banana"} x = setFruits.pop() print(x)

1 2 3

Ví dụ 3.6.9. Xóa phần tử "banana" bằng hàm pop().

Kết quả: cherry

setFruits = {"apple", "cherry", "banana"} setFruits.clear() print(setFruits)

1 2 3

Ví dụ 3.6.10. Xóa toàn bộ set bằng hàm clear().

Kết quả: set()

- Sử dụng từ khóa del: Lệnh del sẽ xóa hoàn toàn set.

Chương 3. Lập trình có cấu trúc với Python 138

1 2 3

setFruits = {"apple", "cherry", "banana"} del setFruits print(setFruits)

Ví dụ 3.6.11. Xóa hoàn toàn set bằng hàm del.

Kết quả: NameError: name ’setFruits’ is not defined

Nối 2 set trong Python: Chúng ta có thể sử dụng hàm union() trả về một set mới chứa tất cả các phần tử từ cả hai bộ hoặc hàm update() chèn tất cả các mục từ set này sang set khác.

set1 = {"a", "b" , "c"} set2 = {1, 2, 3, ’c’}

1 2 3 4 5

set3 = set1.union(set2) print(set3)

Ví dụ 3.6.12. Nối 2 set sử dụng hàm union().

Kết quả: {1, 2, 3, ’c’, ’b’, ’a’}

set1 = {"a", "b" , "c"} set2 = {1, 2, 3, ’c’}

1 2 3 4 5

set1.update(set2) print(set1)

Ví dụ 3.6.13. Nối 2 set sử dụng hàm update().

Kết quả: {1, 2, ’b’, 3, ’c’, ’a’}

Constructor set(): Chúng ta có thể sử dụng hàm tạo set() để tạo một set.

1 2

setFuits = set(("apple", "banana", "cherry")) print(setFuits)

Ví dụ 3.6.14. Tạo set sử dụng hàm set().

Kết quả: {’banana’, ’cherry’, ’apple’}

Bảng 3.8 liệt kê các hàm đã được xây dựng sẵn để thao tác với Set trong Python.

3.7 Xử lý mảng (array) 139

Bảng 3.8: Một số hàm xử lý tập hợp trong Python

Tên hàm

Chức năng

add() clear() copy() difference() difference_update() discard() intersection() intersection_update() isdisjoint()

issubset() issuperset() pop() remove() symmetric_difference()

symmetric_difference_update()

Thêm một phần tử tới set. Xóa tất cả các phần tử của một set. Returns a copy of the set. Trả về một set chứa các phần tử khác nhau của 2 hoặc nhiều set. Xóa các phần tử của set này mà tồn tại trong set khác. Xóa phần tử được chỉ định. Trả về một set mà các phần tử của nó tồn tại trong cả 2 set đã cho. Xóa các phần tử của set này mà không tồn tại trong set kia. Trả về True nếu không có phần tử nào trong một set trùng với phần tử trong set 2. Trả về False nếu có bất kỳ phần tử nào trong set ban đầu giống với set 2. Trả về True nếu tất cả các phần tử trong một set 1 tồn tại trong set 2, ngược lại trả về false. Trả về true nếu tất cả các phần tử trong set2 tồn tại trong một set, ngược lại trả về false. Xóa phần tử cuối cùng của một set. Xóa phần tử được chỉ định. Trả về một set mà chứa các phần tử của cả 2 set đã cho, sao cho các phần tử này tồn tại trong set này nhưng không tồn tại trong set kia. Cập nhật set ban đầu bằng việc loại bỏ phần tử của cả 2 set đã cho, sao cho các phần tử này tồn tại trong set này nhưng không tồn tại trong set kia. Trả về môt set mà được nối từ 2 set với nhau. Nối set này với set khác.

union() update()

3.7 Xử lý mảng (array)

Tạo mảng trong Python là một tập hợp mục được lưu trữ tại các vị trí bộ nhớ liền kề. Ý tưởng ở đây là lưu trữ nhiều mục cùng loại với nhau. Hành động này hỗ trợ người dùng tính toán vị trí của từng phần tử dễ dàng hơn bằng cách thêm một giá trị bù vào giá trị cơ sở, tức là vị trí bộ nhớ của phần tử đầu tiên trong mảng (thường được biểu thị bằng tên của mảng).

Mảng có thể được mô đun tên array xử lý trong Python. Chúng có thể hữu ích khi chúng ta chỉ phải xử lý một giá trị kiểu dữ liệu. Chúng ta có thể xem list là mảng. Tuy nhiên, chúng ta không thể giới hạn kiểu thành phần được lưu trong danh sách. Nếu tạo mảng bằng môđun array thì toàn bộ thành phần của mảng sẽ phải thuộc cùng một kiểu. Nếu chúng ta muốn tạo mảng thực sự trong Python, chúng ta cần phải sử dụng cấu trúc dữ liệu mảng của NumPy. Để giải quyết các vấn đề toán học thì mảng NumPy sẽ hiệu quả hơn.

3.7.1 Thư viện array trong Python

1

a= [1, 3.5, "Hello"]

Chúng ta có thể thao tác với list giống như mảng nhưng không thể ép kiểu phần tử được lưu trữ trong list. Ví dụ:

Nếu chúng ta tạo mảng sử dụng thư viện array, tất cả các phần tử của mảng phải có cùng kiểu số.

Chương 3. Lập trình có cấu trúc với Python 140

1 2 3 4 5 6

import array as arr # Chay code nay se bao loi vi cac kieu khac nhau a = arr.array(’d’, [1, 3.5, "Hello"]) # Thu vien array yeu cau cac phan tu phai co cung kieu so a = arr.array(’d’,[1.1, 3.5, 4.5]) print(a)

Ví dụ 3.7.1. Tạo mảng sử dụng thư viện array.

Ví dụ trên trên tạo mảng có kiểu float. Chữ ’d’ là mã kiểu, quyết định kiểu của mảng trong quá trình tạo. Bảng 3.9 liệt kê những mã kiểu thường dùng.

Bảng 3.9: Những mã kiểu thường dùng trong thư viện array

Mã kiểu

Kiểu Python

Kích thước tối thiểu tính theo byte

int Unicode character int int float float

1 2 2 4 4 8

’b’, ’B’ ’u’ ’h’, ’H’, ’i’, ’I’ ’l’, ’L’ ’f’ ’d’

Ghi chú: Mã code ’u’ cho các ký tự Unicode không còn được chấp nhận từ phiên bản Python 3.3.

3.7.2 Truy cập vào các phần tử của mảng

Chúng ta sử dụng chỉ số index để truy cập đến các phần tử của mảng. Index cũng bắt đầu từ 0 tương tự như trong list.

1 2 3 4 5

import array as arr a = arr.array(’i’, [2, 4, 6, 8]) print("Phan tu dau tien:", a[0]) print("Phan tu thu 2:", a[1]) print("Phan tu cuoi cung:", a[-1])

Ví dụ 3.7.2. Truy cập vào các phần tử của mảng thông qua chỉ số.

1 2 3

Phan tu dau tien: 2 Phan tu thu 2: 4 Phan tu cuoi cung: 8

Thực thi chương trình cho kết quả sau:

Chúng ta cũng có thể truy cập vào một dải phần tử trong mảng, sử dụng toán tử cắt lát : như sau:

Ví dụ 3.7.3. Truy cập vào một dải phần tử trong mảng sử dụng toán tử cắt lát :.

import array as arr

numbers_list = [5, 85, 65, 15, 95, 52, 36, 25] numbers_array = arr.array(’i’, numbers_list)

print(numbers_array[2:5]) # Phan tu thu 3 den 5 print(numbers_array[:-5]) # Phan tu dau tien den 4 print(numbers_array[5:]) # Phan tu thu 6 den het print(numbers_array[:]) # Phan tu dau tien den cuoi cung

1 2 3 4 5 6 7 8 9

141 3.7 Xử lý mảng (array)

array(’i’, [65, 15, 95]) array(’i’, [5, 85, 65]) array(’i’, [52, 36, 25]) array(’i’, [5, 85, 65, 15, 95, 52, 36, 25])

1 2 3 4

Thực thi chương trình cho kết quả sau:

3.7.3 Thay đổi, thêm phần tử trong mảng

Mảng có thể thay đổi, các phần tử của nó có thể thay đổi theo cách tương tự như list.

import array as arr numbers = arr.array(’i’, [1, 1, 2, 5, 7, 9])

numbers[0] = 0 # thay doi phan tu dau tien bang 0 print(numbers)

numbers[2:5] = arr.array(’i’, [4, 6, 8]) # thay phan tu thu 3 den thu 5 print(numbers)

1 2 3 4 5 6 7 8

Ví dụ 3.7.4. Thay đổi phần tử trong mảng array.

array(’i’, [0, 1, 2, 5, 7, 9]) array(’i’, [0, 1, 4, 6, 8, 9])

1 2

Thực thi chương trình cho kết quả sau:

Chúng ta có thể thêm một mục vào mảng sử dụng append() hoặc thêm vài mục sử dụng extend():

import array as arr

numbers = arr.array(’i’, [3, 5, 7])

numbers.append(4) print(numbers)

numbers.extend([5, 6, 7]) # extend() noi vao cuoi mang print(numbers)

1 2 3 4 5 6 7 8 9

Ví dụ 3.7.5. Thêm một mục vào trong mảng array.

Chương 3. Lập trình có cấu trúc với Python 142

1 2

array(’i’, [3, 5, 7, 4]) array(’i’, [3, 5, 7, 4, 5, 6, 7])

Thực thi chương trình cho kết quả sau:

Chúng ta có thể nối hai mảng lại thành một nhờ toán tử +:

import array as arr mang_le = arr.array(’i’, [3, 5, 7]) mang_chan = arr.array(’i’, [2, 6, 8]) numbers = arr.array(’i’) # tao mang trong numbers = mang_le + mang_chan print(numbers)

1 2 3 4 5 6

Ví dụ 3.7.6. Thay đổi phần tử trong mảng array.

1

array(’i’, [3, 5, 7, 2, 6, 8])

Thực thi chương trình cho kết quả sau:

3.7.4 Xóa phần tử của mảng

Để xóa một hoặc nhiều phần tử của mảng ta sử dụng lệnh del.

# xoa toan bo mang

import array as arr number = arr.array(’i’, [1, 3, 3, 5, 7]) del number[2] # xoa phan tu thu 3 print(number) # Output: array(’i’, [1, 3, 5, 7]) del number print(number) # Error: array ’number’ is not defined

1 2 3 4 5 6

Ví dụ 3.7.7. Xóa phần tử của mảng.

Chúng ta có thể sử dụng remove() để xóa mục đã cho hoặc pop() để xóa mục với index cho trước:

import array as arr

numbers = arr.array(’i’, [1, 1, 3, 5, 9]) numbers.remove(1) print(numbers) print(numbers.pop(2)) print(numbers)

1 2 3 4 5 6 7

Ví dụ 3.7.8. Xóa phần tử của mảng sử dụng remove(), pop().

Output: array(’i’, [1, 3, 5, 9]) 12 Output: array(’i’, [1, 3, 9])

1 2 3

Thực thi chương trình cho kết quả sau:

3.7 Xử lý mảng (array) 143

Lưu ý: Trên thực tế, List linh hoạt hơn mảng, chúng có thể lưu trữ phần tử với nhiều kiểu dữ liệu khác nhau, bao gồm cả chuỗi. List cũng nhanh hơn mảng, vậy thì tại sao lại cần dùng mảng? Nếu chúng ta phải thực hiện những phép tính toán toán học trên mảng và ma trận thì nên sử dụng thư viện NumPy. Trừ khi thực sự cần đến mảng để giao tiếp với các code C, ngược lại thì không nên sử dụng.

3.7.5 Độ phức tạp khi loại bỏ array trong Python

Trong mảng của Python, chúng ta có nhiều cách để in toàn bộ mảng với tất cả các phần tử. Tuy nhiên, để in một phạm vi phần tử cụ thể từ mảng, chúng ta cần dùng toán tử slice. Toán tử này được thực hiện trên mảng cùng với dấu hai chấm (:). Để in các phần tử ngay từ đầu tới mảng dùng [:Index], để in các phần tử ở cuối dùng [:-Index], để in các phần tử từ index cụ thể cho tới cuối dùng [Index:], để in các phần tử trong một phạm vi, dùng [Start Index:End Index] và để in toàn bộ danh sách bằng toán tử slice, dùng [:]. Ngoài ra, để in toàn bộ mảng theo thứ tự đảo ngược, hãy sử dụng [::-1].

import array as arr l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # Tao danh sach

a = arr.array(’i’, l) print("Mang ban dau: ") for i in (a):

print(i, end=" ")

# In cac nhan to cua mot mang dung toan tu Slice Sliced_array = a[3:8] print("\n Tach cac phan tu trong mang 3-8:") print(Sliced_array)

# In cac nhan to tu diem xac dinh truoc toi cuoi Sliced_array = a[5:] print("\n Tach phan tu trong mang tu thu 5 toi cuoi") print(Sliced_array)

# In cac nhan to tu diem bat dau toi cuoi Sliced_array = a[:] print("\n In tat ca cac phan tu bang toan tu slice: ") print(Sliced_array)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

Ví dụ 3.7.9. Độ phức tạp khi xóa phần tử trong mảng

Mang ban dau: 1 2 3 4 5 6 7 8 9 10 Tach cac phan tu trong mang 3-8: array(’i’, [4, 5, 6, 7, 8])

Tach phan tu trong mang tu thu 5 toi cuoi:

1 2 3 4 5 6

Kết quả:

array(’i’, [6, 7, 8, 9, 10])

7 8 9 10

In tat ca cac phan tu bang toan tu slice: array(’i’, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

Chương 3. Lập trình có cấu trúc với Python 144

3.8 Xử lý tập tin (file)

3.8.1 Vì sao phải lưu tập tin

Xử lý file trong Python là một công cụ mạnh mẽ và linh hoạt, có thể được dùng để triển khai một loạt các hoạt động khác nhau. Tuy nhiên, điều quan trọng ở đây là chúng ta cần xem xét cẩn thận ưu và nhược điểm của xử lý file khi viết các chương trình Python, để đảm bảo rằng code an toàn, đáng tin cậy và được triển khai tốt. File hay còn gọi là tệp, tập tin. File là tập hợp của các thông tin được đặt tên và lưu trữ trên bộ nhớ máy tính như đĩa cứng, đĩa mềm, CD, DVD,... Khi muốn đọc hoặc ghi file, chúng ta cần phải mở file trước. Khi hoàn thành, file cần phải được đóng lại để các tài nguyên được gắn với file được giải phóng.

Python cũng hỗ trợ xử lý file và cho phép người dùng xử lý tập tin, ví dụ đọc và ghi file, cùng với nhiều lựa chọn xử lý file khác để thao tác trên file. Khái niệm xử lý file đã có ở hầu hết mọi ngôn ngữ lập trình, nhưng việc triển khai khá phức tạp và dài dòng. Tuy nhiên, giống như các khái niệm khác trong Python, khái niệm xử lý file cũng dễ dàng và ngắn gọn.

Python xử lý các file khác nhau dưới dạng văn bản hoặc nhị phân. Điều này rất quan trọng. Mỗi dòng code đều bao gồm một chuỗi ký tự và chúng tạo thành một file văn bản. Mỗi dòng của file được kết thúc bằng một ký tự đặc biệt, mang tên EOL hay ký tự kết dòng như dấu phẩy hoặc ký tự báo dòng mới. Nó chấm dứt dòng hiện tại và cho trình phiên dịch biết một dòng mới đã bắt đầu. Giờ chúng ta hãy cùng nhau tìm hiểu cách đọc dữ liệu từ file trong Python.

3.8.2.1 Mở file (open)

3.8.2 Các thao tác trên tập tin với Python

Trong Python, có một hàm được xây dựng sẵn phục vụ cho việc mở file là open(). Hàm này trả về đối tượng file hay còn gọi là “handle” vì chúng ta có thể thực hiện các hoạt động đọc, ghi, sửa đổi trên file đó.

• Cú pháp: fileObject = open(file_name [, access_mode][, buffering]) • Các mode (chế độ) mở một file được liệt kê trong Bảng 3.10.

Thuộc tính của file:

• file.closed: Trả về True nếu file đã đóng, ngược lại là False. • file.mode: Trả về chế độ truy cập của file đang được mở. • file.name: Trả về tên của file.

3.8 Xử lý tập tin (file) 145

Bảng 3.10: Các mode (chế độ) mở một file trong Python

Chế độ

Mô tả

Chế độ chỉ được phép đọc. Chế độ được phép đọc và ghi. Mở file chế độ đọc cho định dạng nhị phân. Con trỏ tại phần bắt đầu của file.

‘r’ ‘r+’ ‘rb’ ‘rb+’, ‘r+b’ Mở file để đọc và ghi trong định dạng nhị phân. Con trỏ tại phần bắt đầu của file. ‘w’

‘w+’

‘wb’

Mở file để ghi. Nếu file không tồn tại thì sẽ tạo mới file và ghi nội dung, nếu file đã tồn tại thì sẽ bị cắt bớt (truncate) và ghi đè lên nội dung cũ. Mở file để đọc và ghi. Nếu file không tồn tại thì sẽ tạo mới file và ghi nội dung, nếu file đã tồn tại thì sẽ bị cắt bớt (truncate) và ghi đè lên nội dung cũ. Mở file để ghi cho dạng nhị phân. Nếu file không tồn tại thì sẽ tạo mới file và ghi nội dung, nếu file đã tồn tại thì sẽ bị cắt bớt (truncate) và ghi đè lên nội dung cũ.

‘a’

‘a+’

‘ab’

‘wb+’, ‘w+b’ Mở file để đọc và ghi cho dạng nhị phân. Nếu file không tồn tại thì sẽ tạo mới file và ghi nội dung, nếu file đã tồn tại thì sẽ bị cắt bớt (truncate) và ghi đè lên nội dung cũ. Mở file chế độ ghi tiếp. Nếu file đã tồn tại rồi thì nó sẽ ghi tiếp nội dung vào cuối file, nếu file không tồn tại thì tạo một file mới và ghi nội dung vào đó. Mở file chế độ đọc và ghi tiếp. Nếu file đã tồn tại rồi thì nó sẽ ghi tiếp nội dung vào cuối file, nếu file không tồn tại thì tạo một file mới và ghi nội dung vào đó. Mở file chế độ ghi tiếp ở dạng nhị phân. Nếu file đã tồn tại rồi thì nó sẽ ghi tiếp nội dung vào cuối file, nếu file không tồn tại thì tạo một file mới và ghi nội dung vào đó.

‘ab+’, ‘a+b’ Mở file chế độ đọc và ghi tiếp ở dạng nhị phân. Nếu file đã tồn tại rồi thì nó sẽ ghi tiếp nội

‘x’

‘x+’

‘xb’

dung vào cuối file, nếu file không tồn tại thì tạo một file mới và ghi nội dung vào đó. Mở file chế độ ghi. Tạo file độc quyền mới (exclusive creation) và ghi nội dung, nếu file đã tồn tại thì chương trình sẽ báo lỗi. Mở file chế độ đọc và ghi. Tạo file độc quyền mới (exclusive creation) và ghi nội dung, nếu file đã tồn tại thì chương trình sẽ báo lỗi. Mở file chế độ ghi dạng nhị phân. Tạo file độc quyền mới và ghi nội dung, nếu file đã tồn tại thì chương trình sẽ báo lỗi.

‘xb+’, ‘x+b’ Mở file chế độ đọc và ghi dạng nhị phân. Tạo file độc quyền mới và ghi nội dung,

nếu file đã tồn tại thì chương trình sẽ báo lỗi. Mở file ở chế độ nhị phân. Mở file ở chế độ văn bản (mặc định).

‘b’ ‘t’

Chúng ta có thể xác định cách thức mà tập tin được mở ra để làm gì như: read, write, append,... Đây là thông số tùy chọn có thể có hoặc không. Ngoài ra, người lập trình cũng có thể định rõ file mở ra dạng văn bản hay dạng nhị phân. Chế độ truy cập file mặc định là read (r). Khi dùng chế độ này chúng ta sẽ nhận được giá trị chuỗi trả về dạng văn bản. Mặt khác nếu giá trị trả về ở dạng byte thì tệp được mở ra là hình ảnh hoặc exe.

1 2 3 4

file = open("vidu.txt", "wb") #Mo file vidu.txt print ("Ten cua file la: ", file.name) #Ten cua file la: vidu.txt print ("File co dong khong?:", file.closed) #File co dong hoac khong?: False print ("Che do mo file:",file.mode) #Che do mo file: wb

Ví dụ 3.8.1. Thao tác mở file.

Ví dụ 3.8.2. Thao tác mở file với các tham số khác nhau.

# mo file mode ’r’ hoac ’rt’ de doc

1 2 3

f = open("test.txt") f = open("test.txt",’w’) # mo file mode ’w’ de ghi f = open("img.bmp",’r+b’) # mo file mode ’r+b’ de doc va ghi dang nhi phan

Chương 3. Lập trình có cấu trúc với Python 146

1

f = open("test.txt",mode = ’r’,encoding = ’utf-8’)

3.8.2.2 Đóng file (close)

Ví dụ 3.8.3. Khi làm việc với các tệp ở chế độ văn bản, chúng ta nên chỉ định loại mã hóa.

Sau khi thực hiện xong các thao tác với file thì chúng ta cần đóng nó lại. Đóng file để đảm bảo quy chế đóng mở và giải phóng bộ nhớ cho chương trình nên điều này là cần thiết. Việc đóng file được xây dựng trong Python bằng hàm close(). Python cũng tự động đóng một file khi đối tượng tham chiếu của file đã được tái gán cho một file khác. Tuy nhiên, sử dụng phương thức close() để đóng một file vẫn tốt hơn. - Cú pháp: fileObject.close()

1 2

file = open("vidu.txt", "r") #Mo file file.close() #Dong file

Ví dụ 3.8.4. Đóng file.

Tuy nhiên cách này chưa thực sự đảm bảo. Vẫn có trường hợp một số ngoại lệ xảy ra khi chúng ta thực hiện các thao tác với file khiến chương trình tự động thoát ra mà không đóng tệp. Để đảm bảo hơn, chúng ta nên sử dụng khối lệnh try...finally (finally sẽ luôn luôn được thực thi bất chấp có hay không ngoại lệ) ở đây.

try:

f = open("test.txt",encoding = ’utf-8’) # thuc hien cac thao tac voi tep

finally:

1 2 3 4

f.close()

Ví dụ 3.8.5. Đóng file sử dụng khối lệnh try...finally.

Bằng cách trên, chúng ta có thể yên tâm file được đóng đúng ngay cả khi phát sinh ngoại lệ khiến chương trình dừng đột ngột. Một cách khác để đóng file là sử dụng câu lệnh with. Lệnh with cho phép bảo đảm rằng file luôn luôn được đóng mà không cần biết những logic xử lý bên trong.

1

with open("test.txt",encoding = ’utf-8’) as f: # thuc hien cac thao tac voi tep

Ví dụ 3.8.6. Đóng file sử dụng câu lệnh with.

So sánh hai cách viết này thì chúng ta đã thấy rất rõ ràng rằng, sử dụng with cho chúng ta cách viết code ngắn gọn hơn.

3.8.2.3 Ghi file (write)

3.8 Xử lý tập tin (file) 147

Để ghi một file ta cần mở file bằng cú pháp để ghi, sử dụng mode write ‘w’, append ‘a’ hoặc mode tạo độc quyền ‘x’. Chúng ta cần cẩn thận với chế độ ‘w’ vì nó ghi đè lên nội dung nếu file đã tồn tại, các dữ liệu trước đó sẽ bị xóa. Nếu ghi vào file dạng nhị phân các chuỗi văn bản hoặc chuỗi dạng byte thì kết quả trả về sẽ là số kí tự được ghi vào file. - Cú pháp: fileObject.write(string)

1 2 3

file = open("vidu.txt", "wb") #Mo file vidu.txt file.write("Python la ngon ngu lap trinh") #Noi dung ghi file.close() #Dong file

3.8.2.4 Đọc file (read/tell)

Ví dụ 3.8.7. Ghi file.

Tương tự ghi file, để đọc một file chúng ta cần mở file bằng cú pháp để đọc sử dụng mode read ‘r’.

Dùng read(size): Sử dụng phương thức read(size) để lấy về dữ liệu có kích thước bằng size. Nếu để trống tham số này thì nó sẽ đọc hết file hoặc nếu file quá lớn thì nó sẽ đọc đến khi giới hạn của bộ nhớ cho phép.

f = open("test.txt",’r’,encoding = ’utf-8’) a = f.read(10) # doc 10 ki tu dau tien print(’Noi dung 11 ki tu dau la:\n’, (a)) b = f.read(30) # doc 30 ki tu tiep theo print(’Noi dung 35 ki tu tiep theo la:\n’, (b)) c = f.read() # doc phan con lai print(’Noi dung phan con lai la:\n’, (c))

1 2 3 4 5 6 7

Ví dụ 3.8.8. Đọc file dùng read(size).

Noi dung 10 ki tu dau la: Giao trinh Noi dung 30 ki tu tiep theo la: Phat trien ung dung voi Python Noi dung phan con lai la: Nhom tac gia

1 2 3

3.8.2.5 Đổi tên file (rename)

Kết quả:

- Cú pháp: os.rename("", "")

# os la mot module tich hop san voi Python. # Module nay cho phep chung ta thao tac voi tep va thu muc. import os # Doi ten vidu.txt thanh baitap.txt os.rename("vidu.txt", "baitap.txt")

1 2 3 4 5

Ví dụ 3.8.9. Đổi tên file.

3.8.2.6 Xóa file (remove)

Chương 3. Lập trình có cấu trúc với Python 148

Cú pháp: os.remove("")

1 2 3 4

# os la mot module tich hop san voi Python. # Module nay cho phep chung ta thao tac voi tep va thu muc. import os os.remove("vidu.txt") #Xoa file vidu.txt

3.8.2.7 Kiểm soát con trỏ file

Ví dụ 3.8.10. Xóa file.

Chúng ta có thể thấy, con trỏ file rất quan trọng, nó dẫn đường cho việc đọc file, viết file. Do đó, chúng ta cũng cần phải kiểm soát được nó với các hàm tell() và phương thức seek.

• Hàm tell() cho biết vị trí con trỏ hiện tại bên trong file. • Hàm seek(offset[, from]) thay đổi vị trí con trỏ hiện tại bên trong file. Trong đó, tham số offset là chỉ số byte để được di chuyển. Tham số from xác định vị trí tham chiếu mà từ đó byte được di chuyển. Nếu from là 0 thì sử dụng phần đầu file như là vị trí tham chiếu. Nếu from là 2 thì sử dụng phần cuối file như là vị trí tham chiếu.

# Mo file file = open("vidu.txt", "r+") str = file.read(10); print ("Chuoi da doc la:", str) #Chuoi da doc la: Python la

# Kiem tra con tro hien tai vitri = file.tell(); print ("Con tro hien tai:", vitri) #Con tro hien tai: 10

# Dat lai vi tri con tro tai vi tri dau file vitri = file.seek(0, 0); str = file.read(10); print ("Chuoi da doc la:", str) #Chuoi da doc la: Python la

# Dong file file.close()

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Ví dụ 3.8.11. Xác định vị trí file.

3.8.3.1 Xử lý file text

3.8.3 Các thao tác xử lý file text, XML, JSON, CVS và Excel

Danh sách đầy đủ các phương thức xử lý file text được liệt kê trong Bảng 3.11.

3.8 Xử lý tập tin (file) 149

Bảng 3.11: Các phương thức xử lý file text trong Python

Phương thức

Mô tả

close() fileno() flush() isatty() read(n) readable() readline(n=-1) readlines(n=-1)

Đóng một file đang mở. Nó không thực thi được nếu tập tin đã bị đóng. Trả về một số nguyên mô tả file (file descriptor). Xóa sạch bộ nhớ đệm của luồng file. Trả về TRUE nếu file được kết nối với một thiết bị đầu cuối. Đọc n kí tự trong file. Trả về TRUE nếu file có thể đọc được. Đọc và trả về một dòng từ file. Đọc nhiều nhất n byte/ký tự nếu được Đọc và trả về một danh sách các dòng từ file. chỉ định. Đọc nhiều nhất n byte/ký tự nếu được chỉ định. Thay đổi vị trí hiện tại bên trong file. Trả về TRUE nếu luồng hỗ trợ truy cập ngẫu nhiên. Trả về vị trí hiện tại bên trong file. Cắt gọn kích cỡ file thành kích cỡ tham số size. Trả về True nếu file có thể ghi được. Ghi s kí tự vào trong file và trả về. Ghi một danh sách các dòng và file.

seek(offset,from=SEEK_SET) seekable() tell() truncate(size=None) writable() write(s) writelines(lines)

Phương thức readline() cho phép đọc từng dòng trong file:

f = open("test.txt",’r’,encoding = ’utf-8’) a = f.readline()print (’Noi dung dong dau: ’, (a)) b = f.readline()print (’Noi dung dong 2: ’, (b)) c = f.readline()print (’Noi dung dong 3: ’, (c)) d = f.readline()print (’Noi dung dong 4: ’, (d))

1 2 3 4 5

Ví dụ 3.8.12. Đọc từng dòng trong file với phương thức readline().

Phương thức readlines() trả về toàn bộ các dòng còn lại trong file và trả về giá trị rỗng khi kết thúc file.

f = open("test.txt",’r’,encoding = ’utf-8’) a = f.readline() print (’Noi dung dong dau: ’, (a))b = f.readlines() print (’Noi dung cac dong con lai: \n’, (b)) c = f.readlines() print (’Noi dung cac dong con lai: \n’, (c))

1 2 3 4 5 6

3.8.3.2 Xử lý XML file

Ví dụ 3.8.13. Đọc toàn bộ các dòng trong file với phương thức readlines().

Thư viện Python chuẩn cung cấp các Interface hữu ích để làm việc với XML. Hai APIs cơ bản và được sử dụng nhiều nhât là SAX và DOM. SAX (viết tắt của Simple API for XML) là read-only trong khi DOM (viết tắt của Document Object Model) cho phép tạo các thay đổi tới XML file.

Chương 3. Lập trình có cấu trúc với Python 150

Phân tích cú pháp XML với SAX APIs: Chúng ta cần tạo riêng một ContentHandler là lớp con của xml.sax.ContentHandler. ContentHandler sẽ xử lý các tag cụ thể và các thuộc tính của XML. Một đối tượng ContentHandler cung cấp các phương thức để xử lý các sự kiện parsing khác nhau. Phương thức startDocument và endDocument được gọi tại phần bắt đầu và phần cuối của XML file. Phương thức characters(text) để truyền dữ liệu ký tự của XML thông qua tham số text.

Đối tượng ContentHandler được gọi tại phần bắt đầu và phần cuối của mỗi phần tử. Nếu Parser không trong namespace mode, thì các phương thức startElement(tag, thuoc_tinh) và endElement(tag) được gọi; nếu không thì, các phương thức tương ứng startElementNS và endElementNS được gọi. Ở đây, tham số tag là thẻ và thuoc_tinh là một đối tượng At- tributes.

1

xml.sax.make_parser([parser_list])

Phương thức make_parser trong Python: Phương thức sau tạo một đối tượng parser mới và trả về nó. Đối tượng parser đã được tạo này sẽ là kiểu parser đầu tiên mà hệ thống tìm thấy. Tham số parser_list là tùy ý, bao gồm một danh sách các parser để sử dụng, tất cả phải triển khai phương thức make_parser.

1

xml.sax.parse( xmlfile, contenthandler[, errorhandler])

Phương thức parse trong Python: Phương thức này tạo một SAX parser và sử dụng nó để phân tích cú pháp một tài liệu.

1

xml.sax.parseString(xmlstring, contenthandler[, errorhandler])

Các tham số trong phương thức gồm: • xmlfile: Đây là tên của XML file để đọc từ đó. • contenthandler: Đây phải là một đối tượng ContentHandler. • errorhandler: Nếu được xác định, thì nó phải là một đối tượng SAX ErrorHandler. Phương thức parseString trong Python: Phương thức này cũng dùng để tạo một SAX parser và để phân tích cú pháp XML string đã cho.

Các tham số trong phương thức gồm: • xmlstring: Là tên của XML string để đọc từ đó. • contenthandler: Phải là một đối tượng ContentHandler. • errorhandler: Nếu được xác định, thì nó phải là một đối tượng SAX ErrorHandler.

import xml.sax class Phim BoHandler( xml.sax.ContentHandler ):

def __init__(self):

1 2 3 4 5 6 7

self.CurrentData = "" self.type = "" self.format = "" self.year = ""

Ví dụ 3.8.14. Xử lý file XML.

self.rating = "" self.stars = "" self.description = ""

def startElement(self, tag, attributes): # Goi khi mot phan tu bat dau

self.CurrentData = tag if tag == "movie":

print "*****Phim Bo*****" title = attributes["title"] print "Ten Phim:", title

def endElement(self, tag): # Goi khi mot phan tu ket thuc

if self.CurrentData == "type": print "The loai:", self.type elif self.CurrentData == "format": print "Dinh dang:", self.format

elif self.CurrentData == "year":

print "Nam:", self.year

elif self.CurrentData == "rating": print "Rating:", self.rating elif self.CurrentData == "stars": print "Dien vien:", self.stars

elif self.CurrentData == "description": print "Gioi thieu:", self.description

self.CurrentData = ""

def characters(self, content): # Goi khi mot ky tu duoc doc

if self.CurrentData == "type":

self.type = content

elif self.CurrentData == "format":

self.format = content

elif self.CurrentData == "year":

self.year = content

elif self.CurrentData == "rating":

self.rating = content

elif self.CurrentData == "stars":

self.stars = content

elif self.CurrentData == "description":

self.description = content

if ( __name__ == "__main__"):

# Tao mot XMLReader

# ghi de ContextHandler mac dinh

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

parser = xml.sax.make_parser() parser.setFeature(xml.sax.handler.feature_namespaces, 0) # Tat cac namepsace Handler = Phim BoHandler() parser.setContentHandler( Handler ) parser.parse("movies.xml")

3.8 Xử lý tập tin (file) 151

Phân tích cú pháp XML với DOM APIs: DOM thực sự hữu ích với các ứng dụng truy cập ngẫu nhiên. SAX chỉ cho phép chúng ta xem một bit của tài liệu tại một thời điểm và

Chương 3. Lập trình có cấu trúc với Python 152

không có quyền truy cập khác. Cách nhanh nhất để tải một XML document và tạo một đối tượng minidom sử dụng xml.dom module. Đối tượng minidom cung cấp một phương thức parser đơn giản mà tạo một DOM tree một cách nhanh chóng từ XML file. Hàm parse(file [,parser]) của đối tượng minidom để phân tích cú pháp XML file đã được chỉ rõ bởi file bên trong một đối tượng DOM tree.

from xml.dom.minidom import parse import xml.dom.minidom

# Mo mot tai lieu XML document boi su dung minidom parser DOMTree = xml.dom.minidom.parse("movies.xml") collection = DOMTree.documentElement if collection.hasAttribute("shelf"):

print "Root element : %s" % collection.getAttribute("shelf")

# Lay tat ca phim trong bo suu tap movies = collection.getElementsByTagName("movie")

# in chi tiet ve moi phim. for movie in movies:

print "*****Phim Bo*****" if movie.hasAttribute("title"):

print "Ten Phim: %s" % movie.getAttribute("title")

type = movie.getElementsByTagName(’type’)[0] print "The loai: %s" % type.childNodes[0].data format = movie.getElementsByTagName(’format’)[0] print "Dinh dang: %s" % format.childNodes[0].data rating = movie.getElementsByTagName(’rating’)[0] print "Rating: %s" % rating.childNodes[0].data description = movie.getElementsByTagName(’description’)[0] print "Gioi thieu: %s" % description.childNodes[0].data

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

3.8.3.3 Xử lý JSON file

Ví dụ 3.8.15. Phân tích cú pháp XML với DOM APIs.

1

import json

JSON là một kiểu định dạng dữ liệu trong đó sử dụng văn bản thuần tuý, định dạng JSON sử dụng các cặp key - value để dữ liệu sử dụng. JSON ban đầu được phát triển để dành phục vụ cho ứng dụng viết bằng JavaScript. Bản thân thuật ngữ JSON là viết tắt của cụm từ JavaScript Object Notation . Tuy nhiên vì JSON là một định dạng dữ liệu nên nó có thể được sử dụng bởi bất cứ ngôn ngữ nào àm không giới hạn với JavaScript. JSON là một trong những định dạng file trao đổi dữ liệu thông dụng nhất hiện nay. Với kiến trúc đơn giản và tương đồng với cấu trúc của Python nên việc thao tác JSON trên Python rất dễ hiểu. JSON trong Python: Python tích hợp sẵn một gọi có tên là json, có thể sử dụng để làm việc với dữ liệu JSON.

3.8 Xử lý tập tin (file) 153

Load file từ Internet: Thông thường dữ liệu JSON được lấy từ nguồn khác (như file, internet..) nên chúng ta sẽ bắt đầu bằng cách hướng dẫn download một file JSON từ Internet và sau đó mới parsing nội dung JSON download. Chúng ta sử dụng module urllib2 để download file và module json để encode/decode JSON data.

import urllib2 import json

response = urllib2.urlopen(’https://api.github.com/users/nhuongld/repos’) data = json.load(response) print data

1 2 3 4 5 6

Ví dụ 3.8.16. Download file JSON.

Ví dụ trên sẽ truy vấn đường dẫn https://api.github.com/users/nhuongld/repos để lấy danh sách Repository trên Github của mình dưới định dạng JSON. Parsing JSON Data: Nếu như chúng ta đã có JSON data dưới dạng chuỗi, muốn parsing chuỗi này thành data thì sử dụng như sau:

1 2 3 4

import json mystring = ’{"a":1,"b":2,"c":3,"d":4,"e":5}’ data = json.loads(mystring) print data

Ví dụ 3.8.17. Chuyển file JSON thành dữ liệu.

Kết quả hiển thị: {u’a’: 1,u’c’: 3,u’b’: 2,u’e’: 5,u’d’: 4}

Encoding JSON Data: Nếu như đã có một biến và muốn encode thành JSON string thì có thể dùng theo cách sau:

import json mydata = {

’name’: ’John’, ’age’: 10}

1 2 3 4 5 6

jsonstring = json.dumps(mydata) print jsonstring

Ví dụ 3.8.18. Mã hóa dữ liệu file JSON.

3.8.3.4 Xử lý CSV file

Kết quả hiển thị: {{"age": 10,"name": "John"}}

File CSV: Là viết tắt của (comma separated values) được định nghĩa là định dạng tệp đơn giản sử dụng cấu trúc cụ thể để sắp xếp dữ liệu dạng bảng. Nó lưu trữ dữ liệu dạng bảng như bảng tính hoặc cơ sở dữ liệu bằng văn bản thuần túy và có định dạng chung để trao đổi dữ liệu. Tệp csv được mở bằng excel và dữ liệu hàng và cột xác định định dạng chuẩn.

Chương 3. Lập trình có cấu trúc với Python 154

Các hàm của module CSV trong Python: Công việc môđun CSV được sử dụng để xử lý các tệp CSV để đọc ghi và nhận dữ liệu từ các cột được chỉ định. Có nhiều loại hàm CSV khác nhau, như sau: • csv.field_size_limit: Trả về kích thước max của trường hiện tại được cho phép bởi parser.

• csv.get_dialect : Trả về dialect liên kết đến tên. • csv.list_dialects: Trả về tên của tất cả các dialect đã đăng ký. • csv.reader: Đọc dữ liệu từ tệp csv. • csv.register_dialect: Nó liên kết dialect với một tên. Tên phải là một chuỗi hoặc một đối tượng Unicode.

• csv.writer: Ghi dữ liệu vào tệp csv. • csv.unregister_dialect: Nó xóa dialect được liên kết với tên từ sổ đăng ký dialect. Nếu tên không phải là tên dialect đã đăng ký, thì lỗi sẽ được đưa ra.

• csv.QUOTE_ALL: Hướng dẫn đối tượng writer trích dẫn tất cả các trường. • csv.QUOTE_MINIMAL: Nó hướng dẫn đối tượng writer chỉ trích dẫn những trường có chứa các ký tự đặc biệt như dấu ngoặc kép, dấu phân cách, v.v. • csv.QUOTE_NONNUMERIC: Hướng dẫn đối tượng writer trích dẫn tất cả các trường không phải là số.

• csv.QUOTE_NONE: Hướng dẫn đối tượng writer không bao giờ trích dẫn các trường. Đọc file CSV trong Python: Môđun csv.reader() được sử dụng để đọc tệp csv, quá trình đọc được tiến hành theo từng hàng của file và tạo ra một danh sách tất cả các cột.

1 2 3

name,department,birthday month Parker,Accounting,November Smith,IT,October

Ví dụ 3.8.19. Tạo một file csv có nội dung như sau.

import csv with open(’D:/test/csv_demo.csv’) as csv_file:

csv_reader = csv.reader(csv_file, delimiter=’,’) line_count = 0 for row in csv_reader: if line_count == 0:

print(f’Ten cac cot la: {", ".join(row)}’) line_count += 1

else:

print(f’\t{row[0]} lam viec trong {row[1]}, va duoc sinh ra thang {row[2]}.’) line_count += 1

1 2 3 4 5 6 7 8 9 10 11 12

print(f’Da doc {line_count} lines.’)

Chương trình sau sẽ thực hiện quá trình đọc file csv ở trong thư mục D:/test/csv_demo.csv:

1 2

Ten cac cot la: name, department, birthday month Parker lam viec trong Accounting, va duoc sinh ra thang November.

Kết quả:

3 4

Smith lam viec trong IT, va duoc sinh ra thang October. Da doc 3 lines.

3.8 Xử lý tập tin (file) 155

import csv with open(’D:/test/csv_demo.csv’) as csv_file:

csv_reader = csv.DictReader(csv_file, delimiter=’,’) line_count = 0 for row in csv_reader: if line_count == 0:

print(f’Ten cac cot la: {", ".join(row)}’) line_count += 1

print(f’\t{row["name"]} lam viec trong {row["department"]}, va duoc sinh ra thang {row["birthday month"]}.’)

line_count += 1

print(f’Da doc {line_count} lines.’)

1 2 3 4 5 6 7 8 9 10 11 12

Ví dụ 3.8.20. Đọc file CSV trong Python sử dụng Dictionary.

Ten cac cot la: name, department, birthday month Parker lam viec trong Accounting, va duoc sinh ra thang November. Smith lam viec trong IT, va duoc sinh ra thang October. Da doc 3 lines.

1 2 3 4

3.8.3.5 Xử lý Excel file

Kết quả:

Để xử lý file excel, Python sử dụng các thư viện được liệt kê trong Bảng 3.12:

Bảng 3.12: Các thư viện xử lý file excel với Python

Thư viện

Mô tả, linkdownload

openpyxl

xlsxwriter

xlrd

xlwt

xlutils

Pandas

Thư viện được đề xuất cho việc đọc ghi file Excel 2010 (xlsx). Download: http://pypi.python.org/pypi/openpyxl. Thư viện để ghi dữ liệu, format, tạo bảng biểu cho Excel 2010 (xlsx). Download: https://pypi.python.org/pypi/XlsxWriter. Thư viện đọc, ghi file excel với dịnh dạng cũ (xls). Download: http://pypi.python.org/pypi/xlrd. Thư viện đọc, ghi file excel với dịnh dạng cũ (xls). Download: http://pypi.python.org/pypi/xlwt. Thư viện tổng hợp cả xlrd, openpyxl và xlwt, để xử lý copy và chỉnh sửa các file excel. Download: http://pypi.python.org/pypi/xlutils. Thư viện hỗ trợ đọc các định dạng file: CSV, MS Excel, HTML, SQL,. . . Download: https://pandas.pydata.org/.

Đối với Excel, Pandas sử dụng tích hợp các thư viện xlrd, openpyxl, xlsxwriter và xlwt (mặc định là xlrd). Nếu người lập trình muốn sử dụng thư viện nào thì phải cài đặt thư viện đó thông qua công cụ quản lý pip3 của Python 3. Ví du, để cài đặt thư viện Pandas, ta sử dụng công cụ quản lý pip3 như sau:

1

pip3 install pandas

Chương 3. Lập trình có cấu trúc với Python 156

1

pip3 install xlrd

Mặc đinh Pandas sử dụng thư viện đọc Excel là xlrd nên chúng ta cần cài thêm xlrd:

1

pip3 install xlrd==1.2.0

Hiện tại thì phiên bản mới nhất của xlrd đã không còn hỗ trợ định dang file xlsx, nếu nếu muốn sử dụng thì chúng ta cài version thấp hơn là 1.2.0.

1

pip3 install openpyxl

Hoặc cài bản openpyxl

Để đọc file Excel với Pandas chúng ta thực hiện như sau:

Ví dụ 3.8.21. Sử dụng Pandas đọc file example.xls có format như sau:

1 2 3 4 5 6

#! /usr/bin/python3 import pandas as pd xl = pd.ExcelFile(’example.xls’) # get the first sheet as an object df = pd.read_excel(xl, 0, header=None) print(df.head())

Source Code:

Kết quả:

1

pd.read_excel(path, engine = ’openpyxl’)

Trường hợp là file xlsx chúng ta cần cài openpyxl và chuyển sang sử dụng khi đó:

3.8 Xử lý tập tin (file) 157

Một số hàm xử lý file Excel với Pandas:

Bảng 3.13: Một số hàm xử lý file Excel với Pandas trong Python

Hàm

Mô tả

Lấy giá trị của 1 cell cố định Lấy dữ liệu của 1 cột Lấy số số tổng số dòng dữ liệu của file Excel Kiểm tra dữ liệu kiểu nan

df.at[1, 1] df.iloc[:, 0] max_rows = len(df.iloc[:, 0]) pd.isnull(df.at[1, 1])

3.8.4 Thao tác trên thư mục trong Python

Thư mục là nơi chứa tất cả các file. Python cũng cung cấp rất nhiều phương thức để xử lý các hoạt động đa dạng liên quan tới thư mục. Module os có được xây dựng để cung cấp các phương thức giúp chúng ta tạo, xóa, và thay đổi các thư mục.

Hiển thị thư mục hiện tại: Phương thức getcwd() hiển thị thư mục đang làm việc hiện tại, trả về kết quả dưới dạng một chuỗi. Chúng ta cũng có thể sử dụng phương thức này để nhận về kết quả dưới dạng byte.

1 2 3

>>> import os >>> os.getcwd()’C:\\Program Files\\PyScripter’ >>> os.getcwdb()b’C:\\Program Files\\PyScripter’

Ví dụ 3.8.22. Hiển thị thư mục hiện tại với phương thức getcwd().

Thay đổi thư mục hiện tại: Thư mục làm việc hiện tại có thể được thay đổi bằng phương thức chdir(). Phương thức này nhận một tham số là tên thư mục chúng ta muốn tới từ thư mục hiện tại. Có thể sử dụng cả dấu gạch chéo (/) hoặc dấu gạch chéo ngược (\) để tách các phần tử trong đường dẫn, nhưng tốt nhất vẫn nên sử dụng dấu gạch ngược (\).

1 2 3

>>> os.chdir(’C:\\Python39’) >>> print(os.getcwd()) C:\Python39

Ví dụ 3.8.23. Thay đổi thư mục hiện tại với phương thức chdir().

Danh sách thư mục và file: Chúng ta có thể liệt kê tất cả các tệp và thư mục con bên trong một thư mục bằng cách sử dụng phương thức listdir(). Phương thức này nhận một đường dẫn và trả về danh sách thư mục con và các file trong đường dẫn đó. Nếu không có đường dẫn nào được chỉ định, kết quả trả về sẽ truy xuất từ thư mục làm việc hiện tại.

1 2 3

>>> print(os.getcwd()) C:\Python33 >>> os.listdir()[’DLLs’,’Doc’,’include’,’Lib’,’libs’,’LICENSE.txt’,’NEWS.txt’,

Ví dụ 3.8.24. Liệt kê tất cả các tệp và thư mục với phương thức listdir().

4 5 6

’python.exe’,’pythonw.exe’,’README.txt’,’Scripts’,’tcl’,’Tools’] >>> os.listdir(’G:\\’)[’\$RECYCLE.BIN’,’Movies’,’Music’,’Photos’,’Series’, ’System Volume Information’]

Chương 3. Lập trình có cấu trúc với Python 158

Tạo một thư mục mới: Để tạo các thư mục mới, chúng ta sử dụng phương thức mkdir() của module os. Chúng ta có thể chọn nơi chứa thư mục mới bằng cách ghi đầy đủ đường dẫn tới nơi muốn tạo. Nếu đường dẫn đầy đủ không được chỉ định, thư mục mới sẽ được tạo trong thư mục làm việc hiện tại.

1 2

>>> os.mkdir(’test’) >>> os.listdir()[’test’]

Ví dụ 3.8.25. Tạo một thư mục mới với phương thức mkdir().

Xóa bỏ thư mục: Để xóa toàn bộ thư mục, sử dụng phương thức rmdir()

>>> os.listdir()[’new_one’, ’old.txt’] >>> os.remove(’old.txt’) >>> os.listdir()[’new_one’] >>> os.rmdir(’new_one’) >>> os.listdir()[]

1 2 3 4 5

Ví dụ 3.8.26. Xóa bỏ thư mục với phương thức rmdir().

Lưu ý: Phương thức rmdir() chỉ có thể xóa các thư mục rỗng. Để loại bỏ một thư mục không rỗng, chúng ta có thể sử dụng phương thức rmtree() bên trong module shutil.

>>> os.listdir()[’test’] >>> os.rmdir(’test’) Traceback (most recent call last):... OSError: [WinError 145] The directory is not empty: ’test’ >>> import shutil >>> shutil.rmtree(’test’) >>> os.listdir()[]

1 2 3 4 5 6 7

Ví dụ 3.8.27. Xóa thư mục không rỗng với phương thức rmtree() .

3.9 Câu hỏi và bài tập

3.9.1 Câu hỏi

1. Lập trình cấu trúc là gì? Tại sao lập trình có cấu trúc lại quan trọng? 2. Hàm là gì? Tại sao nên sử dụng hàm? Trình bày cách định nghĩa một hàm trong Python? 3. Làm thế nào để gọi một hàm trong Python và truyền tham số cho hàm đó? 4. Trình bày cách tạo một danh sách (list) và thêm phần tử vào danh sách đó trong Python? 5. Cho ví dụ về cách hỗ trợ xử lý ngoại lệ (exception handling) trong Python? 6. Trong Python, làm thế nào để mở một tệp tin để đọc nội dung của nó?

3.9 Câu hỏi và bài tập 159

7. Làm thế nào để viết nội dung vào một tệp tin trong Python? 8. Python hỗ trợ xử lý tệp tin nhị phân (binary files) không? Nếu có, làm thế nào để mở một tệp tin nhị phân?

9. Làm thế nào để kiểm tra xem một tệp tin có tồn tại trong Python hay không? 10. Trình bày cách đọc tệp tin dòng một (line by line) trong Python? 11. Làm thế nào để khai báo một chuỗi (string) trong Python? 12. Python có hỗ trợ nối (concatenate) chuỗi không? Cho ví dụ để nối chuỗi? 13. Làm thế nào để cắt chuỗi (substring) trong Python? 14. Trình bày các định dạng chuỗi (string formatting) và cho ví dụ trong Python. 15. Làm thế nào để chuyển đổi một chuỗi thành chữ thường (lowercase) hoặc chữ hoa (uppercase) trong Python?

16. Hàm có thể trả về giá trị như thế nào trong Python? 17. Làm thế nào để tạo một hàm không trả về giá trị (void function) trong Python? 18. Đệ quy trong lập trình là gì? Khi nào nên sử dụng hàm đệ quy? Khi sử dụng đệ quy, tại sao cần có điều kiện dừng (base case hay neo)?

19. Python có hạn chế về độ sâu của đệ quy không? Làm thế nào để tối ưu hóa đệ quy? 20. Tuple là gì trong Python và khác biệt chính giữa tuple và list là gì? 21. Trình bày cách khai báo một tuple trong Python? Làm thế nào để truy cập các phần tử của một tuple trong Python?

22. Trình bày cách xác định chiều dài của một tuple trong Python? 23. Từ điển (dictionary) là gì? Trình bày cách khai báo và truy cập phần tử trong từ điển? 24. Trình bày cách thêm một phần tử vào từ điển và cập nhật giá trị của một phần tử có sẵn trong từ điển? 25. Làm thế nào để kiểm tra xem một key có tồn tại trong từ điển hay không? Trình bày cách thức duyệt qua các phần tử trong từ điển và lấy key và giá trị tương ứng?

26. Tập hợp (set) là gì và cách nào để khai báo một tập hợp trong Python? 27. Trình bày cách kiểm tra xem một phần tử có tồn tại trong tập hợp hay không? Các thức thêm một phần tử và xóa một phần tử khỏi tập hợp trong Python?

28. Trình bày cách lấy tập hợp giao (intersection) và tập hợp hợp (union) của hai tập hợp? 29. Trình bày cách tạo một tập hợp con (subset) từ một tập hợp lớn hơn trong Python? 30. Trình bày cách viết hàm trong Python có thể nhận một số lượng biến đối số không xác định (sử dụng *args) và một số lượng đối số khóa không xác định (sử dụng **kwargs)? 31. Giả sử chúng ta có một hàm lồng nhau (nested function) trong Python. Làm thế nào để chúng ta có thể truy cập biến cục bộ (local variables) của hàm bên ngoài từ bên trong hàm lồng nhau? 32. Làm thế nào để chúng ta tạo một hàm decorator trong Python để thay đổi hoặc mở rộng hành vi của một hàm khác mà không cần sửa đổi mã nguồn của hàm gốc? 33. Giải thích cách hoạt động của closures trong Python và cung cấp một ví dụ cụ thể về việc sử dụng chúng.

Chương 3. Lập trình có cấu trúc với Python 160

34. Làm thế nào để để tạo một hàm generator trong Python và điểm mạnh của việc sử dụng generator trong việc xử lý dữ liệu lớn? 35. Hãy mô tả cụ thể sự khác biệt giữa hàm global và biến global trong Python. Lấy ví dụ minh họa.

36. Làm thế nào để sao chép một danh sách (list) mà không thay đổi danh sách gốc? 37. Trình bày cách đảo ngược một danh sách trong Python? 38. Trình bày cách sắp xếp một danh sách theo thứ tự giảm dần (descending) trong Python? 39. Làm thế nào để loại bỏ các phần tử trùng lặp từ một danh sách trong Python? 40. Làm thế nào để tạo một danh sách mới bằng cách áp dụng một hàm cho từng phần tử của danh sách cũ trong Python? 41. Trình bày cách kiểm tra một khóa (key) có tồn tại trong từ điển không? Làm thế nào để

lấy giá trị mặc định cho một khóa nếu khóa đó không tồn tại trong từ điển? 42. Làm thế nào để thêm và xóa một cặp khóa-giá trị mới vào từ điển trong Python? 43. Làm thế nào để lặp qua từng cặp khóa-giá trị trong từ điển trong Python? 44. Trình bày cách tạo từ điển mới từ hai danh sách, một danh sách chứa khóa và một danh sách chứa giá trị, trong Python?

45. Làm thế nào để thay đổi giá trị của một phần tử cụ thể trong một tuple? 46. Trình bày cách nối (concatenate) hai hoặc nhiều tuple lại với nhau? 47. Làm thế nào để lặp qua từng phần tử của một tuple trong Python? 48. Làm thế nào để kiểm tra xem một tệp tin có tồn tại trong hệ thống không trong Python? 49. Trình bày cách đọc nội dung của một tệp tin dưới dạng danh sách các dòng trong Python? 50. Trình bày cách thay đổi tên hoặc di chuyển một tệp tin trong Python?

3.9.2 Câu hỏi trắc nghiệm

1. Trong Python, để định nghĩa một hàm, chúng ta sử dụng từ khóa nào? (a) func (c) def (d) function

(b) define 2. Hàm trong Python có thể trả về bao nhiêu giá trị cùng một lúc? (c) Nhiều giá trị. (b) 2 (a) 1 (d) Không giá trị. 3. Trong Python, biến nào được gọi trong một hàm và chỉ có phạm vi trong hàm đó?

(a) Biến toàn cục (b) Biến cục bộ (c) Biến cục bộ (d) Biến đối tượng

4. Để gọi một hàm trong Python, chúng ta sử dụng cú pháp nào? (c) function() (d) invoke_function{} (a) call_function() (b) function.call() 5. Hàm return có tác dụng gì?

(a) In ra kết quả (b) Dừng vòng lặp (c) Trả giá trị về cho lời gọi hàm (d) Khởi tạo biến toàn cục 6. Nếu một hàm không có câu lệnh return, giá trị trả về mặc định là gì?

3.9 Câu hỏi và bài tập 161

(a) 0 (b) "" (c) False (d) None 7. Câu lệnh nào gọi hàm hello() trong Python? (a) hello[] (b) hello() (c) call hello() (d) invoke hello 8. Tham số mặc định được định nghĩa khi nào?

(a) Trong câu lệnh return (b) Khi gọi hàm (c) Trong khai báo hàm (d) Trong thân hàm 9. Hàm nào sau đây không có tham số?

(a) def my_function(): (b) def my_function(param1,param2): (c) def my_function(param1="default"): (d) def my_function(*args): 10. Trong Python, để tạo một hàm có khả năng chấp nhận số lượng tham số biến đổi, chúng ta sử dụng cú pháp nào?

(a) def my_function(): (b) def my_function(param1,param2): (c) def my_function(param1="default"): (d) def my_function(*args): 11. Trong Python, để tạo một hàm có tham số mặc định, chúng ta sử dụng cú pháp nào?

(a) def my_function(param1,param2): (b) def my_function(param1="default"): (c) def my_function(): (d) def my_function(*args): 12. Hàm return trong Python được sử dụng để làm gì?

(a) Định nghĩa một hàm. (b) Gọi một hàm. (c) Trả về giá trị từ hàm. (d) Xóa một hàm. 13. Để gọi một hàm với các tham số bằng tên (keyword arguments) trong Python, chúng ta sử dụng cú pháp nào?

(c) function(arg1=1, arg2=2) (d) function(arg2=2, arg1=1) (a) function(arg1, arg2) (b) function(arg2, arg1) 14. Trong Python, hàm nào được sử dụng để chấm dứt việc thực thi của một hàm và trả về giá trị ngay lập tức? (a) exit() (b) break() (c) return() (d) continue() 15. Trong Python, để tạo một hàm có tài liệu mô tả về cách sử dụng hàm đó, chúng ta sử

(c) def my_function(): (d) def my_function(param1, param2): dụng cú pháp nào? (a) # Comment (b) """Docstring""" 16. Đệ quy là gì trong ngôn ngữ lập trình Python?

(a) Một loại lỗi trong code. (b) Một kỹ thuật lập trình trong đó một hàm gọi chính nó. (c) Một cấu trúc dữ liệu trong Python. (d) Một loại biến đặc biệt trong Python. 17. Trong đệ quy, điều quan trọng nhất là gì để tránh việc gọi vô hạn mà không kết thúc?

(a) Số lượng tham số của hàm. (b) Điều kiện dừng (base case). (c) Số lần gọi đệ quy. (d) Số lượng biến cục bộ. 18. Trong đệ quy, base case thường được sử dụng để làm gì?

Chương 3. Lập trình có cấu trúc với Python 162

(a) Gọi một hàm khác. (b) Trả về kết quả cuối cùng. (c) Gọi chính hàm đó. (d) In ra giá trị của biến. 19. Khi sử dụng đệ quy, trong trường hợp nào chúng ta cần phải cẩn thận để tránh gọi đệ quy quá nhiều lần?

(a) Khi dùng hàm trả về giá trị None. (b) Khi dùng hàm không có base case. (c) Khi dùng hàm với tham số mặc định. (d) Khi dùng hàm với tham số lớn. 20. Trong đệ quy, nếu không có hoặc không chỉ rõ base case, điều gì sẽ xảy ra?

(a) Lỗi cú pháp. (b) Stack overflow (tràn ngăn xếp). (c) Giá trị None sẽ được trả về. (d) Không có hiệu suất tốt.

21. Trong Python, để nối hai chuỗi lại với nhau, chúng ta sử dụng toán tử nào? (d) - (b) * (c) / (a) + 22. Để lấy chiều dài của một chuỗi trong Python, chúng ta sử dụng phương thức nào? (a) length() (b) size() (c) len() (d) count() 23. Phương thức nào trong Python được sử dụng để chuyển một chuỗi thành chữ thường? (a) to_lower() (b) lower_case() (c) lowercase() (d) lower() 24. Trong Python, để cắt (slice) một phần của chuỗi, chúng ta sử dụng cú pháp nào? (a) cut() (b) slice() (c) splice() (d) [start : end] 25. Phương thức nào trong Python được sử dụng để tìm vị trí đầu tiên của một chuỗi con trong chuỗi gốc? (a) find() (b) search() (c) locate() (d) index() 26. Để thay thế tất cả các xuất hiện của một chuỗi con trong chuỗi gốc bằng một chuỗi mới, chúng ta sử dụng phương thức nào? (a) replace() (b) substitute() (c) swap() (d) update() 27. Trong Python, để kiểm tra xem một chuỗi có phải là một số nguyên (integer) hợp lệ hay không, chúng ta sử dụng phương thức nào? (a) isint() (b) isinteger() (c) isnumeric() (d) isdigit() 28. Phương thức nào trong Python được sử dụng để xóa các khoảng trắng ở đầu và cuối của

một chuỗi? (a) trim() (b) strip() (c) clean() (d) clear() 29. Trong Python, để đảo ngược một chuỗi, chúng ta sử dụng cú pháp nào? (a) reverse() (b) invert() (c) flip() (d) [:: −1] 30. Để kiểm tra xem một chuỗi có bắt đầu bằng một chuỗi con cụ thể hay không, chúng ta sử dụng phương thức nào? (a) starts() (b) begins() (c) startswith() (d) initiate() 31. Trong Python, để chia một chuỗi thành một danh sách các từ (tách bằng khoảng trắng),

chúng ta sử dụng phương thức nào? (b) divide() (a) split() (c) break() (d) cut() 32. Trong Python, có thể trả về một hàm từ một hàm khác. Hàm được trả về được gọi là gì?

3.9 Câu hỏi và bài tập 163

(a) Nested function (b) Subroutine (c) Lambda function (d) Return function

33. Khi sử dụng lambda function trong Python, lambda được sử dụng để làm gì? (c) Định nghĩa một vòng lặp. (d) Định nghĩa một list. (a) Định nghĩa một hàm đặc biệt. (b) Định nghĩa một biến đặc biệt. 34. Trong Python, hàm nào dùng để lặp qua các phần tử của một chuỗi hoặc danh sách và áp dụng một hàm khác vào từng phần tử? (a) map() (b) apply() (c) for_each() (d) iterate() 35. Trong Python, hàm nào dùng để lặp qua các phần tử của một chuỗi hoặc danh sách và áp dụng một hàm khác vào từng phần tử? (a) map() (b) apply() (c) for_each() (d) iterate() 36. Hàm nào trong Python được sử dụng để tạo một danh sách (list) mới bằng cách chọn các phần tử từ danh sách cũ dựa trên một điều kiện? (a) filter() (b) select() (c) sort() (d) append() 37. Trong Python, hàm globals() được sử dụng để làm gì?

(a) Trả về danh sách các hàm toàn cục (global functions) (b) Trả về tất cả biến toàn cục (global variables) hiện có (c) Định nghĩa một biến toàn cục mới (d) Xóa tất cả biến toàn cục 38. Trong Python, mảng (list) là một cấu trúc dữ liệu gì?

(a) Tự động sắp xếp các phần tử. (b) Danh sách các số nguyên. (c) Dãy các phần tử có thứ tự. (d) Bảng dữ liệu hai chiều. 39. Để tạo một mảng rỗng trong Python, chúng ta sử dụng cú pháp nào?

(a) empty_array = [] (b) empty_array = {} (c) empty_array = list() (d) empty_array = None 40. Trong Python, làm thế nào để truy cập phần tử cuối cùng của một mảng (list)? (a) list[-1] (b) list[last()] (c) list.last() (d) list.end() 41. Hàm nào trong Python được sử dụng để thêm một phần tử vào cuối một mảng (list)? (a) add() (b) insert() (c) append() (d) push() 42. Để sao chép một mảng (list) trong Python mà không ảnh hưởng đến mảng gốc, chúng ta sử dụng cú pháp nào? (a) copy() (b) clone() (c) duplicate() (d) replicate() 43. Trong Python, để xóa một phần tử tại vị trí cụ thể trong một mảng, chúng ta sử dụng phương thức nào? (a) delete() (b) remove() (c) erase() (d) pop() 44. Trong Python, làm thế nào để kiểm tra xem một phần tử cụ thể có tồn tại trong mảng hay không?

Chương 3. Lập trình có cấu trúc với Python 164

(a) exists() (b) in_array() (c) contains() (d) in 45. Trong Python, để sắp xếp một mảng theo thứ tự giảm dần, chúng ta sử dụng hàm nào? (a) sort() (b) reverse() (c) descending() (d) sorted() 46. Trong Python, để tạo một mảng mới bằng cách kết hợp hai mảng khác, chúng ta sử dụng

phương thức nào? (a) combine() (b) concat() (c) merge() (d) extend() 47. Trong Python, hàm zip() được sử dụng để làm gì với các mảng (lists)?

(a) Ghép nối các mảng lại với nhau (b) Nén các mảng thành một mảng đơn (c) Sắp xếp các mảng (d) Lấy phần tử cuối cùng của mỗi mảng 48. Trong Python, tuple và list khác nhau như thế nào?

(a) Tuple là không thay đổi (immutable), list là thay đổi (mutable). (b) Tuple là thay đổi (mutable), list là không thay đổi (immutable). (c) Tuple chứa số nguyên, list chứa chuỗi ký tự. (d) Tuple chứa chuỗi ký tự, list chứa số nguyên. 49. Trong Python, làm thế nào để tạo một tuple rỗng?

(a) empty_tuple = () (b) empty_tuple = {} (c) empty_tuple = tuple() (d) empty_tuple = None 50. Trong Python, làm thế nào để truy cập phần tử cuối cùng của một tuple?

(a) tuple[-1] (b) tuple.last() (c) tuple.end() (d) tuple[-len(tuple)] 51. Hàm nào trong Python được sử dụng để tìm vị trí đầu tiên của một giá trị cụ thể trong

một tuple? (a) find() (b) search() (c) index() (d) locate() 52. Trong Python, làm thế nào để sao chép một tuple?

(a) tuple.copy() (b) tuple.clone() (c) tuple[:] (d) tuple.copy_tuple() 53. Trong Python, làm thế nào để thay đổi một phần tử trong một tuple đã tồn tại?

(c) Sử dụng phương thức replace() (d) Sử dụng phương thức update() (a) Sử dụng phương thức change() (b) Tuple là không thay đổi, không thể thay đổi phần tử 54. Trong Python, làm thế nào để nối (concatenate) hai tuple lại với nhau và tạo một tuple mới?

(a) Sử dụng toán tử + (b) Sử dụng phương thức concat() (c) Sử dụng phương thức join() (d) Tuple không thể nối lại với nhau 55. Hàm nào trong Python được sử dụng để tạo một tuple từ một danh sách (list)?

(a) tuple() (b) list() (c) create_tuple() (d) from_list() 56. Trong Python, hàm count() được sử dụng để làm gì đối với một tuple?

3.9 Câu hỏi và bài tập 165

trong tuple (d) Xóa tất cả các phần tử trong tuple (a) Đếm số lượng phần tử trong tuple (b) Tính tổng của các phần tử trong tuple (c) Đảo ngược thứ tự của các phần tử 57. Trong Python, làm thế nào để tạo một tuple mới từ một tuple đã có và thêm một phần tử vào cuối?

(a) Sử dụng phương thức append() (b) Sử dụng phương thức extend() (c) Sử dụng phương thức add() (d) Sử dụng phương thức insert() 58. Trong Python, từ điển (dictionary) là một cấu trúc dữ liệu gì?

(a) Dãy các phần tử có thứ tự (b) Danh sách các số nguyên (c) Dãy các phần tử không có thứ tự, mỗi phần tử có một khóa (key) riêng biệt (d) Bảng dữ liệu hai chiều 59. Trong Python, làm thế nào để tạo một từ điển rỗng?

(a) empty_dict = {} (b) empty_dict = dict() (c) empty_dict = () (d) empty_dict = None 60. Trong Python, làm thế nào để truy cập giá trị của một phần tử trong từ điển bằng khóa (key)?

(a) dictionary.get(key) (b) dictionary.access(key) (c) dictionary[key] (d) dictionary.value(key) 61. Trong Python, làm thế nào để kiểm tra xem một khóa (key) cụ thể có tồn tại trong từ

điển hay không? (a) key_exist() (b) in_dict() (c) contains_key() (d) key in dictionary 62. Trong Python, hàm keys() được sử dụng để làm gì đối với một từ điển?

(a) Trả về danh sách các khóa (keys) (b) Trả về danh sách các giá trị (values) (c) Xóa tất cả các khóa (d) Tạo một bản sao của từ điển

63. Trong Python, làm thế nào để loại bỏ một phần tử khỏi từ điển? (b) delete() (a) remove() (d) discard() (c) pop() 64. Trong Python, tập hợp (set) là một cấu trúc dữ liệu gì?

(a) Dãy các phần tử có thứ tự (b) Danh sách các số nguyên (c) Dãy các phần tử không có thứ tự, không chứa các phần tử trùng lặp (d) Bảng dữ liệu hai chiều 65. Trong Python, làm thế nào để tạo một tập hợp rỗng?

(a) empty_set = set() (b) empty_set = {} (c) empty_set = [] (d) empty_set = None 66. Trong Python, làm thế nào để thêm một phần tử vào một tập hợp?

Chương 3. Lập trình có cấu trúc với Python 166

(a) add() (b) insert() (c) append() (d) push() 67. Trong Python, làm thế nào để kiểm tra xem một phần tử cụ thể có tồn tại trong tập hợp

hay không? (a) exists() (c) contains() (d) in

(b) in_set() 68. Trong Python, làm thế nào để loại bỏ một phần tử khỏi tập hợp? (b) delete() (a) remove() (c) discard() (d) pop() 69. Trong Python, hàm union() được sử dụng để làm gì đối với hai tập hợp?

(c) Trả về tập hợp con của một tập hợp (d) Trả về hợp của hai tập hợp (a) Trả về giao của hai tập hợp (b) Trả về hiệu của hai tập hợp 70. Hàm len("Python") trả về kết quả gì? (a) 5 (c) 7 (d) Lỗi

(a) H (c) l (d) o (b) 6 71. "Hello"[1] trả về ký tự nào? (b) e 72. Phương thức nào dùng để chuyển chuỗi thành chữ hoa? (a) upper() (b) capitalize() (c) lower() (d) replace() 73. Phép toán "abc" + "123" trả về: (a) abc123 (c) Lỗi (d) [”abc”, ”123”] (b) abc 123 74. Chuỗi " hello ".strip() trả về: (a) "hello" (b) " hello" (c) "hello " (d) "hello\n" 75. Phép len([1, 2, 3]) trả về: (a) 2 (b) 3 (c) 4 (d) Lỗi

76. my_list = [1, 2, 3]; my_list.append(4) kết quả là: (c) [1, 2, 3] (d) Lỗi (a) [1, 2, 3, 4] (b) [4, 1, 2, 3] 77. Phương thức list.pop() dùng để:

(a) Thêm phần tử vào danh sách (b) Xoá phần tử đầu (c) Xoá phần tử cuối và trả về (d) Sắp xếp danh sách

78. my_list = [10, 20, 30]; print(my_list[1]) in ra: (b) 20 (a) 10 (c) 30 (d) 40 79. Cách nào đúng để duyệt qua từng phần tử của list?

(a) for i in range(list) (b) while list: (c) for item in list: (d) list.each() 80. Tuple khác list ở điểm nào?

(a) Không thể chứa số (b) Không thể thay đổi (c) Không thể duyệt (d) Không thể in ra 81. a = (1, 2, 3) kiểu dữ liệu của a là: (a) list (b) set (c) tuple (d) dict 82. Câu nào đúng khi tạo tuple 1 phần tử?

3.9 Câu hỏi và bài tập 167

(a) a = (1) (c) a = (1,) (d) a = 1,1 (b) a = [1,] 83. Từ điển là cấu trúc dữ liệu lưu trữ dưới dạng: (a) Danh sách số (b) Cặp key-value (c) Tuple (d) Hàm và biến 84. Tạo từ điển có khóa là “name” và giá trị là “Python”?

(a) d = [“name”: “Python”] (b) d = (“name”, “Python”) (c) d = {“name”: “Python”} (d) d = dict([“name”, “Python”]) 85. Trong Python, làm thế nào để mở một tệp tin để đọc nội dung của nó?

(a) open("file.txt", "r") (b) read("file.txt") (c) read_file("file.txt", "read") (d) load("file.txt") 86. Trong Python, làm thế nào để mở một tệp tin để ghi nội dung vào nó (nếu tệp không tồn tại, tạo mới)?

(a) open("file.txt", "w") (b) write("file.txt") (c) create("file.txt", "write") (d) edit("file.txt") 87. Trong Python, làm thế nào để đọc nhiều dòng từ một tệp tin vào một danh sách?

(a) read_lines() (b) load_lines() (c) file.readlines() (d) open("file.txt", "r").readlines() 88. Trong Python, làm thế nào để ghi nhiều dòng từ một danh sách vào một tệp tin?

(a) write_lines() (b) save_lines() (c) file.writelines() (d) open("file.txt", "w").writelines() 89. Trong Python, làm thế nào để kiểm tra xem một tệp tin đã tồn tại hay chưa?

(a) file_exists() (b) check_file() (c) os.exists("file.txt") (d) os.path.exists("file.txt")

90. Trong Python, làm thế nào để đọc nội dung của một tệp tin dưới dạng chuỗi? (c) open("file.txt", "r").read() (d) read_file("file.txt", "string") (a) read_as_string() (b) file.read_text() 91. Trong Python, làm thế nào để ghi nội dung vào tệp tin dưới dạng chuỗi?

(c) open("file.txt", "w").write() (d) write_file("file.txt", "string") (a) write_as_string() (b) file.write_text() 92. Làm sao để di chuyển hoặc đổi tên một tệp tin từ vị trí này sang vị trí khác trong Python?

(c) copy_file() (d) transfer_file() (a) move_file() (b) rename_file() 93. Trong Python, làm thế nào để mở một tệp tin và chỉ đọc nội dung của nó mà không thay đổi tệp gốc?

(c) open("file.txt", "r") (d) open("file.txt", "w") (a) open("file.txt", "r+") (b) open("file.txt", "a+") 94. Trong Python, làm thế nào để ghi nội dung vào một tệp tin mới và không ghi đè lên tệp gốc nếu nó đã tồn tại?

Chương 3. Lập trình có cấu trúc với Python 168

(a) open("file.txt", "a") (b) open("file.txt", "x") (c) open("file.txt", "w+") (d) open("file.txt", "wb") 95. Trong Python, làm thế nào để xác định kiểu tập tin (file type) của một tệp có phần mở rộng (extension)?

(a) file_type("file.txt") (b) extension("file.txt") (c) get_type("file.txt") (d) os.path.splitext("file.txt")[1] 96. Trong Python, để ghi nội dung vào tập tin dưới dạng nhị phân (binary) dùng lệnh nào?

(a) open("file.txt", "rb") (b) open("file.txt", "wb") (c) open("file.txt", "bb") (d) open("file.txt", "binary") 97. Trong Python, làm thế nào để xóa một tệp tin?

(a) delete_file("file.txt") (b) os.remove("file.txt") (c) erase("file.txt") (d) remove("file.txt") 98. Trong Python, làm thế nào để sao chép nội dung của một tệp tin vào một tệp tin khác?

(a) copy("source.txt", "destination.txt") (b) shutil.copy("source.txt", "destination.txt") (c) os.copy_file("source.txt", "destination.txt") (d) duplicate("source.txt", "destination.txt") 99. Trong Python, làm thế nào để đọc một tệp tin từ một URL (địa chỉ web)?

(a) read_url("http://example.com/file.txt") (b) urllib.urlopen("http://example.com/file.txt") (c) requests.get("http://example.com/file.txt") (d) download("http://example.com/file.txt") 100. Trong Python, làm thế nào để đọc nội dung của một tệp tin nằm trong một thư mục nén (compressed) như ZIP?

(a) open("archive.zip/file.txt", "r") (b) zipfile.open("archive.zip", "file.txt") (c) zipfile.ZipFile("archive.zip").read("file.txt") (d) extract("archive.zip", "file.txt")

3.9.3 Bài tập thực hành

1. Viết hàm tính tổng hai số nguyên a, b. Kết quả trả về là tổng hai số nguyên a và b. 2. Định nghĩa hàm chuyển số nguyên thành chuỗi và in nó ra giao diện điều khiển. 3. Định nghĩa hàm nhận hai số nguyên trong dạng chuỗi và tính tổng của chúng, sau đó in tổng ra giao diện điều khiển.

4. Định nghĩa hàm nhận 2 chuỗi từ input và nối chúng sau đó in ra giao diện điều khiển. 5. Định nghĩa một hàm có input là 2 chuỗi và in chuỗi có độ dài lớn hơn trong giao diện điều khiển. Nếu 2 chuỗi có chiều dài như nhau thì in tất cả các chuỗi theo dòng. 6. Định nghĩa hàm chấp nhận input là số nguyên và in "Đây là một số chẵn" nếu nó chẵn và in "Đây là một số lẻ" nếu là số lẻ.

3.9 Câu hỏi và bài tập 169

7. Định nghĩa một hàm có thể in dictionary chứa key là các số từ 1 đến 3 (bao gồm cả hai số) và các giá trị bình phương của chúng 8. Định nghĩa một hàm có thể tạo và in list chứa các giá trị bình phương của các số từ 1 đến 20 (tính cả 1 và 20) 9. Định nghĩa một hàm có thể tạo ra list chứa các giá trị bình phương của các số từ 1 đến 20 (bao gồm cả 1 và 20), rồi in 5 mục cuối cùng trong list. 10. Định nghĩa 1 hàm có thể tạo và in một tuple chứa các giá trị bình phương của các số từ 1 đến 20 (tính cả 1 và 20). 11. Viết hàm nhập vào 3 cạnh của tam giác, kiểm tra tính hợp lệ của tam giác. Nếu là tam giác thì tính diện tích theo công thức Herong. 12. Viết hàm để chơi Game đoán số trong phạm vi từ a đến b nhập từ bàn phím với số lượng câu hỏi ít nhất.

13. Viết hàm đệ quy Python tính tổng S = 1 + 2 + 3 + 4 + 5... + n. 14. Viết hàm tính giá trị BMI = Cân nặng/(chiều cao*chiều cao). 15. Viết hàm tính giá trị ROI = (Lợi nhuận – chi phí) / Chi phí. 16. Viết hàm đệ qui tính số Fibonacci thứ n với nhập từ bàn phím 17. Viết hàm tìm kiếm nhị phân để tìm các item trong một list đã được sắp xếp. Hàm sẽ trả

lại chỉ số của phần tử được tìm thấy trong list. 18. Viết hàm tính giai thừa của một số cho trước. 19. Viết hàm kiểm tra số hoàn thiện, số thịnh vượng. 20. Viết hàm vẽ hình dùng hàm sleep. 21. Viết hàm tính căn bậc 2 lồng nhau của số x ((cid:112)((cid:112)(x)). 22. Viết hàm tính logax với a và x nhập từ bàn phím. 23. Viết hàm in chuỗi Unicode "Hello world" và đọc chuỗi ASCII và chuyển đổi nó sang một chuỗi Unicode được mã hóa bằng UTF-8.

24. Viết hàm chấp nhận chuỗi từ do người dùng nhập vào, phân tách nhau bởi dấu phẩy và in những từ đó thành chuỗi theo thứ tự bảng chữ cái, phân tách nhau bằng dấu phẩy 25. Viết hàm nhận chuỗi là các dòng được nhập vào, chuyển và in các dòng này thành chữ in hoa.

26. Viết hàm kiểm tra chuỗi đối xứng với đầu vào và đầu ra là một chuỗi. 27. Viết hàm chấp nhận đầu vào là một chuỗi các từ tách biệt bởi khoảng trắng, loại bỏ các từ trùng lặp, sắp xếp theo thứ tự bảng chữ cái, rồi in chúng.

28. Viết hàm nhận đầu vào là chuỗi các số nhị phân 4 chữ số, phân tách bởi dấu phẩy, kiểm tra xem chúng có chia hết cho 5 không. Sau đó in các số chia hết cho 5 thành dãy phân tách bởi dấu phẩy. 29. Viết hàm tối ưu chuỗi bằng cách xóa hết các khoảng trắng dư thừa với đầu vào là một chuỗi bất kỳ.

30. Viết hàm chấp nhận đầu vào là một câu, đếm số chữ cái và chữ số trong câu đó 31. Viết hàm tìm tất cả các số trong đoạn 1000 và 3000 (tính cả 2 số này) sao cho tất cả các

Chương 3. Lập trình có cấu trúc với Python 170

chữ số trong số đó là số chẵn. In các số tìm được thành chuỗi cách nhau bởi dấu phẩy, trên một dòng.

32. Viết hàm xử lý tách chuỗi ban đầu truyền vào thành các chuỗi khác nhau theo vị trí. 33. Viết một chương trình yêu cầu người dùng nhập tên và tuổi của họ. Gửi lại họ một tin nhắn cho biết năm họ sẽ tròn 100 tuổi.

34. Viết hàm có đầu vào là một câu, đếm số lượng chữ hoa, đếm số lượng chữ thường. 35. Viết hàm tách lấy tên bài hát từ tên file đầu vào. 36. Viết hàm đảo ngược một xâu ký tự bất kỳ. Ví dụ: ‘I am a student’ ⇒ ‘tneduts a ma I’. 37. Viết chương trình sắp xếp tuple (name, age, score) theo thứ tự tăng dần, name là string, age và height là number. Tuple được nhập vào bởi người dùng. Tiêu chí sắp xếp là: theo name sau đó sắp xếp theo age, sau đó sắp xếp theo score. Ưu tiên là tên > tuổi > điểm.

38. Viết hàm tạo và in list chứa bình phương của các số từ 1 đến 20 (tính cả 1 và 20). 39. Viết hàm tạo tuple mới chứa các số chẵn trong tuple (1,2,3,4,5,6,7,8,9,10) cho trước. 40. Viết hàm tìm kiếm nhị phân để tìm các item trong một list đã được sắp xếp. Hàm sẽ trả lại chỉ số của phần tử được tìm thấy trong list.

41. Viết các hàm nhập vào họ và tên của một người (có thể nhập dữ liệu bất kỳ gồm chữ hoa, chữ thường lẫn lộn, dấu cách nhiều). Hãy chuẩn hoá xâu họ tên vừa nhập theo đúng qui cách sau: chữ cái đầu của họ, đệm, tên phải là chữ hoa; các chữ cái còn lại phải là chữ thường. Giữa họ - đệm, đệm- đệm, đệm – tên chỉ tồn tại một dấu cách.

42. Viết chương trình theo cấu trúc thành các hàm nhập vào một xâu ký tự. Đếm số từ trong xâu vừa nhập (Từ được phân cách bằng các dấu cách) và hiển thị thông báo ra màn hình. 43. Nhập vào một xâu ký tự. Kiểm tra xem xâu ký tự đó có là xâu đối xứng hay không? Ví dụ: ‘ABBCBBA’ ⇒ Đối xứng; ‘AABCBBA’ ⇒ Không đối xứng. 44. Viết hàm kiểm tra chuỗi nhập vào có chứa ít nhất một chữ số, một chữ cái viết hoa, và một ký tự đặc biệt.

45. Viết hàm nhận vào chuỗi và ký tự c, trả về số lần xuất hiện của c trong chuỗi. 46. Viết hàm tính tổng các số nguyên tố nhỏ hơn n. 47. Viết hàm sử dụng danh sách để lọc các số lẻ từ danh sách được người dùng nhập vào. 48. Viết hàm nhập vào chuỗi mô tả địa chỉ email, kiểm tra xem chuỗi đó có hợp lệ không (phải chứa và . sau ). 49. Viết hàm nhập vào một chuỗi và tách toàn bộ các số nguyên có trong chuỗi, lưu vào danh sách. 50. Viết chương trình mã hóa chuỗi bằng Caesar Cipher (dịch các ký tự theo số bước nhất định trong bảng chữ cái).

51. Viết hàm để tạo tuple khác, chứa các giá trị là số chẵn trong tuple cho trước. 52. Viết hàm để tạo ra và in tuple chứa các số chẵn được lấy từ tuple (1,2,3,4,5,6,7,8,9,10). 53. Viết hàm lọc các số chẵn trong danh sách sử dụng hàm filter. Danh sách là [1,2,3,4,5,6,7,8,9,10] 54. Viết hàm dùng map() để tạo list chứa các giá trị bình phương của các số trong [1,2,3,4,5,6,7,8,9,10].

3.9 Câu hỏi và bài tập 171

55. Viết hàm dùng map() và filter() để tạo list chứa giá trị bình phương của các số chẵn trong [1,2,3,4,5,6,7,8,9,10] 56. Viết chương trình để tạo tất cả các câu có chủ ngữ nằm trong ["Anh","Em"], động từ nằm trong ["Chơi","Yêu"] và tân ngữ là ["Bóng đá","Xếp hình"]. 57. Viết chương trình nhập danh sách điểm sinh viên, tính điểm trung bình và xếp loại theo các mức: Giỏi, Khá, Trung bình, Yếu.

58. Viết hàm in list sau khi xóa các số chẵn trong [5,6,77,45,22,12,24]. 59. Viết hàm sử dụng list comprehension in list sau khi đã loại bỏ các số chia hết cho 5 và 7 trong list [12,24,35,70,88,120,155].

60. Viết hàm trộn ngẫu nhiên thứ tự các phần tử trong một list. 61. Viết hàm loại bỏ các phần tử trùng nhau trong list nhưng giữ nguyên thứ tự ban đầu. 62. Viết chương trình tính tổng các phần tử có vị trí là số nguyên tố trong list. 63. Viết hàm tạo mảng 3D 3*5*8 có mỗi phần tử là 0. 64. Viết chương trình in list từ list [12,24,35,24,88,120,155,88,120,155], sau khi đã xóa hết các giá trị trùng nhau.

65. Viết hàm xử lý List nhập ngẫu nhiên và List đa chiều. 66. Viết hàm nhập vào 1 list có N số ngẫu nhiên KHÔNG TRÙNG NHAU 67. Viết hàm nhập vào một dãy các số theo thứ tự tăng, nếu nhập sai quy cách thì yêu cầu nhập lại. In dãy số sau khi đã nhập xong 68. Viết các hàm có chức năng nhập vào một dãy n số thực M[0], M[1], ..., M[n − 1], sắp xếp dãy số theo thứ tự giảm dần. Xuất ra dãy số sau khi sắp xếp.

69. Viết hàm sắp xếp mảng dùng thuật toán Bubble Sort. 70. Viết hàm lấy một list các con số (Ví dụ: a = [2, 4, 6, 8, 10]) và tạo một list mới chỉ gồm các phần tử đầu tiên và cuối cùng của list đã cho.

71. Viết một hàm nhận một list các số có sắp xếp thứ tự từ nhỏ đến lớn và một số khác. Hàm đó sẽ xác định xem số đã cho có nằm trong list hay không và trả về, in ra một Boolean thích hợp. Yêu cầu sử dụng Binary Search (tìm kiếm nhị phân).

72. Hãy tạo một Dictionary (Bộ từ điển) gồm tên và ngày sinh trong file của bạn. Viết chương trình yêu cầu người dùng nhập tên và trả lại đúng ngày sinh của người đó.

73. Viết hàm nhập hỏi người dùng một số và in ra tất cả ước số của số đó. 74. Yêu cầu người dùng cung cấp một chuỗi và cho biết đó có phải một palindrome không (palindrome là một chuỗi có thể được viết xuôi hay viết ngược vẫn chỉ cho ra chính nó). 75. Viết chương trình cho ra một list chỉ chứa những phần tử chung giữa các list đã cho (không được trùng nhau). Đảm bảo rằng chương trình có thể hoạt động trên hai lists có kích thước khác nhau. Chúng ta cần sử dụng ít nhất một List Comprehension (List Comprehension là cách viết code ngắn gọn để tạo một danh sách phức tạp).

76. Viết một hàm để nhận một list và trả lại một list mới loại bỏ mọi phần tử bị trùng nhau trong list ban đầu. Trong đó, viết hai loại hàm: Một sử dụng vòng lặp (Loop), một sử dụng Set trong Python

Chương 3. Lập trình có cấu trúc với Python 172

77. Viết hàm tính giá trị của đa thức P (x) = anxn + an−1xn−1 + · · · + a1x + a0 theo công thức Horner với các hệ số được lưu trong mảng bằng cách nhân lần lượt từng hệ số. 78. Viết chức chương trình theo dạng các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, đếm số lượng phần tử âm trong mảng và hiển thị kết quả

79. Viết chức chương trình theo dạng các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, kiểm tra xem mảng A có phải là mảng số nguyên tố hay không? (Mảng số nguyên tố khi tất cả các phần tử là số nguyên tố).

80. Viết chức chương trình theo dạng các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số thực. Sắp xếp dãy số theo chiều giảm dần.

81. Viết chức chương trình theo dạng các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, đếm số phần tử lớn hơn 0 và tính tổng của chúng dùng mảng. Hiển thị kết quả ra màn hình.

82. Viết chức chương trình theo dạng các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tìm vị trí xuất hiện số nguyên tố đầu tiên trong mảng. Cho biết vị trí xuất hiện tương ứng (nếu có).

83. Viết hàm tính tổng các phần tử trong mảng một chiều gồm n phần tử số thực. 84. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tìm tính tổng các phần tử có vị trí chẵn ở trong mảng. Hiển thị kết quả ra màn hình.

85. Viết chức chương trình theo dạng các hàm để nhập vào 2 mảng số nguyên A có m phần tử và mảng B có n phần tử từ bàn phím. Hãy cộng hai mảng A và B lưu lại thành mảng C với số phần tử k = m + n.

86. Viết chương trình nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, đếm số lượng phần tử dương trong mảng và hiển thị kết quả ra màn hình.

87. Viết chương trình nhập vào 2 mảng 1 chiều: mảng A gồm n phần tử, mảng B gồm m phần tử cùng kiểu nguyên. Hãy nối hai mảng A, B lại và lưu lại trong mảng C. Hiển thị kết quả của mảng C ra màn hình

88. Viết chương trình nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tìm và hiển thị phần tử có giá trị bằng trung bình cộng của n-1 phần tử còn lại.

89. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tìm số nguyên dương nhỏ nhất ở trong mảng và hiển thị kết quả ra màn hình.

90. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tìm số âm lớn nhất trong mảng A.

91. Viết các hàm nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, kiểm tra số B có xuất hiện trong dãy số đó hay không? Nếu xuất hiện thì xuất hiện bao nhiêu lần? 92. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên kiểm tra xem mảng A có phải là mảng tăng dần hay không? Hiển thị kết quả ra màn hình. 93. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên hãy cập nhật lại các số nguyên tố trong mảng A thành các số 0.

94. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên và 2 số

3.9 Câu hỏi và bài tập 173

a, b. Hãy tính tổng các phần tử trong mảng A nằm trong đoạn [a, b].

95. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên và một số nguyên x. Tìm vị trí cuối cùng của phần tử x xuất hiện trong mảng A.

96. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tách các số nguyên tố trong mảng A đưa vào mảng B. Hiển thị kết quả mảng B ra màn hình. 97. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tách các số nguyên tố đưa vào mảng B, các số còn lại cho vào mảng C.

98. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tách mảng A thành 2 mảng B chứa các số nguyên dương, mảng C chứa các số nguyên âm. 99. Viết chương trình theo dạng các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tách mảng A thành 2 mảng B chứa các số nguyên lẻ, mảng C chứa các số nguyên chẵn.

100. Viết chương trình theo dạng các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, cập nhật tất cả các số nguyên tố có trong mảng A thành số 0. 101. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, chèn thêm số 0 đằng sau các số nguyên tố trong mảng A, hiển thị kết quả ra màn hình. 102. Viết các hàm để nhập vào mảng một chiều A = {a1, a2, ..., an} gồm n số nguyên, tính tổng tất cả các số không phải là số nguyên tố trong mảng A.

103. Viết chương trình nhập vào 2 ma trận A = {ai j}M×N và ma trận B = {bi j}M×N. Tính tổng hai ma trận lưu lại trong ma trận C(M × N) = A(M × N) + B(M × N).

104. Viết các hàm để nhập vào ma trận vuông A = {ai j}N×N. Hãy tính tổng các phần tử nằm trên đường chéo chính của ma trận.

105. Viết chương trình nhập vào một ma trận A = {ai j}M×N có M × N phần tử nguyên. Đếm số lượng phần tử âm trong ma trận. Hiển thị kết quả ra màn hình. 106. Viết hàm nhận giá trị từ đầu vào và tạo ra một mảng 2 chiều. Giá trị phần tử trong hàng thứ i và cột thứ j của mảng phải là i × j. Lưu ý: i = 0, 1, ..., X − 1; j = 0, 1, ...,Y − 1. 107. Viết các hàm để nhập vào mảng 1 chiều A gồm n số nguyên. Hãy xóa tất cả các số nguyên tố trong mảng A. Hiển thị kết quả ra màn hình

108. Viết các hàm để nhập vào một ma trận có A = {ai j}M×N có M × N phần tử. Hãy tìm cột có tổng các phần tử là lớn nhất và cho biết đó là cột nào?

109. Viết chương trình tách từng từ trong chuỗi thành danh sách. 110. Nhập họ tên, in ra tên viết tắt (VD: “Nguyễn Văn Anh” (cid:25) “N.V.A”). 111. Nhập chuỗi, đếm số từ, số chữ số, số ký tự đặc biệt. 112. Viết chương trình nhập danh sách gồm n số nguyên, in ra danh sách sắp xếp tăng dần. 113. Viết hàm tìm phần tử xuất hiện nhiều nhất trong danh sách. 114. Viết hàm xóa tất cả các phần tử trùng nhau trong danh sách. 115. Viết hàm tính tổng các phần tử lẻ trong danh sách. 116. Viết chương trình nhập vào một danh sách, chèn phần tử mới vào đúng vị trí giữ nguyên thứ tự tăng.

Chương 3. Lập trình có cấu trúc với Python 174

117. Viết chương trình nhập danh sách học sinh và điểm, tìm sinh viên có điểm cao nhất. 118. Viết chương trình nhập chuỗi số, chuyển thành tuple và in ra phần tử lớn nhất. 119. Viết chương trình đếm số lần xuất hiện của mỗi phần tử trong tuple. 120. Viết hàm chuyển đổi list thành tuple và ngược lại. 121. Viết hàm ghép hai tuple thành một tuple duy nhất. 122. Viết chương trình chuyển đổi danh sách các tuple (gồm tên và điểm) thành dictionary. 123. Viết chương trình hoán đổi hai tuple (cùng độ dài) phần tử với nhau theo từng vị trí. 124. Viết chương trình theo dạng các hàm để tính số tiền thực của một tài khoản ngân hàng dựa trên nhật ký giao dịch được nhập vào từ giao diện điều khiển.

125. Viết chương trình thống kê tần số xuất hiện của các từ trong một văn bản dùng dictionary. 126. Viết chương trình tạo từ điển lưu trữ thông tin sinh viên (MSSV, họ tên, điểm) và cho phép tìm kiếm theo MSSV. 127. Viết chương trình nhập từ điển sản phẩm: tên (cid:25) giá, tìm sản phẩm có giá cao nhất và in thông tin.

128. Viết chương trình ghi danh sách tên học sinh vào file văn bản. 129. Viết chương trình đọc nội dung từ file data.txt và in ra màn hình. 130. Viết chương trình đếm số dòng, số từ trong file văn bản. 131. Viết chương trình ghi kết quả tính toán vào file và đọc lại. 132. Viết chương trình đọc danh sách tên từ file, sắp xếp tên theo bảng chữ cái rồi ghi lại vào file mới.

133. Viết chương trình đọc nội dung file input.txt, đếm số dòng, số từ và lưu vào file report.txt. 134. Viết chương trình ghi kết quả xử lý một danh sách số (tổng, trung bình, lớn nhất, nhỏ nhất) vào file summary.txt.

135. Viết chương trình đọc danh sách điểm từ file, tính điểm trung bình của lớp. 136. Viết chương trình tìm dòng chứa từ khóa “Python” trong file. 137. Viết chương trình nhập dữ liệu từ người dùng và lưu vào file theo định dạng CSV. 138. Viết chương trình ghép nội dung từ 2 file văn bản thành một file mới. 139. Viết chương trình quản lý sản phẩm với dữ liệu từ file text cho trước. 140. Viết chương trình xử lý các số nhập từ Text File cho trước. 141. Viết chương trình xử lý XML File cho trước. 142. Viết chương trình xử lý file JSON, chuyển đổi string Json qua Python Object. 143. Viết chương trình xử lý file JSON, chuyển đổi Python object qua string JSON. 144. Viết chương trình xử lý file CSV cho trước. 145. Viết chương trình xử lý file Excel cho trước. 146. Viết chương trình xử lý file JSON quản lý sinh viên. 147. Viết chương trình xử lý file Excel File quản lý tiền lương. 148. Viết chương trình xử lý file Excel File quản lý thu nhập cá nhân. 149. Viết chương trình xử lý file CSV quản lý danh bạ điện thoại. 150. Viết chương trình xử lý file XML quản lý thiết bị.

4. Lập trình hướng đối tượng với Python

Mục tiêu: Kết thúc chương này, sinh viên có thể:

• Phân biệt sự khác nhau giữa lớp và đối tượng. • Nắm vững và sử dụng thành thạo các cách định nghĩa lớp trong Python. • Hiểu được cách khai báo và sử dụng biến đối tượng trong Python. • Biết cách sử dụng lập trình hướng đối tượng giải quyết một số bài toán. • Biết cách sử dụng và thao tác trên các module thông dụng để giải quyết một số bài toán. • Biết cách sử dụng và thao tác trên package để giải quyết một số bài toán.

4.1 Lập trình hướng đối tượng

Python là một ngôn ngữ lập trình hướng đối tượng mạnh nên việc tạo ra và sử dụng các đối tượng là hết sức dễ dàng. Trong phần này, cuốn sách sẽ giới thiệu qua một số khái niệm cơ bản trong lập trình hướng đối tượng cũng như cách khởi tạo và sử dụng chúng với Python.

4.1.1 Các khái niệm lập trình hướng đối tượng trong Python

Lớp (Class) và đối tượng (Object) là hai khái niệm cơ bản trong lập trình hướng đối tượng bên cạnh thuộc tính và phương thức của đối tượng. • Đối tượng (Object): Là những thực thể tồn tại có hành vi. Ví dụ, đối tượng là một xe ô

Chương 4. Lập trình hướng đối tượng với Python 176

tô có tên hãng, màu sắc, loại nguyên liệu, hành vi đi, dừng, đỗ, nổ máy... Hầu hết mọi thứ trong Python là một đối tượng nên đều có thuộc tính và phương thức. Tất cả các hàm đều có thuộc tính __doc__ tích hợp có chức năng trả về chuỗi doc được xác định trong mã nguồn của hàm.

• Lớp (Class): Là một kiểu dữ liệu đặc biệt do người dùng định nghĩa, tập hợp nhiều thuộc tính đặc trưng cho mọi đối tượng được tạo ra từ lớp đó. Lớp là một thực thể logic có một số thuộc tính và phương thức cụ thể. Ví dụ: nếu chúng ta có một lớp nhân viên thì nó phải chứa một thuộc tính và phương thức, tức là một địa chỉ, tên, tuổi, lương,... • Thuộc tính (Attribute): Là các giá trị của lớp. Sau này khi các đối tượng được tạo ra từ lớp, thì thuộc tính của lớp lúc này sẽ trở thành các đặc điểm của đối tượng đó.

• Phương thức (Method): Là hàm được liên kết với một đối tượng. Trong Python, một phương thức không phải là duy nhất cho các thể hiện của lớp. Bất kỳ kiểu đối tượng nào cũng có thể có phương thức. Lập trình hướng đối tượng có 4 tính chất quan trọng sau:

Hình 4.1: Các tính chất của lập trình hướng đối tượng

• Kế thừa (Inheritance): Kế thừa là khía cạnh quan trọng nhất của lập trình hướng đối tượng, mô phỏng khái niệm thừa kế trong thế giới thực. Nó xác định rằng đối tượng con có được tất cả các thuộc tính và hành vi của đối tượng cha. Bằng cách sử dụng tính kế thừa, chúng ta có thể tạo một lớp sử dụng tất cả các thuộc tính và hành vi của lớp khác. Lớp mới được biết đến như là một lớp dẫn xuất hoặc lớp con và lớp còn lại gọi là lớp cơ sở hoặc lớp cha. Kế thừa giúp tái sử dụng lại mã nguồn.

• Đa hình (Polymorphism): Đa hình chứa hai từ "poly" và "morphs". Poly có nghĩa là nhiều và Morphs có nghĩa là hình thức, hình dạng. Chúng ta hiểu rằng đa hình là cách một nhiệm vụ có thể được thực hiện theo những cách khác nhau. Ví dụ, chúng ta có một lớp động vât và tất cả các con vật đều biết kêu. Nhưng chúng kêu khác nhau. Ở đây, hành vi "kêu" là đa hình theo nghĩa và phụ thuộc vào động vật. Vì vậy, khái niệm "động vật" trừu tượng không thực sự "nói", nhưng các động vật cụ thể (như chó và mèo) có một triển khai cụ thể của hành động "kêu".

• Đóng gói (Encapsulation): Đóng gói cũng là một khía cạnh quan trọng của lập trình hướng đối tượng. Nó được sử dụng để hạn chế quyền truy cập vào các phương thức và biến. Trong đóng gói, mã và dữ liệu được gói cùng nhau trong một đơn vị.

4.1 Lập trình hướng đối tượng 177

• Trừu tượng (Abstraction): Trừu tượng hóa dữ liệu và đóng gói cả hai thường được sử dụng như từ đồng nghĩa. Cả hai đều gần như đồng nghĩa vì sự trừu tượng hóa dữ liệu đạt được thông qua việc đóng gói. Trừu tượng được sử dụng để ẩn chi tiết nội bộ và chỉ hiển thị các chức năng. Trừu tượng hóa một cái gì đó có nghĩa là đặt tên cho những thứ để cái tên nắm bắt cốt lõi của những gì một chức năng hoặc toàn bộ chương trình làm.

4.1.2 Lớp và đối tượng trong Python

Lớp (Class) là một thực thể ảo và có thể được xem như một bản thiết kế của một đối tượng. Giả sử một lớp là một nguyên mẫu của một tòa nhà. Một tòa nhà chứa tất cả các chi tiết về sàn nhà, cửa ra vào, cửa sổ,... Chúng ta có thể tạo ra nhiều tòa nhà như mong muốn dựa trên những chi tiết này. Do đó, tòa nhà có thể được xem như là một lớp và chúng ta có thể tạo ra nhiều đối tượng của lớp này. Lớp có thể được định nghĩa như là một template mô tả trạng thái và hành vi mà loại đối tượng của lớp hỗ trợ.

Đối tượng (Object) là một thể hiện (Instance) của một lớp có trạng thái và hành vi. Khi lớp được định nghĩa, chỉ có mô tả cho đối tượng được định nghĩa. Do đó, không có bộ nhớ nào được cấp phát. Khi đó, nếu chúng ta muốn sử dụng lớp đó, chúng ta cần cấp phát bộ nhớ nhằm sử dụng nó. Quá trình tạo một đối tượng được gọi là khởi tạo. Về cơ bản, các đối tượng có các tính chất sau đây:

• Trạng thái hay thuộc tính: Một đối tượng có các thuộc tính đại diện cho các trạng thái của nó, và nó phản ánh các đặc tính của đối tượng. Ví dụ: màu xanh, màu đỏ, cân nặng,... • Hành vi hay phương thức: Một đối tượng sẽ có các phương thức để thể hiện các hành vi hoặc hành động nào đó trong chương trình. Ví dụ: đọc, ghi, nói,....

Ví dụ 4.1.1. Nếu chúng ta thiết kế một lớp trên các trạng thái và hành vi của một Người, thì các trạng thái có thể được biểu diễn dưới dạng các biến thể hiện đặc điểm của người đó và các hành vi dưới dạng các phương thức của lớp.

Hình 4.2: Ví dụ về lớp và đối tượng

Ở đây chúng ta có 1 lớp Người, trong đó:

Chương 4. Lập trình hướng đối tượng với Python 178

• Các thuộc tính: Tên, Giới tính, Nghề nghiệp. • Các hành vi: Làm việc(), Học().

Sử dụng các thuộc tính và hành vi này, chúng ta có thể tạo thành rất nhiều các đối tượng khác nhau:

• Đối tượng p1 có các thuộc tính: Tên là Jessa, Giới tính: Nữ, Nghề nghiệp: Kỹ sư; và có hành vi là: Làm việc(): Cô ấy là kỹ sư tại công ty ABC và hành vi Học(): Cô ấy học 10 tiếng mỗi ngay

• Đối tượng p2 có các thuộc tính: Tên là Jon, Giới tính: Nam, Nghề nghiệp: Bác sĩ; và có các hành vi là Làm việc(): Anh ấy là bác sĩ tại bệnh viện XYZ và hành vi Học(): Anh ấy học 15 tiếng mỗi ngày.

4.1.2.1 Định nghĩa lớp trong Python

Chúng ta có thể thấy lớp được định nghĩa ở trên là giống nhau nhưng các đối tượng được tạo ra từ cùng một lớp có thể khác nhau. Chúng có thể có các đặc tính và hành vi khác nhau. Như vậy, chúng ta thấy rằng, để tạo ra và sử dụng các đối tượng trước tiên cần phải định nghĩa một lớp. Việc định nghĩa một lớp sẽ chỉ ra các thuộc tính và hành vi có thể có cho đối tượng.

Giống như định nghĩa hàm bắt đầu bằng từ khóa def, trong Python, một lớp có thể được tạo bằng cách sử dụng từ khóa class theo sau là tên lớp. Cú pháp để tạo một lớp được đưa ra dưới đây:

1 2 3 4 5 6

class TenLop: """docstrings""" ...

• Cú pháp:

Trong đó:

• TenLop là tên được đặt cho lớp được định nghĩa, chúng ta sẽ tương tác với các đối tượng sinh ra từ lớp bằng cách sử dụng tên này.

• Chuỗi đầu tiên bên trong lớp được gọi là docstring và có nhiệm vụ mô tả ngắn gọn về lớp, mặc dù là không bắt buộc. Mỗi lớp được liên kết với một chuỗi tài liệu có thể được truy cập bằng cách sử dụng .__ doc__. • Các câu lệnh để định nghĩa các thuộc tính và hành vi (phương thức) của đối tượng trong lớp. Một lớp chứa một bộ câu lệnh bao gồm các trường, constructor, hàm,...

Một lớp tạo ra một không gian tên cục bộ mới, nơi chứa tất cả các thuộc tính và hành vi của nó. Các quy tắc về phạm vi của biến cũng áp dụng tương tự như đối với phạm vi của biến trong hàm.

Về mặt biểu diễn các khối lệnh, chúng ta cũng áp dụng các quy tắc thụt lề tương tự như hàm với lưu ý ở đây khối định nghĩa lớp là khối lệnh lớn nhất, sau đó sẽ đến các khối lệnh

4.1 Lập trình hướng đối tượng 179

định nghĩa hàm (phương thức) trong lớp, các khối điều kiện, vòng lặp... Mỗi khối lệnh nhỏ nằm trong khối lệnh lớn sẽ phải thụt dòng một khoảng bằng nhau!

class SinhVien:

"Đây là docstring của lớp SinhVien" pass

1 2 3

Ví dụ 4.1.2. Định nghĩa một lớp SinhVien.

Thông thường để code nhìn trong sáng, chúng ta nên đặt tên lớp theo quy tắc đó là tên lớp nên bắt đầu bằng chữ viết Hoa. Nếu tên lớp chứa nhiều từ, chúng ta nên sử dụng cú pháp dạng lạc đà (CamelCase), tức là viết hoa các chữ cái đầu của mỗi từ. Chẳng hạn như OfficeManager, FulltimeEmployee, SinhVien,...

Ở ví dụ trên, chúng ta chưa biết làm gì với lớp này nên chúng ta sử dụng từ khóa pass để bỏ qua các đoạn mã bắt buộc để tránh chương trình báo lỗi. Điều này giúp giữ chỗ để thêm các đoạn mã khác sau này.

Việc định nghĩa lớp cơ bản giống như chúng ta đã định nghĩa các hàm trước đây, chỉ cần thay từ khóa def bằng class. Và cũng tương tự như với hàm, khi định nghĩa lớp vẫn chưa có giá trị sử dụng, do nó chưa được cấp phát và hiểu trong chương trình. Để sử dụng nó, chúng ta phải tạo ra các đối tượng của lớp.

class Employee: id = 10 name = "Dac-Nhuong Le"

def display (self):

print(self.id, self.name)

1 2 3 4 5 6

Ví dụ 4.1.3. Tạo một lớp Employee có chứa hai trường là id và name.

4.1.2.2 Tạo một đối tượng của lớp trong Python

Ở đây, self được sử dụng như một biến tham chiếu tham chiếu đến đối tượng lớp hiện tại. Nó luôn là đối số đầu tiên trong định nghĩa hàm. Tuy nhiên, việc sử dụng self là tùy chọn trong gọi hàm. Lớp này cũng chứa một hàm display() được sử dụng để hiển thị thông tin của Employee.

Nếu chúng ta muốn sử dụng các thuộc tính hoặc phương thức trong một lớp chúng ta cần phải tạo một thể hiện của một lớp gọi là đối tượng. • Cú pháp: = ()

1 2

a=SinhVien() b=SinhVien()

Ví dụ 4.1.4. Tạo đối tượng sinh viên.

Chương 4. Lập trình hướng đối tượng với Python 180

Ở đây, chúng ta đã tạo các đối tượng a và b là các thể hiện của lớp SinhVien trong chương trình bằng cách khai báo và gán nó với hàm tạo lớp là SinhVien(). Ở đây, chúng ta có thể tạm hiểu giống như phần trước khi chúng ta tạo ra một đối tượng dữ liệu kiểu list, tuple,...chúng ta cũng dùng các hàm tạo tương ứng với các kiểu dữ liệu này. Hàm tạo sẽ có tên giống với tên lớp nhưng thêm dấu ngoặc tròn và có thể truyền vào các đối số. Nó cho phép chúng ta tạo ra một đối tượng hay một thể hiện của lớp trong chương trình, được cấp phát bộ nhớ và sẵn sàng thực hiện các hành vi tương ứng được thiết kế khi nó được gọi.

class SinhVien:

"Đây là docstring của lớp SinhVien" pass

1 2 3 4 5 6 7 8

a=SinhVien() b=SinhVien() print(a) print(b)

Ví dụ 4.1.5. In ra 2 đối tượng sinh viên được tạo.

1 2

<__main__.SinhVien object at 0x00000141029A3EB8> <__main__.SinhVien object at 0x0000014102A1A748>

Kết quả chúng ta thu được địa chỉ của chúng trong bộ nhớ:

Hai địa chỉ này khác nhau do đó, chúng ta có thể hiểu nó là hai đối tượng khác nhau.

Ở trong ví dụ này, chúng ta vẫn chưa làm được gì với lớp ngoài việc khai báo và tạo một đối tượng của lớp. Lí do đó là chúng ta chưa đưa các yếu tố tối quan trọng của đối tượng vào định nghĩa trong lớp. Đó là các thuộc tính và hành vi của đối tượng. Trong Python, các thuộc tính được hiểu là các biến và các hành vi được mô hình hóa thành các hàm, Khi một hàm nằm trong một lớp nó được gọi là phương thức.

Phương thức của đối tượng: Như đã đề cập ở trên, một đối tượng sẽ có các hành vi. Các hành vi này sẽ được mô hình hóa trong Python thành các hàm. Khi các hàm thuộc vào một lớp, nó sẽ được gọi là các phương thức. Những điều chúng ta đã học với hàm cũng được áp dụng y hệt như với phương thức. Để định nghĩa một phương thức chúng ta xét ví dụ sau:

class SinhVien:

def in_thong_tin(self):

1 2 3

print(’Sinh vien’)

Ví dụ 4.1.6. Tạo phương thức in_thong_tin() trong lớp SinhVien.

1

object_name.method_name()

Chúng ta đã định nghĩa một lớp SinhVien với phương thức in_thong_tin(). Phương thức này nhìn giống với các hàm thông thường trừ việc nó có tham số self. Để sử dụng một phương thức, chúng ta thực hiện như sau:

4.1 Lập trình hướng đối tượng 181

Việc sử dụng phương thức trong lớp tương tự khi sử dụng các phương thức join(), split(), sort(),... trong các cấu trúc dữ liệu list, tuple, tập hợp hay từ điển đã được trình bày ở Chương 3.

class SinhVien:

def in_thong_tin(self): print("Sinh viên")

a=SinhVien() a.in_thong_tin()

1 2 3 4 5 6

Ví dụ 4.1.7. Với lớp SinhVien, chúng ta sẽ tạo ra một đối tượng a và gọi phương thức in_thong_tin trên đối tượng a này.

Kết quả: Sinh viên

def in_thong_tin(self): print("Sinh vien")

in_thong_tin()

1 2 3 4

Chúng ta thấy rằng ở ví dụ trên có một điều khá lạ so với trước đây đã trình bày. Đó là, hàm in_thong_tin được khai báo có một tham số nhưng khi sử dụng chúng ta lại không đưa vào bất cứ tham số nào nhưng hàm vẫn chạy đúng. Bình thường, nếu chúng ta khai báo một hàm có đối số thì khi gọi nó chúng ta phải truyền đúng số lượng tham số, nếu không chương trình sẽ báo lỗi. Ví dụ nếu ta sử dụng như sau:

1

a.in_thong_tin()

Đoạn chương trình sẽ báo lỗi: TypeError: in_thong_tin() missing 1 required positional argument: ’self’. Tuy nhiên, với phương thức trong một lớp thì điều này không vấn đề gì. Trong lớp SinhVien, phương thức in_thong_tin() có một tham số là self. Tuy nhiên, khi gọi nó, chúng ta không cần truyền vào bất cứ tham số nào nhưng nó vẫn làm việc bình thường. Lí do đó là khi chúng ta gọi một phương thức trên một đối tượng, Python đã tự động truyển đối tượng đó vào phương thức như là tham số đầu tiên của phương thức này. Tham số self thực chất là chỉ chính đối tượng của lớp gọi đến phương thức đó. Trong ví dụ trên, khi đối tượng a gọi đến phương thức in_thong_tin():

1

a.in_thong_tin(a)

thì chính nó sẽ được truyền vào như một tham số đầu tiên của phương thức. Hay thực chất nó là:

class SinhVien:

def in_thong_tin(self):

print(self) print("Sinh viên")

1 2 3 4

Ví dụ 4.1.8. Kiểm chứng tham số self.

5 6 7 8

a=SinhVien() a.in_thong_tin() print(a)

Chương 4. Lập trình hướng đối tượng với Python 182

1 2 3

<__main__.SinhVien object at 0x000002221A9D3EB8> Sinh viên <__main__.SinhVien object at 0x000002221A9D3EB8>

Kết quả:

Chúng ta có thể thấy, địa chỉ của self và a là như nhau, hay nói cách khác hai đối tượng này tham chiếu đến cùng một đối tượng và tương đương nhau. Nguyên tắc ở đây là: tất cả các phương thức của một lớp đều phải có ít nhất một tham số (self) là đối tượng gọi đến phương thức đó.

class Employee: id = 10; name = "Dac-Nhuong Le"

def display (self):

print("ID: %d \n Name: %s" % (self.id, self.name))

1 2 3 4 5 6 7 8

emp = Employee() emp.display()

Ví dụ 4.1.9. Tạo ra thể hiện của lớp Employee đã được định nghĩa ở trên.

1 2

ID: 10 Name: Dac-Nhuong Le

Kết quả thực hiện:

1

class Car:

loaixe = "Ôtô" # thuộc tính lớp def __init__(self, tenxe, mausac, nguyenlieu):

# thuộc tính đối tượng

self.tenxe = tenxe self.mausac = mausac self.nguyenlieu = nguyenlieu

#Các thể hiện của lớp Car toyota = Car("Toyota", "Đỏ", "Điện") lamborghini = Car("Lamborghini", "Vàng", "Deisel") porsche = Car("Porsche", "Xanh", "Gas")

# access the class attributes print("Porsche là {}.".format(porsche.__class__.loaixe)) print("Toyota là {}.".format(toyota.__class__.loaixe)) print("Lamborghini cũng là {}.".format(lamborghini.__class__.loaixe))

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Ví dụ 4.1.10. Tạo lớp Car và các đối tượng

# access the instance attributes print("Xe {} có màu {}. {} là nguyên liệu vận hành.".format( toyota.tenxe, toyota.mausac, toyota.nguyenlieu)) print("Xe {} có màu {}. {} là nguyên liệu vận hành.".format( lamborghini.tenxe, lamborghini.mausac, lamborghini.nguyenlieu)) print("Xe {} có màu {}. {} là nguyên liệu vận hành.".format( porsche.tenxe, porsche.mausac, porsche.nguyenlieu))

18 19 20 21 22 23 24

4.1 Lập trình hướng đối tượng 183

Porsche là Ôtô.

1

Toyota là Ôtô.

2

Lamborghini cũng là Ôtô. Xe Toyota có màu Đỏ. Điện là nguyên liệu vận hành. Xe Lamborghini có màu Vàng. Deisel là nguyên liệu vận hành. Xe Porsche có màu Xanh. Gas là nguyên liệu vận hành.

3 4 5 6

Kết quả trả về sẽ là:

4.1.2.3 Kiểu của đối tượng và biến của lớp

Ví dụ trên tạo một lớp Car, sau đó xác định các thuộc tính, đặc điểm của đối tượng. Chúng ta truy cập thuộc tính class bằng cách sử dụng __class__.loaixe. Các thuộc tính lớp được chia sẻ cho tất cả các cá thể của lớp. Tương tự, chúng ta truy cập các thuộc tính instance bằng cách sử dụng toyota.tenxe, toyota.mausac và toyota.nguyenlieu. Tuy nhiên, các thuộc tính instance là khác nhau cho mỗi cá thể của một lớp.

1 2

print(type(vector_1)) # prints ""

Kiểu của đối tượng: Chúng ta có thể hiểu các lớp giống nhau các kiểu dữ liệu số nguyên, số thực,... còn đối tượng thì tương đương như các biến mà chúng ta dùng trước đây. Để kiểm tra kiểu của các đối tượng vừa tạo, ta có thể sử dụng hàm type():

Khi chúng ta in ra kiểu của vector_1 là một đối tượng của lớp Vector thì nó sẽ trả về kiểu của đối tượng này là: __main__.Vector. Trong đó, __main__ nghĩa là “file hiện tại mà chúng ta đang chạy” và do đó, chúng ta có thể đọc đầu ra của hàm type() ở trên là: "lớp Vector được định nghĩa ở đây, trong file mà bạn đang chạy".

Biến của lớp: Khi chúng ta muốn sử dụng cùng một dữ liệu cho toàn bộ các thể hiện của một lớp, chúng ta sử dụng một biến lớp (class variable). Một biến lớp là một biến mà nó sẽ giống nhau ở tất cả các thể hiện của lớp. Chúng ta có thể định nghĩa một biến lớp bằng cách thêm nó vào trong phần định nghĩa của lớp và có thể truy cập vào nó trong mọi đối tượng của lớp với cú pháp: object.variable.

class Circle: pi = 3.1416

1 2 3 4 5

c1 = Circle() print(c1.pi)

Ví dụ 4.1.11. Biến của lớp Circle.

Chương 4. Lập trình hướng đối tượng với Python 184

Kết quả: 3.1416

4.1.2.4 Các hàm lớp dựng sẵn của Python

Ở đoạn mã trên, chúng ta định nghĩa một lớp Circle, sau đó khởi tạo một đối tượng là c1 có kiểu là Circle. Sau đó, chúng ta có thể in ra thuộc tính pi của c1. Đây là một biến lớp và chúng ta đã gán cho nó một giá trị là 3.1416. Nếu chúng ta định nghĩa một đường tròn khác, chẳng hạn như c2=Circle() thì nó cùng có chung thuộc tính .pi như đường tròn c1 và của lớp Circle.

Các hàm dựng sẵn của Python được định nghĩa trong lớp được mô tả trong Bảng 4.1.

Bảng 4.1: Các hàm lớp dựng sẵn của Python

Tên hàm

Mô tả

getattr(obj,name,default) setattr(obj,name,value) delattr(obj,name) hasattr(obj,name)

Sử dụng để truy cập thuộc tính của đối tượng. Sử dụng để đặt một giá trị cụ thể cho thuộc tính cụ thể của một đối tượng. Sử dụng để xóa một thuộc tính cụ thể. Trả về True nếu đối tượng chứa một số thuộc tính cụ thể.

class Student:

def __init__(self, name, id, age):

self.name = name; self.id = id; self.age = age

#tạo đối tượng của lớp Student

s = Student("Dac-Nhuong Le", 101, 39) print(getattr(s, ’name’)) #in thuộc tính name của đối tượng s setattr(s, "age", 40) # gán giá trị của age cho 40 print(getattr(s, ’age’)) # in giá trị của age print(hasattr(s, ’id’)) # True nếu student chứa thuộc tính id delattr(s, ’age’) # xóa thuộc tính age print(s.age) # Hiển thị lỗi nếu age đã bị xóa

1 2 3 4 5 6 7 8 9 10 11 12 13

Ví dụ 4.1.12. Thiết lập và lấy thuộc tính của đối tượng.

Dac-Nhuong Le 40 True

print(s.age)

1 2 3 4 5

AttributeError: ’Student’ object has no attribute ’age’

4.1.2.5 Các thuộc tính lớp tích hợp của Python

Kết quả thực hiện:

Cùng với các thuộc tính khác, một lớp python cũng chứa một số thuộc tính lớp tích hợp cung cấp thông tin về lớp. Các thuộc tính lớp tích hợp được đưa ra trong Bảng 4.2.

4.1 Lập trình hướng đối tượng 185

Bảng 4.2: Các thuộc tính lớp tích hợp của Python

Tên thuộc tính Mô tả

Trả về dictionary chứa namespace của lớp. Chứa một chuỗi về tài liệu lớp. Sử dụng để truy cập tên lớp. Sử dụng để truy cập môđun trong đó, lớp này được định nghĩa. Chứa một tuple bao gồm tất cả các lớp cơ sở.

__dict__ __doc__ __name__ __module__ __bases__

class Student:

def __init__(self, name, id, age):

self.name = name; self.id = id; self.age = age

def display_details(self):

print("Name:%s, ID:%d, age:%d" % (self.name, self.id))

1 2 3 4 5 6 7 8 9 10 11

s = Student("Dac-Nhuong Le", 101, 40) print(s.__doc__) print(s.__dict__) print(s.__module__)

Ví dụ 4.1.13. Khai báo các thuộc tính của lớp sinh viên.

1 2 3

None {’name’: ’Dac-Nhuong Le’, ’id’: 101, ’age’: 40} __main__

Kết quả thực hiện:

4.1.3 Phương thức (Method)

Phương thức (method) là các hàm được định nghĩa bên trong phần thân của một lớp. Chúng được sử dụng để xác định các hành vi của một đối tượng. Tham số đầu tiên của một phương thức luôn luôn là đối tượng gọi nó. Để thuận tiện ta hay đặt tên đối số này là self. Phương thức trong lớp luôn có ít nhất một tham số (nếu ta muốn tham chiếu và sử dụng nó từ đối tượng). Phương thức có thể trả về hoặc không trả về dữ liệu. Chúng ta định nghĩa phương thức tương tự như hàm, chỉ trừ việc nó được đặt trong lớp và cách dấu dòng như khối lệnh trong lớp.

class Cat:

sound = "Meo" def shout(self): print(sound*3)

1 2 3 4 5 6

kitty = Cat() kitty.shout()

Ví dụ 4.1.14. Phương thức shout() của lớp Cat.

Kết quả: MeoMeoMeo

Chương 4. Lập trình hướng đối tượng với Python 186

Đoạn mã trên tạo lớp Cat với phương thức là shout() cùng tham số duy nhất là self, tham số này tham chiếu đến đối tượng gọi nó. Chúng ta tạo đối tượng Cat có tên là kitty và gọi phương thức .shout() nhưng không truyền tham số khi gọi nó. Bởi Python đã hiểu rằng kitty chính là đối tượng gọi và sẽ ngầm định chính là tham số self được truyền vào. Khi gọi một phương thức, nó sẽ truyền đối tượng gọi vào tham số đầu tiên của phương thức đó.

class Car:

# thuộc tính đối tượng def __init__(self, tenxe, mausac, nguyenlieu):

self.tenxe = tenxe self.mausac = mausac self.nguyenlieu = nguyenlieu

# phương thức def dungxe(self, mucdich):

return "{} đang dừng xe để {}".format(self.tenxe,mucdich)

def chayxe(self):

return "{} đang chạy trên đường".format(self.tenxe)

def nomay(self):

return "{} đang nổ máy".format(self.tenxe)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

# instantiate the Car class toyota = Car("Toyota", "Đỏ", "Điện") lamborghini = Car("Lamborghini", "Vàng", "Deisel") porsche = Car("Porsche", "Xanh", "Gas") # call our instance methods print(toyota.dungxe("nạp điện")) print(lamborghini.chayxe()) print(porsche.nomay())

Ví dụ 4.1.15. Tạo phương thức dừng xe, chạy xe và nổ máy.

1 2 3

Toyota đang dừng xe để nạp điện Lamborghini đang chạy trên đường Porsche đang nổ máy

Kết quả thực hiện:

Ở ví dụ này, có ba phương thức là dungxe(), chayxe() và nomay(). Chúng được gọi là phương thức instance bởi vì chúng được gọi trên một đối tượng instance(toyota, lamborghini, porsche).

Khi chúng ta gọi một phương thức trên một đối tượng nó có thể thực hiện các tác động đến đối với đối tượng đó. Xét ví dụ tiếp theo, đầu tiên ta định nghĩa lớp robot. Sau đó, tạo đối tượng rb và rb2. Ở đây, init() là một phương thức đóng vai trò khởi tạo cho lớp. Phương thức chao() và xuatxu() cho phép chúng ta làm những gì chúng ta muốn. Lưu ý rằng phương thức Python phải có tham số self để cho phép chúng tham chiếu đến đối tượng hiện tại.

4.1 Lập trình hướng đối tượng 187

class robot:

def __init__(self,name,madein):

self.name = name self.madein = madein

def chao(self):

print(f’Xin chao, toi la robot {self.name}’)

def xuatxu(self):

print(f"Toi den tu {self.madein}")

def cong(self,a,b): return a+b

rb = robot(’Rong vang’, ’Viet Nam’) rb2 = robot(’Bo tot’, ’Tay Ban Nha’) rb.chao() rb.xuatxu() rb2.chao() x = rb.cong(2, 3) print(x)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Ví dụ 4.1.16. Phương thức tác động lên đối tượng robot.

\item Dòng 14 in ra: Xin chào, tôi là robot Rồng vàng \item Dòng 15 in ra: Tôi đến từ Việt Nam \item Dòng 16 in ra: Xin chào, tôi là robot Bò tót \item Dòng 18 in ra: 5

1 2 3 4

Kết quả:

Phương thức trong Python được gọi trên một đối tượng không giống như một hàm. Trong ví dụ trên, ta gọi chao() trên đối tượng ‘rb’, ‘rb2’. Ngược lại, với hàm ta không gọi nó trên bất kỳ đối tượng nào mà chỉ cần gọi theo tên hàm. Về cú pháp, hàm chỉ cần gọi theo tên hàm theo cú pháp () (Ví dụ: cong(2,3)) còn phương thức phải được trỏ đến đối tượng khi gọi bằng cú pháp:

• Cú pháp: <đối tượng>.() Ví dụ: rb.cong(2,3), rb.chao() (Trong đó, ts là tham số nếu có)

4.1.4 Hàm tạo (contructor) trong Python

Chúng ta đã biết rằng, một đối tượng là một thể hiện của một lớp, khi muốn tạo ra một đối tượng chúng ta phải thực hiện khai báo và gán tên đối tượng với một thao tác tạo đối tượng thông qua phương thức tạo hay hàm tạo (Constructor). Phương thức tạo là một phương thức đặc biệt được sử dụng trong Python để sinh và khởi tạo một đối tượng của lớp. Trong bài này chúng ta sẽ cùng tìm hiểu về loại phương thức đặc biệt này.

Trong lập trình hướng đối tượng, một hàm tạo là một phương thức đặc biệt được sử dụng để sinh và khởi tạo một đối tượng của lớp. Phương thức này được định nghĩa bên trong lớp. Hàm tạo sẽ được thực thi tự động tại thời điểm tạo ra đối tượng trong chương trình và chứa các lệnh để khởi tạo các giá trị cho các thuộc tính của đối tượng. Chẳng hạn, khi chúng ta thực

Chương 4. Lập trình hướng đối tượng với Python 188

thi việc tạo một đối tượng obj = SampleClass(), Python sẽ hiểu rằng chúng ta đang muốn tạo một đối tượng tên là obj của lớp SampleClass và gọi đến hàm tạo của lớp để tạo ra đối tượng mong muốn. Quá trình tạo này sẽ bao gồm hai giai đoạn:

• Giai đoạn tạo đối tượng được thực thi ngầm định bởi phương thức __new__. • Giai đoạn khởi tạo các giá trị cho đối tượng được thực thi bằng phương thức __init__(). Ở đây, phương thức __new__ là ngầm định và chúng ta không cần phải can thiệp vào nó. Điều duy nhất chúng ta cần quan tâm ở đây đó là phương thức __init__() nhằm khởi tạo và gán các giá trị cho đối tượng.

def __init__(self, [tham số 1, tham số 2,...]):

# Thân của hàm tạo

1 2

Để định nghĩa phương thức khởi tạo __init__(), chúng ta thực hiện như định nghĩa một phương thức thông thường trong lớp. Điều khác biệt duy nhất là tên của nó. Trong Python, phương thức __init__ mô phỏng hàm dựng (contructor) của lớp. Phương thức này được gọi khi lớp được khởi tạo. Chúng ta có thể chuyển bất kỳ số lượng đối số nào tại thời điểm tạo đối tượng lớp, tùy thuộc vào định nghĩa __init__. Nó chủ yếu được sử dụng để khởi tạo các thuộc tính của lớp. Mỗi lớp phải có một constructor. - Cú pháp:

Trong đó: • def: Là từ khóa định nghĩa hàm, hay phương thức. • __init__(): Tên của phương thức tạo đặc biệt được chạy ngay khi đối tượng được tạo, và nó bắt buộc phải có tên như vậy.

• self: Tham số đầu tiên self tham chiếu đến đối tượng gọi hay đối tượng được tạo. • Các tham số còn lại là tùy chọn, chúng ta có thể sử dụng để truyền vào hàm tạo, chúng ta có thể sử dụng bao nhiêu tham số tủy thích.

class SinhVien:

def __init__(self, ID, name): print(’Trong hàm tạo’) self.ID=ID self.name = name print(’Khởi tạo giá trị cho các thuộc tính’)

def show(self):

print(’Mã sinh viên: {0}, Tên: {1}’.format(self.ID, self.name))

1 2 3 4 5 6 7 8 9 10

s1 = SinhVien(20,’Dac-Nhuong Le’) s1.show()

Ví dụ 4.1.17. Tạo lớp Student với các thuộc tính mã sinh viên (ID), tên (name).

1 2 3

Trong hàm tạo Khởi tạo giá trị cho các thuộc tính Mã sinh viên: 20, Tên: Dac-Nhuong Le

Kết quả:

4.1 Lập trình hướng đối tượng 189

class Employee:

def __init__(self, name, id):

self.id = id; self.name = name;

def display (self):

print("ID: %d \nName: %s" % (self.id, self.name))

1 2 3 4 5 6 7 8 9 10 11 12

emp1 = Employee("Dac-Nhuong Le", 101) emp2 = Employee("Nguyen Thi Hong Mai", 102) # gọi phương thức display() để hiển thị thông tin employee 1 emp1.display(); # gọi phương thức display() để hiển thị thông tin employee 2 emp2.display();

Ví dụ 4.1.18. Khởi tạo các thuộc tính của lớp Employee.

1 2 3 4

ID: 101 Name: Dac-Nhuong Le ID: 102 Name: Nguyen Thi Hong Mai

Kết quả thực hiện:

class Student:

count = 0 def __init__(self):

Student.count = Student.count + 1

1 2 3 4 5 6 7 8

s1 = Student() s2 = Student() s3 = Student() print("Số lượng sinh viên là:", Student.count)

Ví dụ 4.1.19. Đếm số lượng đối tượng của một lớp.

1

Số lượng sinh viên là: 3

Kết quả thực hiện:

class Student:

def __init__(self): #Constructor không tham số

print("Đây là constructor không tham số.")

def show(self, name):

print("Xin chào:", name)

1 2 3 4 5 6 7

student = Student() student.show("Dac-Nhuong Le")

Ví dụ 4.1.20. Tạo constructor không tham số trong Python.

1 2

Đây là constructor không tham số. Xin chào: Dac-Nhuong Le

Kết quả thực hiện:

Chương 4. Lập trình hướng đối tượng với Python 190

class Student:

def __init__(self, name):

# Constructor tham số

print("Đây là constructor tham số.") self.name = name

def show(self, name):

print("Xin chào:", name)

1 2 3 4 5 6 7 8 9

student = Student() student.show("Dac-Nhuong Le") student.show()

Ví dụ 4.1.21. Tạo constructor tham số trong Python.

1 2

Đây là constructor có tham số. Xin chào: Dac-Nhuong Le

Kết quả thực hiện:

4.1.5 Kế thừa (Inheritance)

Kế thừa (Inheritance) là một khía cạnh quan trọng của mô hình lập trình hướng đối tượng. Kế thừa cung cấp khả năng sử dụng lại mã cho chương trình vì chúng ta có thể sử dụng một lớp hiện có để tạo một lớp mới thay vì tạo nó từ đầu.

Trong kế thừa, lớp con có được các thuộc tính và có thể truy cập tất cả các thành viên dữ liệu và các hàm được định nghĩa trong lớp cha. Một lớp con cũng có thể cung cấp việc triển khai cụ thể cho các hàm của lớp cha. Tính kế thừa cho phép một lớp (class) có thể kế thừa các thuộc tính và phương thức từ các lớp khác đã được định nghĩa. Lớp đã có gọi là lớp cha, lớp mới phát sinh gọi là lớp con. Lớp con kế thừa tất cả thành phần của lớp cha, có thể mở rộng các thành phần kế thừa và bổ sung thêm các thành phần mới.

4.1.5.1 Đơn kế thừa (Single Inheritance)

Hình 4.3: Các kiểu kế thừa trong Python

Trong Python, một lớp dẫn xuất (hay còn gọi là lớp con - sub-class) có thể kế thừa lớp cơ sở (lớp cha - super-class) bằng cách chỉ đề cập đến cơ sở trong ngoặc sau tên lớp dẫn xuất. Cú pháp để một lớp cơ sở kế thừa lớp dẫn xuất như sau:

4.1 Lập trình hướng đối tượng 191

Hình 4.4: Đơn kế thừa (Single Inheritance) trong Python

class lopCha:

1 2 3 4

# Code của lớp cha class lopCon(lopCha): # Code của lớp con

Lớp con có thể sử dụng toàn bộ dữ liệu khai báo ở mức độ protected và public ở lớp cha. Riêng với private thì không được, vì đó là mức độ bảo mật cao nhất, chỉ sử dụng bên trong nội bộ của lớp cha. Đơn kế thừa (Single Inheritance) là một trong những kiểu kế thừa trong Python, trong đó chỉ có một lớp cơ sở và một lớp con. Đây là kiểu kế thừa được sử dụng thường xuyên nhất. • Cú pháp:

class Xe:

# Code ... class XeDap(Xe): # Code ...

1 2 3 4

Ví dụ 4.1.22. Khao báo lớp XeDap kế thừa từ lớp Xe.

Kế thừa thuộc tính và phương thức của lớp cha: Trong kế thừa Python thì đặc điểm hay nhất là lớp con co thể sử dụng dữ liệu của lớp cha, trừ trường hợp dữ liệu đó là private.

class Xe:

name = ’Đây là tên xe’

class XeDap(Xe):

def showName(self):

# Sử dụng thuộc tính name của lớp cha print(self.name)

# Cách dùng d = XeDap() d.showName()

1 2 3 4 5 6 7 8 9

Ví dụ 4.1.23. Sử dụng thuộc tính của lớp cha.

Kết quả: Đây là tên xe.

class Father:

# Base class

def function_1(self):

print (’I am father.’)

1 2 3

Ví dụ 4.1.24. Lớp Children đơn thừa kế từ lớp Father.

class Children(Father): # Child class

def function_2(self):

print (’I am son.’)

4 5 6 7 8 9 10

object = Children() object.function_1() object.function_2()

Chương 4. Lập trình hướng đối tượng với Python 192

1 2

I am father. I am son.

Kết quả:

class Animal:

def speak(self):

print("Animal Speaking")

# lớp con Dog kế thừa lớp Animal class Dog(Animal): def bark(self):

print("Gou gou!")

1 2 3 4 5 6 7 8 9 10 11

d = Dog() d.bark() d.speak()

Ví dụ 4.1.25. Lớp Dog đơn kế thừa lớp Animal trong Python.

1 2

Gou gou! Animal Speaking

4.1.5.2 Kế thừa đa cấp (Multilevel Inheritance)

Kết quả thực hiện:

Kế thừa đa cấp (Multilevel Inheritance) có thể có trong python như các ngôn ngữ hướng đối tượng khác. Kế thừa đa cấp khi một lớp dẫn xuất kế thừa một lớp dẫn xuất khác. Không có giới hạn về số lượng cấp độ, kế thừa đa cấp trong Python.

Hình 4.5: Kế thừa đa cấp trong Python

Cú pháp kế thừa đa cấp:

class class1:

class class2(class1): class class3(class2):

... class classN(classN-1):

1 2 3 4 5 6 7 8 9

4.1 Lập trình hướng đối tượng 193

class Animal:

def speak(self):

print("Animal Speaking")

class Dog(Animal): #lớp con Dog kế thừa lớp Animal

def bark(self):

print("Gou gou!")

class DogChild(Dog): #lớp con Dogchild kế thừa lớp Dog

def eat(self):

print("Eating milk...")

1 2 3 4 5 6 7 8 9 10 11 12 13 14

d = DogChild() d.bark() d.speak() d.eat() d.speak()

Ví dụ 4.1.26. Kế thừa đa cấp trong Python.

1 2 3 4

Gou gou! Animal Speaking Eating milk... Animal Speaking

4.1.5.3 Đa thừa kế (Multiple Inheritance)

Kết quả:

class Base1:

class Base2:

... class BaseN:

class Derived(Base1, Base2, ...... BaseN):

1 2 3 4 5 6 7 8 9 10

Python cung cấp cho chúng ta sự linh hoạt để kế thừa nhiều lớp cơ sở trong lớp con. Một lớp có thể kế thừa nhiều lớp bằng cách đề cập đến tất cả chúng trong dấu ngoặc. • Cú pháp:

Chương 4. Lập trình hướng đối tượng với Python 194

Hình 4.6: Đa thừa kế (Multiple Inheritance) trong Python

class A: # Base class1

aname = ’’ def aclass(self):

print (self.aname)

class B: # Base class2

bname = ’’ def bclass(self):

print (self.bname

class C(A, B): # Child class

def cname(self):

print (’B :’, self.bname) print (’A :’, self.aname)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

s1 = C() s1.bname = ’Mohit’ s1.aname = ’Ashutosh’ s1.cname()

Ví dụ 4.1.27. Khai báo lớp C kế thừa thuộc tính của lớp B và lớp A.

1 2

B: Mohit A: Ashutosh

Kết quả:

class Calculation1:

def Summation(self, a, b):

return a + b;

class Calculation2:

def Multiplication(self, a, b):

return a * b;

class Derived(Calculation1, Calculation2):

def Divide(self, a, b):

return a / b;

1 2 3 4 5 6 7 8 9 10 11 12 13

d = Derived() print(d.Summation(10, 20)) print(d.Multiplication(10, 20)) print(d.Divide(10, 20))

Ví dụ 4.1.28. Đa kế thừa trong Python.

4.1 Lập trình hướng đối tượng 195

1 2 3

30 200 0.5

Kết quả:

Phương thức issubclass(sub,sup): Phương thức này được sử dụng để kiểm tra mối quan hệ giữa các lớp được chỉ định. Nó trả về true nếu lớp thứ nhất là lớp con của lớp thứ hai và ngược lại là False.

class Calculation1:

def Summation(self, a, b):

return a + b;

class Calculation2:

def Multiplication(self, a, b):

return a * b;

class Derived(Calculation1, Calculation2):

def Divide(self, a, b):

return a / b;

1 2 3 4 5 6 7 8 9 10 11

print("Derived la con cua Calculation2:", issubclass(Derived,Calculation2)) print("Calculation1 la con cua Calculation2:", issubclass(Calculation1,Calculation2))

Ví dụ 4.1.29. Phương thức kiểm ra mối quan hệ giữa các lớp được chỉ định.

1 2

Derived la con cua Calculation2: True Calculation1 la con cua Calculation2: False

Kết quả:

Phương thức isinstance(obj,class): Phương thức này được sử dụng để kiểm tra mối quan hệ giữa các đối tượng và các lớp. Nó trả về true nếu tham số đầu tiên, tức là obj là thể hiện của tham số thứ hai, tức là lớp.

class Calculation1:

def Summation(self, a, b):

return a + b;

class Calculation2:

def Multiplication(self, a, b):

return a * b;

class Derived(Calculation1, Calculation2):

def Divide(self, a, b):

return a / b;

1 2 3 4 5 6 7 8 9 10 11

d = Derived() print("Doi tuong d la the hien cua lop Derived: ", isinstance(d,Derived))

Ví dụ 4.1.30. Phương thức isinstance(obj,class) kiểm tra mối quan hệ giữa các đối tượng và các lớp.

1

Doi tuong d la the hien cua lop Derived: True

Kết quả:

Chương 4. Lập trình hướng đối tượng với Python 196

# Lớp cha class Car:

def __init__(self, hangxe, tenxe, mausac): #Hàm Constructor

# Lớp Car có 3 thuộc tính: tenxe, mausac, hang xe self.hangxe = hangxe self.tenxe = tenxe self.mausac = mausac

def chayxe(self): # phương thức

print ("{} đang chạy trên đường".format(self.tenxe))

def dungxe(self, mucdich):

print ("{} đang dừng xe để {}".format(self.tenxe, mucdich))

class Toyota(Car): # Lớp Toyota mở rộng từ lớp Car.

def __init__(self, hangxe, tenxe, mausac, nguyenlieu):

# Gọi tới constructor của lớp cha (Car) để gán giá trị thuộc tính của lớp cha super().__init__(hangxe, tenxe, mausac) self.nguyenlieu = nguyenlieu

def chayxe(self): # Kế thừa phương thức cũ

print ("{} đang chạy trên đường".format(self.tenxe))

# Ghi đè (override) phương thức cùng tên của lớp cha. def dungxe(self, mucdich):

print ("{} đang dừng xe để {}".format(self.tenxe, mucdich)) print ("{} chạy bằng {}".format(self.tenxe, self.nguyenlieu))

def nomay(self): # Bổ sung thêm thành phần mới print ("{} đang nổ máy".format(self.tenxe))

toyota1 = Toyota("Toyota", "Toyota Hilux", "Đỏ", "Điện") toyota2 = Toyota("Toyota", "Toyota Yaris", "Vàng", "Deisel") toyota3 = Toyota("Toyota", "Toyota Vios", "Xanh", "Gas")

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

toyota1.dungxe("nạp điện") toyota2.chayxe() toyota3.nomay()

Ví dụ 4.1.31. Tạo hai lớp kế thừa, lớp cha Car và lớp con Toyota.

1 2 3 4

Toyota Hilux đang dừng xe để nạp điện Toyota Hilux chạy bằng Điện Toyota Yaris đang chạy trên đường Toyota Vios đang nổ máy

Kết quả trả về sẽ là:

Khai báo constructor mới để gán giá trị vào thuộc tính của lớp cha. Hàm super() đứng trước phương thức __init __ để gọi tới nội dung __init __ của Car.

Class Toyota kế thừa hàm chayxe() và dungxe() của class Car đồng thời sửa đổi một hành vi thể hiện ở phương thức dungxe(). Sau đó lớp con bổ sung thêm thành phần mới là nomay() để mở rộng kế thừa.

4.1.5.4 Kế thừa phân cấp (Hierarchical Inheritance)

4.1 Lập trình hướng đối tượng 197

Kế thừa phân cấp (Hierarchical Inheritance) thuật ngữ được sử dụng để mô tả các tình huống có nhiều lớp dẫn xuất từ một lớp cơ sở duy nhất. Trong Hình 4.7, lớp A và B kế thừa thuộc tính của lớp C, thể hiện tính kế thừa phân cấp.

Hình 4.7: Kế thừa phân cấp (Hierarchical Inheritance)trong Python

# Base class class A:

def function_1(self):

print (’Parent of B and C’)

# Derived class1 class B(A):

def function_2(self):

print (’Child class of A’)

# Derivied class2 class C(A):

def function_3(self):

print (’Child class of A’)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

object1 = C() object2 = B() object1.function_1() object1.function_3() object2.function_1() object2.function_2()

Ví dụ 4.1.32. Kế thừa phân cấp lớp A và B kế thừa thuộc tính của lớp C.

1 2 3 4

Parent of B and C Child class of A Parent of B and C Child class of A

Kết quả:

4.1.5.5 Kế thừa lai (Hybrid Inheritance)

Chương 4. Lập trình hướng đối tượng với Python 198

Kế thừa lai (Hybrid Inheritance) là sự kết hợp nhiều kế thừa với kế thừa đa cấp. Một lớp có thể có hai hoặc nhiều lớp cha nhưng chỉ một trong số chúng có thể có lớp dẫn xuất. Trong Hình 4.8, lớp D có nguồn gốc từ lớp B và C, trong khi lớp B được kế thừa từ lớp A.

Hình 4.8: Kế thừa lai (Hybrid Inheritance) trong Python

class Office:

def func1(self):

print (’This function is in Office.’)

class Emp1(Office): def func2(self):

print (’This function is in Employee 1.’)

class Emp2:

def func3(self):

print (’This function is in Employee 2.’)

class Emp3(Emp1, Emp2): def func4(self):

print (’This function is in Employee 3.’)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

# Driver’s code object = Emp3() object.func1() object.func2()

Ví dụ 4.1.33. Kế thừa lai.

1 2

This function is in Office. This function is in Employee 1.

Kết quả:

4.1.6 Đóng gói (Encapsulation)

Sử dụng lập trình hướng đối tượng trong Python, chúng ta có thể hạn chế quyền truy cập vào trạng thái bên trong của đối tượng. Điều này ngăn chặn dữ liệu bị sửa đổi trực tiếp, được gọi là đóng gói. Trong Python, chúng ta biểu thị thuộc tính private này bằng cách sử dụng dấu gạch dưới làm tiền tố: “_” hoặc “__”.

4.1 Lập trình hướng đối tượng 199

class Computer:

def __init__(self):

self.__maxprice = 900

def sell(self):

print("Giá bán sản phẩm là: {}".format(self.__maxprice))

def setMaxPrice(self, price): self.__maxprice = price

c = Computer() c.sell() c.__maxprice = 1000 # thay đổi giá c.sell() c.setMaxPrice(1000) # sử dụng hàm để thay đổi giá: c.sell()

1 2 3 4 5 6 7 8 9 10 11 12 13

Ví dụ 4.1.34. Hạn chế quyền truy cập thông qua thuốc tính private.

1 2 3

Giá bán sản phẩm là: 900 Giá bán sản phẩm là: 900 Giá bán sản phẩm là: 1000

Kết quả trả về sẽ là:

Ở ví dụ này, chúng ta đã khởi tạo class Computer, sử dụng __init __() để lưu trữ giá bán tối đa của máy tính. Nhưng sau khi sử dụng, chúng ta có nhu cầu sửa đổi giá, tuy nhiên không thể thay đổi theo cách bình thường vì Python đã coi __maxprice là thuộc tính private. Vậy nên để thay đổi giá trị, ta sử dụng hàm setter setMaxPrice().

4.1.7 Đa hình (Polymorphism)

Tính đa hình (Polymorphism) là khái niệm dùng để chỉ hai hoặc nhiều lớp có những phương thức giống nhau nhưng có thể thực thi theo những cách thức khác nhau.

Giả sử, chúng ta cần tô màu một hình khối, có rất nhiều lựa chọn cho hình của chúng ta như hình chữ nhật, hình vuông, hình tròn. Tuy nhiên, chúng ta có thể sử dụng cùng một phương pháp để tô màu bất kỳ hình dạng nào.

class Toyota:

def dungxe(self):

print("Toyota dừng xe để nạp điện")

def nomay(self):

print("Toyota nổ máy bằng hộp số tự động")

class Porsche:

def dungxe(self):

print("Porsche dừng xe để bơm xăng")

def nomay(self):

print("Porsche nổ máy bằng hộp số cơ")

def kiemtra_dungxe(car): car.dungxe() # common interface # instantiate objects

1 2 3 4 5 6 7 8 9 10 11 12

Ví dụ 4.1.35. Tính đa hình trong lập trình hướng đối tượng.

13 14 15 16 17

toyota = Toyota() porsche = Porsche() # passing the object kiemtra_dungxe(toyota) kiemtra_dungxe(porsche)

Chương 4. Lập trình hướng đối tượng với Python 200

1 2

Toyota dừng xe để nạp điện Porsche dừng xe để bơm xăng

Ở ví dụ này, chúng ta vừa tạo hai lớp Toyota và Porsche, cả hai lớp đều có phương thức dungxe(). Tuy nhiên, hàm của chúng khác nhau. Chúng ta sử dụng tính đa hình để tạo hàm chung cho hai lớp, đó là kiemtra_dungxe(). Tiếp theo, chúng ta truyền đối tượng toyota và porsche vào hàm vừa tạo và ta lấy được kết quả như sau:

4.1.8 Ghi đè phương thức (Method Overriding)

Chúng ta có thể cung cấp một số triển khai cụ thể của phương thức lớp cha trong lớp con. Khi phương thức lớp cha được định nghĩa trong lớp con với một số triển khai cụ thể, thì khái niệm này được gọi là ghi đè phương thức trong Python.

class Animal:

def speak(self):

print("Speaking...")

class Dog(Animal):

def speak(self):

print("Barking...")

class Cat(Animal):

def speak(self):

print("Meo meo...")

1 2 3 4 5 6 7 8 9 10 11 12 13

d = Dog() d.speak() c = Cat() c.speak()

Ví dụ 4.1.36. Ghi đè phương thức speak trong lớp Animal với lớp con Dog và Cat.

1 2

Barking... Meo meo...

Kết quả:

class Bank:

def getROI(self): return 10;

class ACB(Bank):

1 2 3 4 5 6 7

def getROI(self): return 7; class BIDV(Bank):

Ví dụ 4.1.37. Ghi đè phương thức getROI trong lớp Bank với lớp con ACB và BIDV..

def getROI(self): return 8;

8 9 10 11 12 13 14 15

b1 = Bank() b2 = ACB() b3 = BIDV() print("Lãi suất tiết kiệm:", b1.getROI()); print("Lãi suất tiết kiệm của ACB:", b2.getROI()); print("Lãi suất tiết kiệm của BIDV:", b3.getROI());

4.2 Thao tác trên module trong Python 201

1 2 3

Lãi suất tiết kiệm: 10 Lãi suất tiết kiệm của ACB: 7 Lãi suất tiết kiệm của BIDV: 8

Kết quả:

4.1.9 Trừu tượng dữ liệu trong Python

Trừu tượng là một khía cạnh quan trọng của lập trình hướng đối tượng. Trong python, chúng ta cũng có thể thực hiện ẩn dữ liệu bằng cách thêm dấu gạch dưới kép (__) làm tiền tố cho thuộc tính cần ẩn. Sau này, thuộc tính sẽ không hiển thị bên ngoài lớp thông qua đối tượng.

class Employee: __count = 0;

def __init__(self):

Employee.__count = Employee.__count + 1

def display(self):

print("Số lượng nhân viên: ", Employee.__count)

emp1 = Employee() emp2 = Employee() try:

print(emp1.__count)

finally:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

emp1.display()

Ví dụ 4.1.38. Trừu tượng dữ liệu trong Python.

1 2

Số lượng nhân viên: 2 AttributeError: ’Employee’ object has no attribute ’__count’

Kết quả:

4.2 Thao tác trên module trong Python

4.2.1 Khái niệm module

Module trong Python được sử dụng để phân loại code thành các phần nhỏ hơn liên quan với nhau. Hay nói cách khác, Module giúp người lập trình tổ chức Python code một cách logic để giúp dễ dàng hiểu và sử dụng hơn.

Chương 4. Lập trình hướng đối tượng với Python 202

Module là một đối tượng với các thuộc tính có thể đặt tên tùy ý và chúng ta có thể gắn kết và tham chiếu. Về cơ bản, mỗi module là một file gồm các lớp, hàm và biến được định nghĩa sẵn. Tất nhiên, một module cũng có thể bao gồm code có thể chạy phục vụ cho một chức năng cụ thể, được sắp xếp tùy vào cách thiết kế của mỗi lập trình viên. Trong Python, modules là những file có phần mở rộng .py.

Chúng ta xét ví dụ sau: Nếu nội dung của một quyển sách không được lập chỉ mục hoặc phân loại thành các chương riêng, thì quyển sách này có thể trở nên nhàm chán và gây khó khăn cho độc giả khi đọc và hiểu nó. Tương tự, module trong Python là các file mà có các code tương tự nhau hay có liên quan với nhau. Khi tổ chức như vậy sẽ đem lại các lợi thế sau: • Khả năng tái sử dụng: Module có thể được sử dụng ở trong phần Python code khác cho phép tăng tính tái sử dụng code. • Khả năng phân loại: Các kiểu thuộc tính tương tự nhau có thể được đặt trong một module.

def print_func( par ):

1 2 3

print "Hello : ", par return

Ví dụ 4.2.1. Hàm có tên là print_func được đặt bên trong module test.py

Để sử dụng các hàm của module A trong module B thì chúng ta phải sử dụng từ khóa import, sau đó chúng ta có thể sử dụng toàn bộ tài nguyên của module A.

4.2.2 Cách tạo module trong Python

Trước khi tạo một module thì người lập trình phải xác định rằng nhu cầu cần tạo một module tên gì? nằm phục vụ một công việc gì? Để từ đó đặt tên module cho có ngữ nghĩa. Giả sử chúng ta cần tạo một thư viện chứa những hàm dùng để quản lý sinh viên, lúc này mình sẽ tạo một file tên là students.py cùng cấp với file chạy chính như sau:

Hình 4.9: Tạo module trong Python

def showStudent(name):

1 2

print(name)

Sau khi thực hiện, chúng ta có file helloworld.py là file chương trình chính của project, còn file students.py là module chứa những hàm quản lý sinh viên sắp viết vào. Trong file students.py, chúng ta dùng lệnh def để tạo một hàm như sau:

4.2 Thao tác trên module trong Python 203

# Goi den module students import students

# Goi den ham showStudent trong module students students.showStudent("Le Dac Nhuong")

1 2 3 4 5

Trong file helloworld.py, chúng ta viết đoạn code sau:

1

Le Dac Nhuong

Chạy file chính helloworld.py lên thì chúng ta sẽ thấy kết quả như sau:

1 2

students.name students.showMessage()

Giả sử trong module students có biến name và hàm showMessage, lúc này chúng ta sẽ gọi đến biến và hàm này như sau:

4.2.3 Lệnh import trong Python

Để sử dụng các đoạn code ở module A vào trong module B thì ta sẽ phải sử dụng lệnh import. Chúng ta có thể sử dụng một trong ba cách sau: Cách 1: Sử dụng lệnh import. Để sử dụng bất cứ source file nào dưới dạng như một module, chúng ta thực thi lệnh import trong source file khác. Cú pháp của lệnh import là:

• Import một module: import module • Import một lúc nhiều module: import module1[, module2[,... moduleN]

# Goi den module students import students

# Lay du lieu print("Hay nhap ten cua sinh vien") name = input()

# Goi den ham showStudent students.showStudent(name)

1 2 3 4 5 6 7 8 9

Ví dụ 4.2.2. Sử dụng hàm showStudent trong module students.

def add(a,b): c=a+b print c return

1 2 3 4

Ví dụ 4.2.3. Chúng ta có đoạn code của hàm add() như sau:

import addition addition.add(10,20) addition.add(30,40)

1 2 3

Đoạn code trên được lưu file dưới tên là addition.py, để sử dụng file chúng ta dùng lệnh import như sau:

Chương 4. Lập trình hướng đối tượng với Python 204

1 2

30 70

Trong đó, addition.add() thì addition là tên file và add() là phương thức đã được định nghĩa trong addion.py. Khi đó, chúng ta có thể sử dụng phương thức đã được định nghĩa trong module bằng cách là ten_file.phuong_thuc(). Code trên sẽ cho kết quả:

Chúng ta có thể truy cập bất cứ hàm nào bên trong một module theo phương thức như trên.

def msg_method():

1 2 3

print "Hom nay troi mua" return

Ví dụ 4.2.4. Thực hiện import nhiều module. - File msg.py có nội dung như sau:

def display_method():

1 2 3

print "Thoi tiet kha am uot" return

- File display.py có nội dung như sau:

1 2 3

import msg,display msg.msg_method() display.display_method()

- File multiimport.py có nội dung như sau:

1 2

Hom nay troi mua Thoi tiet kha am uot

Kết quả là:

Cách 2: Sử dụng lệnh from...import. Lệnh này được sử dụng để import thuộc tính cụ thể từ một Module. Trong trường hợp mà chúng ta không muốn import toàn bộ module nào đó thì có thể sử dụng lệnh này. • Cú pháp: from import name1[, name2[, ... nameN]]

def circle(r):

1 2 3 4 5 6 7 8 9

print 3.14*r*r returndef square(l): print l*l returndef rectangle(l,b): print l*b returndef triangle(b,h): print 0.5*b*h return

Ví dụ 4.2.5. Sử dụng lệnh from...import. - File area.py có nội dung như sau:

- File area1.py có nội dung như sau:

from area import square,rectangle square(10) rectangle(2,5)

1 2 3

4.2 Thao tác trên module trong Python 205

100 10

1 2

Kết quả thực hiện là:

#Doan code trong file calculation.py def summation(a,b): return a+b

def multiplication(a,b):

return a*b def divide(a,b): return a/b

1 2 3 4 5 6 7

Ví dụ 4.2.6. Tính tổng 2 số. - Fie calculation.py có nội dung như sau:

1 2 3 4 5

from calculation import summation # No se import duy nhat ham summation() trong file calculation.py a = int(input("Nhap so thu nhat: ")) b = int(input("Nhap so thu hai: ")) print("Sum = ",summation(a,b))

- Fie main.py có nội dung như sau:

1 2 3

Nhap so thu nhat: 10 Nhap so thu hai: 20 Sum = 30

Kết quả thực thi là:

Cách 3: Sử dụng lệnh from...import*. Lệnh này dùng để import toàn bộ module. Do đó, chúng ta có thể truy cập các thuộc tính trong module này. • Cú pháp: from import*

1 2 3 4 5

from area import * square(10) rectangle(2,5) circle(5) triangle(10,20)

Ví dụ 4.2.7. Import file area.py ở ví dụ trên.

1 2 3 4

100 10 78.5 100.0

Kết quả là:

Chương 4. Lập trình hướng đối tượng với Python 206

4.2.4 Đổi tên module với as

Nếu chúng ta muốn đổi tên module cho ngắn gọn và dễ hiểu thì có thể sử dụng từ khóa AS. Từ khóa này rất hữu ích vì giúp người lập trình tiết kiệm được thời gian nhập những module có tên quá dài, thay vao đó chỉ cần một tên thật đặc biệt. • Cú pháp: import as

#Ten cua module calculation o vi du truoc se doi thanh cal. import calculation as cal a = int(input("Enter a?")) b = int(input("Enter b?")) print("Sum = ",cal.summation(a,b))

1 2 3 4 5

Ví dụ 4.2.8. Thay đổi tên module calculation thành cal.

4.2.5 Xem thuộc tính và phương thức của module

Hàm dir() có công dụng trả về danh sách các thuộc tính và phương thức của module.

1 2 3

import json List = dir(json) print(List)

Ví dụ 4.2.9. Xem những tên biến, hàm có sẵn trong module json.

1 2 3 4

[’JSONDecoder’, ’JSONEncoder’, ’__all__’, ’__author__’, ’__builtins__’, ’__cached__’, ’__doc__’,’__file__’, ’__loader__’, ’__name__’, ’__package__’, ’__path__’,’__spec__’, ’__version__’,’_default_decoder’, ’_default_encoder’, ’decoder’,’dump’, ’dumps’, ’encoder’, ’load’, ’loads’, ’scanner’]

Kết quả thực hiện là:

4.2.6 Tải lại module với hàm reload

Trong Python, khi chúng ta import một module thì nó sẽ thực hiện một lần duy nhất, cho dù sử dụng đoạn code import bao nhiêu lần đi nữa. Tuy nhiên có một số trường hợp người lập trình muốn tải lại dữ liệu mới nhất của module đó thì có thể sử dụng hàm reload(). • Cú pháp: reload()

1

reload(calculation)

Ví dụ 4.2.10. Tải lại module calculation đã được định nghĩa ở các ví dụ trước.

4.2.7 Phạm vi của biến của module trong Python

Như tất cả các ngôn ngữ lập trình khác, chúng ta có hai dạng biến như sau: • Biến toàn cục: là biến có thể sử dụng ở tất cả các vị trí trong chương trình chính, trừ trong hàm. • Biến cục bộ: Là biến chỉ sử dụng được trong một phạm vi nhất định, ví dụ trong hàm.

4.3 Thao tác trên các module có sẵn (built-in) trong Python 207

Vậy khi chúng ta khai báo một biến trong module thì có thể sử dụng tai mọi vị trí trong module đó. Tuy nhiên trong hàm thì không thể gọi đến biến cục bộ đó.

# Day la bien toan cuc name = "john" def print_name(name):

# Bien nay la bien cuc bo, gia tri cua no duoc truyen vao print("Xin chao",name)

1 2 3 4 5 6 7

name = input("Nhap ten cua ban?") print_name(name)

Ví dụ 4.2.11. Biến name đã được khai báo ở cấp ngoài cùng và trong hàm, đây là 2 biến hoàn toàn khác nhau.

4.3 Thao tác trên các module có sẵn (built-in) trong Python

1

print (help(’modules’) )

Phần trên, chúng ta đã tìm hiểu cách tạo ra module cho riêng mình và cách import chúng. Phần này sẽ giới thiệu các module đã được xây dựng sẵn trong Python như: math, random, threading, collections, os, mailbox, string, time, . . . Mỗi module này đã được định nghĩa sẵn rất nhiều hàm để sử dụng và thực hiện các tính năng khác nhau. Để xem danh sách các module có sẵn trong Python thì ta sử dụng lệnh sau:

Chúng ta xét ví dụ với module là math có các hàm đã được giới thiệu trong các chương trước.

1 2 3 4 5 6 7 8 9 10 11 12

import math a=4.6 print (math.ceil(a)) print (math.floor(a)) b=9 print (math.sqrt(b)) print (math.exp(3.0)) print (math.log(2.0)) print (math.pow(2.0,3.0)) print (math.sin(0)) print (math.cos(0)) print (math.tan(45))

Ví dụ 4.3.1. Sử dụng các hàm có sẵn trong module math.

4.3.1 Module Date và Time

Để gọi time hiện tại trong Python, chúng ta sử dụng hàm localtime() nhận một tham số là time.time() trả về thời gian hiện tại của hệ thống. Trong đó, time là module và time() là hàm của module time.

Chương 4. Lập trình hướng đối tượng với Python 208

import time; localtime = time.localtime(time.time()) print("Thoi gian hien tai la :", localtime)

1 2 3

Ví dụ 4.3.2. Lấy thời gian hiện tại.

1 2

Thoi gian hien tai la : time.struct_time(tm_year=2023, tm_mon=9, tm_mday=28, tm_hour=7, tm_min=28, tm_sec=7, tm_wday=3, tm_yday=271, tm_isdst=0)

Kết quả thực hiện:

Các thuộc tính của Time được liệt kê trong Bảng 4.3.

Bảng 4.3: Thuộc tính của Time

Tên thuộc tính Mô tả

Trả về năm hiện tại (ví dụ: 2023) Trả về tháng hiện tại (1-12) Trả về ngày hiện tại (1-31) Trả về giờ hiện tại (0-23) Trả về phút hiện tại (0-59) Trả về giây hiện tại (0-61 với 60 và 61 là các giây nhuận) Trả về ngày trong tuần (0-6 với 0 là Monday) Trả về ngày trong năm (1-366 kể cả năm nhuận) Trả về -1, 0 hoặc 1 tức là có xác định DST không

tm_year tm_mon tm_mday tm_hour tm_min tm_sec tm_wday tm_yday tm_isdst

Gọi time đã được định dạng trong Python: Chúng ta có thể định dạng bất kỳ time nào theo yêu cầu của mình, nhưng phương thức đơn giản nhất là asctime(). Đây là một hàm đã được định nghĩa trong module time. Hàm này trả về một time đã được định dạng bao gồm ngày trong tuần, tháng, ngày trong tháng, thời gian và năm.

1 2 3

import time; localtime = time.asctime( time.localtime(time.time())) print("Thoi gian da duoc dinh dang la :", localtime)

Ví dụ 4.3.3. Gọi time đã được định dạng trong Python.

1

Thoi gian da duoc dinh dang la : Thu Aug 16 11:15:30 2023

Kết quả là:

Có nhiều hàm được định nghĩa sẵn trong module time được liệt kê trong Bảng 4.4, chúng ta có thể được sử dụng khi làm việc.

Có hai thuộc tính quan trọng có sẵn với module time là: • time.timezone: Thuộc tính này là số giây trong local timezone (không DST) từ UTC (>0 trong Americas; <=0 trong Europe, Asia, Africa). • time.tzname: Thuộc tính này là một cặp các chuỗi biểu diễn locale và biểu diễn phụ thuộc, mà tương ứng là tên của local timezone với và không với DST.

4.3 Thao tác trên các module có sẵn (built-in) trong Python 209

Bảng 4.4: Các hàm được định nghĩa sẵn trong module time

Tên hàm

Mô tả

Trả về offset của DST timezone (số giây). Chấp nhận time-tuple và trả về một chuỗi gồm 24 ký tự có thể đọc được Trả về CPU time hiện tại dưới dạng số giây dạng số thực. Giống asctime(localtime(secs)), không có tham số thì như asctime(). Chuyển đổi time biểu diễn số giây từ epoch sang struct_time trong UTC Tương tự như gmtime() nhưng chuyển đổi số giây thành local time. Là ngược với hàm localtime(). Trả về một số thực để tương thích với time() Dừng trình thực thi trong số giây đã cho là secs Chuyển đổi tuple hoặc struct_time thành chuỗi xác định bởi tham số format. Parse một chuỗi biểu diễn time theo một định dạng đã cho.

time.altzone time.asctime([tupletime]) time.clock() time.ctime([secs]) time.gmtime([secs]) time.localtime([secs]) time.mktime(tupletime) time.sleep(secs) time.strftime(fmt[,tupletime]) time.strptime(str,fmt=’%a %b %d %H:%M:%S %Y’) time.time() time.tzset()

Trả về time dưới dạng số thực được biểu diễn qua số giây từ epoch trong UTC. Phục hồi các qui ước về thời gian được sử dụng bởi các chương trình. con của thư viện. Biến môi trường TZ xác định cách được thực hiện.

4.3.2 Module Calendar trong Python

Python cung cấp module calendar giúp hiển thị lịch. Có rất nhiều hàm và phương thức đã được xây dựng sẵn trong module calendar giúp lập trình viên làm việc với calendar. Bảng 4.3 trình bày một số hàm và phương thức thông dụng:

Bảng 4.5: Các hàm được định nghĩa sẵn trong module calendar

Tên hàm

Mô tả

In cả calendar của năm. Trả về ngày trong tuần đầu tiên. Mặc định là 0 biểu diễn Monday. Trả về true nếu năm đã cho là năm nhuận, nếu không là False. Trả về list gồm các ngày trong tháng đã cho của năm dưới dạng các tuần. Trả về số ngày nhuận từ năm year1 tới năm year2. In ra tháng đã cho của năm đã cung cấp.

prcal(year) firstweekday() isleap(year) monthcalendar(year,month) leapdays(year1,year2) prmonth(year,month)

1 2

import calendar print(calendar.firstweekday())

Ví dụ 4.3.4. Hiển thị ngày trong tuần đầu tiên với hàm firstweekday().

Kết quả là: 0

1 2

import calendar print(calendar.isleap(2023))

Ví dụ 4.3.5. Kiểm tra năm nhuận với hàm isleap(year).

Kết quả là: False

1 2

import calendar print(calendar.monthcalendar(2023,8))

Ví dụ 4.3.6. In ra tháng đã cho của năm với hàm monthcalendar(year,month).

Chương 4. Lập trình hướng đối tượng với Python 210

Thang hien tai la: August 2023 Mo Tu We Th Fr Sa Su

3 4 5 6 1 2 8 9 10 11 12 13

7 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

1 2 3 4 5 6 7 8

Kết quả là:

1 2

import calendar print calendar.prmonth(2015,11)

Ví dụ 4.3.7. Hiển thị các ngày trong tháng đã cho của năm dưới dạng các tuần với hàm prmonth(year,month).

1 2

[[0, 0, 0, 0, 0, 0, 1], [2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22], [23, 24, 25, 26, 27, 28, 29], [30, 0, 0, 0, 0, 0, 0]]

Kết quả là:

4.3.3 Module Math trong Python

Module math trong Python được định nghĩa là các hàm toán học phổ biến nhất, bao gồm các hàm lượng giác, hàm số, hàm logarit, v.v. Ngoài ra, nó cũng định nghĩa hai hằng số toán học là số Pie và Euler,... • Pie(n): Đây là hằng số toán học nổi tiếng và được định nghĩa là tỷ lệ chu vi với đường kính của một đường tròn. Giá trị tương ứng là 3.141592653589793. • Số Euler(e): Được định nghĩa là cơ sở của logarit tự nhiên và giá trị của nó là 2.718281828459045.

Một số module toán học thông dụng được sử dụng gồm: 1) Hàm math.log(): Trả về logarit tự nhiên của một số đã cho. Nó được tính dựa trên hằng số e.

1 2 3

import math number = 2e-7 print(’log(fabs(x), base) la :’, math.log(math.fabs(number), 10))

Ví dụ 4.3.8. Tính logarit tự nhiên của một số.

Kết quả thực hiện: log(fabs(x), base) la : -6.698970004336019

2) Hàm math.log10(): Trả về logarit cơ số 10 của số đã cho và được gọi là logarit tiêu chuẩn.

Ví dụ 4.3.9. Tính logarit cơ số 10 của một số.

1 2 3

import math x=13 print(’log10(x) la :’, math.log10(x))

4.3 Thao tác trên các module có sẵn (built-in) trong Python 211

Kết quả thực hiện: log10(x) la : 1.1139433523068367

3) Hàm math.exp(): Trả về một số dấu phẩy động sau khi nâng e lên số đã cho.

import math number = 5e-2 print(’The given number (x) is :’, number) print(’e^x (using exp() function) is :’, math.exp(number) - 1)

1 2 3 4

Ví dụ 4.3.10. Tính số mũ e của một số.

The given number (x) is : 0.05 e^x (using exp() function) is : 0.05127109637602412

1 2

Kết quả thực hiện:

4) Hàm math.sqrt(): Trả về căn bậc hai của bất kỳ số nào.

1 2 3 4 5 6 7

import math x = 20 y = 9 z = 30.5 print(’Can bac hai cua 20 la ’, math.sqrt(x)) print(’Can bac hai cua 9 la ’, math.sqrt(y)) print(’Can bac hai cua 30.5 la ’, math.sqrt(z))

Ví dụ 4.3.11. Tính căn bậc hai của một số.

1 2 3

Can bac hai cua 20 la 4.47213595499958 Can bac hai cua 9 la 3.0 Can bac hai cua 30.5 la 5.522680508593631

Kết quả thực hiện:

5) Hàm math.expm1(): Trả về lũy thừa bậc e của bất kỳ số nào trừ đi 1. e là cơ sở của logarit tự nhiên.

1 2 3 4

import math number = 2 print(’So da cho (x) la :’, number) print(’e^x la:’, math.expm1(number))

Ví dụ 4.3.12. Tính thừa bậc e của một số.

1 2

So da cho (x) la : 2 e^x la: 6.38905609893065

Kết quả thực hiện:

Chương 4. Lập trình hướng đối tượng với Python 212

4.3.4 Module OS trong Python

Module os trong Python cung cấp các chức năng được sử dụng để tương tác với hệ điều hành và cũng có được thông tin liên quan về nó. Module os đi theo các tiện ích tiêu chuẩn của Python cung cấp một cách linh động sử dụng chức năng phụ thuộc vào hệ điều hành. Module os trong python cho phép chúng ta làm việc với các tập tin và thư mục. Các hàm trong module os được đưa ra dưới đây: 1) Hàm os.name: Cung cấp tên của module os được import. Hiện tại, nó đăng ký ’posix’, ’nt’, ’os2’, ’ce’, ’java’ và ’riscos’.

1 2

import os print(os.name)

Ví dụ 4.3.13. Cung cấp tên của module os được import.

Kết quả thực hiện: nt

2) Hàm os.getcwd(): Trả về thư mục làm việc hiện tại (CWD) của tệp.

1 2

import os print(os.getcwd())

Ví dụ 4.3.14. Trả về thư mục làm việc hiện tại (CWD) của tệp.

Kết quả thực hiện: C:\Python39\workspace\src\main

3) Hàm os.error: Xác định các lỗi cấp độ hệ điều hành. Trả về lỗi OSError trong trường hợp tên và đường dẫn file không hợp lệ hoặc không thể truy cập,...

import os try:

# Neu file khong ton tai. No se nem ra mot loi IOError filename = ’Python.txt’ f = open(filename, ’rU’) text = f.read() f.close()

# Neu co loi xay ra cau lenh ben trong IOError.duoc thuc thi except IOError:

1 2 3 4 5 6 7 8 9 10 11 12

# print(os.error) will print(’Problem reading: ’ + filename)

Ví dụ 4.3.15. Xác định các lỗi cấp độ hệ điều hành.

Kết quả thực hiện: Problem reading: Python.txt

4) Hàm os.popen(): Mở một tệp đến hoặc từ lệnh được chỉ định và nó trả về một đối tượng tệp được kết nối với một pipe.

Ví dụ 4.3.16. Mở một tệp.

import os fd = "python.txt"

# popen() la tuong duong voi open() file = open(fd, ’w’) file.write("Phat trien dung dung voi Python!") file.close() file = open(fd, ’r’) text = file.read() print(text)

1 2 3 4 5 6 7 8 9 10 11 12 13 14

# popen() cung cap cong ket noi va truy cap file truc tiep file = os.popen(fd, ’w’) file.write("Phat trien dung dung voi Python!")

4.3 Thao tác trên các module có sẵn (built-in) trong Python 213

Kết quả thực hiện: Phat trien dung dung voi Python!

5) Hàm os.close(): Dùng để đóng file.

1 2 3 4 5 6

import os fr = "Python1.txt" file = open(fr, ’r’) text = file.read() print(text) os.close(file)

Ví dụ 4.3.17. Đóng một file.

1 2 3

Traceback (most recent call last): File "C:\Python39\workspace\src\main\test.py", line 8, in file=open(fr,’r’) FileNotFoundError: [Errno 2] No such file or directory: ’Python1.txt’

Kết quả thực hiện:

6) Hàm os.rename: Một tệp hoặc thư mục có thể được đổi tên bằng cách sử dụng hàm os.rename(). Người dùng có thể đổi tên tệp nếu nó có đặc quyền thay đổi tệp.

1 2 3

import os fd = "python.txt" os.rename(fd,’Python1.txt’)

Ví dụ 4.3.18. Đổi tên một file.

1 2 3 4

Traceback (most recent call last): File"C:\Python39\workspace\src\main\test.py",line 9,in os.rename(fd,’Python1.txt’) FileNotFoundError: [WinError 2] The system cannot find the file specified: ’python.txt’ -> ’Python1.txt’

Kết quả thực hiện:

7) Hàm os.access(): Hàm này sử dụng uid/gid thực để kiểm tra xem người dùng có quyền truy cập vào đường dẫn hay không.

Chương 4. Lập trình hướng đối tượng với Python 214

import os import sys

path1 = os.access("Python.txt", os.F_OK) print("File ton tai:", path1)

# Checking access with os.R_OK path2 = os.access("Python.txt", os.R_OK) print("Co quyen doc file:", path2)

# Checking access with os.W_OK path3 = os.access("Python.txt", os.W_OK) print("Co quyen ghi file:", path3)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

# Checking access with os.X_OK path4 = os.access("Python.txt", os.X_OK) print("Kiem tra xem duoc file co duoc thuc thi:", path4)

Ví dụ 4.3.19. Đổi tên một file.

1 2 3 4

File ton tai: False Co quyen doc file: False Co quyen ghi file: False Kiem tra xem duoc file co duoc thuc thi: False

Kết quả thực hiện:

4.3.5 Module Random trong Python

Module random trong Python chứa các hàm tạo số nguyên ngẫu nhiên, tạo ra số thực (float) giữa 0.0 và 1.0. Có nhiều hàm khác nhau được định nghĩa và sử dụng trong mdule random như trong Bảng 4.4.

Bảng 4.6: Các hàm thông dụng trong module random

Tên hàm

Mô tả

random.random() random.randint() random.randrange()

Tạo ra một số float ngẫu nhiên trong khoảng từ 0.0 đến 1.0. Trả về một số nguyên ngẫu nhiên giữa các số nguyên được chỉ định. Trả về một phần tử được chọn ngẫu nhiên từ phạm vi được tạo bởi các đối số start, stop và step. Giá trị bắt đầu là 0 theo mặc định. Trả về một phần tử được chọn ngẫu nhiên từ một chuỗi không trống. Sắp xếp lại ngẫu nhiên các thành phần trong danh sách.

random.choice() random.shuffle()

1 2

import randomprint random.random() print (random.randint(8,16))

Ví dụ 4.3.20. Tạo số ngẫu nhiên giữa 8 và 16.

4.3 Thao tác trên các module có sẵn (built-in) trong Python 215

4.3.6 Module Statistics trong Python

Module thống kê (statistics) trong Python cung cấp các hàm để thống kê toán học của dữ liệu số. Có một số hàm thống kê phổ biến được định nghĩa trong module này gồm: 1) Hàm statistics.mean(): Tính giá trị trung bình số học của các số trong danh sách.

1 2 3 4 5 6

import statistics # danh sach so nguyen duong datasets = [1, 2, 7, 4, 2, 6, 8, 10] x = statistics.mean(datasets) # In gia tri trung binh cua danh sach print("Gia tri trung binh cua datasets la:", x)

Ví dụ 4.3.21. Tính trung bình số học của các số trong danh sách.

Kết quả thực hiện là: Gia tri trung binh cua datasets la: 5

2) Hàm statistics.median(): Trả về giá trị giữa của dữ liệu số trong danh sách.

1 2 3

import statistics datasets = [4, -5, 6] print("Gia tri median cua datasets la :%s " % (statistics.median(datasets)))

Ví dụ 4.3.22. Tính trung bình số học của các số trong danh sách.

Kết quả thực hiện là: Gia tri median cua datasets la : 4

3) Hàm statistics.mode(): Trả về phần tử xuất hiện nhiều lần nhất trong danh sách.

1 2 3

import statistics dataset =[2, 4, 7, 7, 2, 2, 3, 6, 6, 8] print("Phan tu xuat hien nhieu nhat la: %s" %(statistics.mode(dataset)))

Ví dụ 4.3.23. Tìm phần tử xuất hiện nhiều nhất trong danh sách.

Kết quả thực hiện là: Phan tu xuat hien nhieu nhat la 2

4) Hàm statistics.stdev(): Tính độ lệch chuẩn trên một mẫu nhất định có sẵn ở dạng danh sách.

1 2 3

import statistics sample = [7, 8, 9, 10, 11] print("Do lech chuan cua dataset la: %s " %(statistics.stdev(sample)))

Ví dụ 4.3.24. Tính độ lệch chuẩn của danh sách.

Kết quả thực hiện là: Do lech chuan cua dataset la: 1.5811388300841898

5) Hàm statistics.median_low(): Trả về giá trị trung bình thấp của dữ liệu số trong danh sách.

Ví dụ 4.3.25. Tính trung bình thấp trong danh sách.

1 2 3

import statistics set1 = [4, 6, 2, 5, 7, 7] print("Gia tri trung binh thap cua dataset la: %s "%(statistics.median_low(set1)))

Chương 4. Lập trình hướng đối tượng với Python 216

Kết quả thực hiện là: Gia tri trung binh thap cua dataset la: 5

6) Hàm statistics.median_high(): Trả về giá trị trung bình cao của dữ liệu số trong danh sách.

1 2 3 4

import statistics # list of set of the integers dataset = [2, 1, 7, 6, 1, 9] print("Gia tri trung binh cao cua dataset la: %s " %(statistics.median_high(dataset)))

Ví dụ 4.3.26. Tính trung bình cao trong danh sách.

Kết quả thực hiện là: Gia tri trung binh cao cua dataset la: 6

4.3.7 Module Sys trong Python

Module sys trong Python cung cấp các hàm và các biến được sử dụng để thao tác các phần khác nhau của môi trường chạy Python. Module này cho phép chúng ta truy cập các tham số và chức năng cụ thể của hệ thống. Bảng 4.5 liệt kê các hàm phổ biến trong module sys.

Bảng 4.7: Các hàm thông dụng trong module sys

Tên hàm

Mô tả

sys.modules sys.argv

sys.base_exec_prefix

sys.base_prefix sys.byteorder sys.maxsize sys.path

sys.stdin

sys.getrefcount sys.exit

sys.executable

Trả về tên của các Module python hiện có đã import. Trả về danh sách đối số dòng lệnh được truyền cho tập lệnh Python. Tên của tập lệnh là mục ở chỉ số 0 và phần còn lại của các đối số được lưu trữ tại các chỉ mục tiếp theo. Hàm này cung cấp một cách hiệu quả cho cùng giá trị như exec_prefix. Nếu không chạy môi trường ảo, giá trị sẽ giữ nguyên. Thiết lập khi khởi động Python trước khi site.py chạy, có cùng giá trị với tiền tố. Trả về dấu hiệu của byteorder gốc cung cấp một cách hiệu quả để làm một cái gì đó. Trả về số nguyên lớn nhất của một biến. Hiển thị bộ PYTHONPATH trong hệ thống hiện tại. Đây là một biến môi trường là một đường dẫn tìm kiếm cho tất cả các Module python. Trả về đối tượng chứa các giá trị gốc của stdin khi bắt đầu chương trình và được sử dụng trong quá trình hoàn thiện. Nó có thể khôi phục các tập tin. Trả về số tham chiếu của một đối tượng. Sử dụng để thoát khỏi console trong Python hoặc dấu nhắc lệnh hay thoát khỏi chương trình trong trường hợp ngoại lệ. Trả về đường dẫn tuyệt đối đến trình thông dịch Python. Nó rất hữu ích để biết nơi python được cài đặt trên máy của người khác. Giá trị của hàm này được sử dụng để xác định nền tảng mà chúng ta đang làm việc.

sys.platform

4.4 Thao tác trên Package trong Python

Về cơ bản, package là một tập hợp các module, sub-package,. . . tương tự nhau. Đó là một cấu trúc có thứ bậc của thư mục và file. Phương pháp quản lý các module theo package, giúp việc xây dựng cấu trúc của ứng dụng Python trở nên đơn giản hơn rất nhiều.

4.4 Thao tác trên Package trong Python 217

Trong mục 4.3, chúng ta đã biết cách tạo một module đơn giản trong Python và module nằm cùng cấp thư mục với file chính của chương trình. Giả sử trường hợp người lập trình tạo ra 100 modules thì phải tạo ra 100 files khiến việc quản lý các module sẽ rất phức tạp. Để đơn giản hóa thì trong Python có thêm khái niệm package.

4.4.1 Khái niệm package

Package là cách tạo ra các gói, mỗi gói sẽ chứa những module liên quan với nhau. Phương pháp này giúp phân chia các module trong Python dễ dàng. Có thể hiểu một package giống như folder trong máy tính, bên trong folder này có thể chứa một folder khác (tức là package khác) hay thêm những file khác (tức là các module).

Ví dụ 4.4.1. Cấu trúc của package Game

Bên trong Game có thêm 3 package con là Sound, Image, Level. Bên trong ba package con này chứa các module có liên quan với nhau. Điều đặc biệt là mỗi package bắt buộc phải có file __init__.py, đây là file được gọi đầu tiên mỗi khi người tập trình import package nó vào chương trình. Nếu chúng ta đã học lập trình hướng đối tượng thì file này giống như hàm khởi tạo của một lớp.

4.4.2 Tạo một package trong Python

Giả sử, chúng ta cần tạo package có tên là Store, đầu tiên ta sẽ tạo một folder Store và một file file __init__.py sau đó viết code trong file này như sau:

Hình 4.10: Tạo một package trong Python

Chương 4. Lập trình hướng đối tượng với Python 218

1

print("Ban da load package Store")

Ví dụ 4.4.2. Tạo file file __init__.py trong thư mục: Store/__init__.py

1

import Store

Để gọi đến package này trong file helloworld.py, ta sử dụng lệnh sau:

Như vậy đoạn code trong file __init__.py đã tự động được gọi.

4.4.3 Tạo module trong package

Để tạo một module nằm trong một package A, chúng ta cần tạo file module_name.py nằm trong thư mục package A. Giả sử, cần tạo module computer.py nằm trong package Store thì cấu trúc sẽ như sau:

def showComputerMsg(msg):

print(msg)

1 2

Ví dụ 4.4.3. Tạo một hàm trong package computer như sau:

import Store.computer Store.computer.showComputerMsg(’May tinh cua Freetuts.net’)

1 2

- Bây giờ để sử dụng package computer trong file helloworld.py thì ta sử dụng lệnh import như sau:

from Store import computer computer.showComputerMsg(’May tinh cua Freetuts.net’)

1 2

- Hoặc sử dụng lệnh from ... import như sau:

4.4.4 Tạo package bên trong một package khác

packageA

__init__.py packageB

1 2 3

Package trong Python có thể tạo chồng lên nhau. Ví dụ trong package A người lập trình muốn chia thành 2 package nhỏ là B và C thì hoàn toàn được, bằng cách sử dụng cấu trúc sub folder như phần trên. Điều lưu ý duy nhất là mỗi package bắt buộc phải có file __init__.py.

__init__.py

packageC

__init__.py

4 5 6

4.4 Thao tác trên Package trong Python 219

Để truy xuất đến các package này, chúng ta chỉ cần sử dụng dấu chấm để nối giữa các package.

Store

__init__.py Computer

__init__.py Ram

__init__.py raminfor.py

1 2 3 4 5 6 7

Ví dụ 4.4.4. Tạo package bên trong một package khác. - Giả sử chúng ta có cấu trúc package như sau trong một ứng dụng Python.

1

import Store.Computer.Ram.raminfor

- Lúc này để gọi đến module raminfor thì ta sử dụng cú pháp sau:

Tóm lại, các bước để tạo và import một package như sau: • Bước 1: Tạo một thư mục. • Bước 2: Đặt các module khác nhau bên trong thư mục vừa tạo. Chúng ta đặt ba module là msg1.py, msg2.py, và msg3.py và đặt tương ứng code trên vào các module tương ứng. Chúng ta đặt hàm msg1() trong msg1.py, hàm msg2() trong msg2.py và hàm msg3() trong msg3.py.

• Bước 3: Tạo một __init__.py file để xác định các thuộc tính trong mỗi Module. • Bước 4: Cuối cùng chúng ta import package này và sử dụng các thuộc tính đó bởi sử dụng package.

import os os.mkdir("Info")

1 2

Ví dụ 4.4.5. Sử dụng package trong Python. - Tạo thư mục Info.

def msg1():

print "Day la msg1"

1 2

def msg2():

print "Day la msg2"

1 2

def msg3():

print "Day la msg3"

1 2

- Đặt các module khác nhau trong package: msg1.py, msg2.py, msg3.py.

- Tạo một __init__.py file.

from msg1 import msg1 from msg2 import msg2 from msg3 import msg3

1 2 3

Chương 4. Lập trình hướng đối tượng với Python 220

1 2 3 4

import Info Info.msg1() Info.msg2() Info.msg3()

- Import package này và sử dụng các thuộc tính.

1 2 3

Day la msg1 Day la msg2 Day la msg3

Kết quả là:

4.5 Câu hỏi và bài tập

4.5.1 Câu hỏi

1. Lập trình hướng đối tượng (OOP) là gì và tại sao nó quan trọng trong Python? 2. Trình bày các khái niệm cơ bản về đối tượng (object) trong Python là gì? 3. Trình bày định nghĩa lớp (class) trong Python và cách tạo một đối tượng từ lớp đó. 4. Phương thức và thuộc tính là gì trong ngữ cảnh của lập trình hướng đối tượng? 5. Phân biệt khác biệt nhau giữa lớp (class) và đối tượng (object). 6. Trình bày cách khởi tạo một đối tượng và tại sao phương thức __init__ quan trọng? 7. Giải thích khái niệm kế thừa (inheritance) và cách nó hoạt động trong Python. 8. Sự khác biệt giữa lớp cha (parent class) và lớp con (child class) trong kế thừa. 9. Trình bày cách sử dụng từ khóa super() để gọi phương thức của lớp cha từ lớp con. 10. Tại sao sử dụng tính đa hình (polymorphism) trong Python và cách thực hiện nó. 11. Tại sao đóng gói (encapsulation) lại quan trọng trong lập trình hướng đối tượng? 12. Trình bày cách sử dụng thuộc tính và phương thức riêng tư (private) trong Python 13. Từ khóa self trong Python đại diện cho cái gì và tại sao nó cần thiết? 14. Làm thế nào để xác định kiểu của một đối tượng trong Python? 15. Trình bày cách sử dụng phương thức tĩnh (static method) trong Python và khi nào nên sử dụng chúng.

16. Sự khác biệt giữa phương thức tĩnh và phương thức thường (instance method). 17. Tại sao Python không hỗ trợ việc định nghĩa thuộc tính trong lớp con mà không cần định nghĩa trong lớp cha (việc này có thể gây lỗi)?

18. Trình bày cách sử dụng tính trừu tượng (abstract) trong Python. 19. Sự khác biệt giữa lớp trừu tượng (abstract class) và lớp thông thường. 20. Lý do khi nào và tại sao nên sử dụng tính đóng gói, kế thừa và đa hình trong lập trình hướng đối tượng trong Python.

4.5 Câu hỏi và bài tập 221

21. Trình bày cách sử dụng tính đóng gói (encapsulation) trong Python và tại sao nó quan trọng.

22. Làm thế nào để xác định kiểu của một đối tượng trong Python? 23. Trình bày cách sử dụng tính đóng gói (encapsulation) trong Python. 24. Làm thế nào để xác định kiểu của một đối tượng trong Python? 25. Giải thích khái niệm kế thừa đa cấp (multiple inheritance) trong Python và cách nó hoạt động.

26. Trình bày cách sử dụng tính trừu tượng (abstract) trong Python và tại sao nó quan trọng. 27. Sự khác biệt giữa lớp trừu tượng (abstract class) và lớp thông thường. 28. Giải thích tại sao nên sử dụng tính đóng gói (encapsulation) trong lập trình hướng đối tượng?

29. Giải thích tại sao nên sử dụng tính kế thừa (inheritance) trong lập trình hướng đối tượng? 30. Giải thích tại sao nên sử dụng tính đa hình (polymorphism) trong lập trình hướng đối tượng?

4.5.2 Câu hỏi trắc nghiệm

1. Lập trình hướng đối tượng (OOP) là gì?

(c) Một trình biên dịch. (d) Một dự án mã nguồn mở. (a) Một ngôn ngữ lập trình. (b) Một phương pháp lập trình. 2. Trong Python, đối tượng (object) là gì?

(a) Biến chỉ lưu trữ dữ liệu (b) Một thực thể có thuộc tính và phương thức (c) Một biến số (d) Một toán tử 3. Để tạo một lớp (class) mới trong Python, chúng ta sử dụng từ khóa nào? (a) def (b) class (c) object (d) instance 4. Thuộc tính của một đối tượng được định nghĩa bằng cách nào trong một lớp Python?

(a) Sử dụng hàm def. (b) Sử dụng từ khóa attribute. (c) Trong constructor (init). (d) Bằng cách gán giá trị cho biến global.

5. Trong Python, để tạo một đối tượng từ một lớp, chúng ta sử dụng gì? (b) Phương thức. (c) Lớp con. (a) Hàm. (d) Toán tử. 6. Trong kế thừa lớp, lớp con kế thừa các thuộc tính và phương thức từ lớp cha?

(a) Đối tượng của lớp con cũng là đối tượng của lớp cha. (b) Đối tượng của Lớp cha là đối tượng của lớp con. (c) Đối tượng của lớp con không là đối tượng của lớp cha. (d) Đối tượng lớp con và đối tượng lớp cha là hoàn toàn khác nhau. 7. Trong Python, để ghi đè (override) một phương thức từ lớp cha trong lớp con, chúng ta sử dụng từ khóa nào?

Chương 4. Lập trình hướng đối tượng với Python 222

(a) override (c) super (d) override (b) extends 8. Đối tượng self trong phương thức của lớp đại diện cho gì?

(a) Lớp cha. (b) Lớp con. (c) Đối tượng hiện tại. (d) Lớp cha và lớp con. 9. Khi một đối tượng được tạo từ một lớp, phương thức init được gọi tự động. Đây là ví

dụ về gì trong Python? (a) Hủy đối tượng (b) Phương thức tĩnh (c) Constructor (d) Destructor 10. Hàm đặc biệt __init__() trong lớp dùng để:

(a) Tạo phương thức tĩnh (b) Xoá đối tượng (c) Khởi tạo đối tượng (d) Gọi lại lớp cha 11. Trong định nghĩa lớp, self đại diện cho:

(a) Lớp hiện tại (b) Đối tượng hiện tại (c) Một module (d) Một biến toàn cục 12. Trong Python, từ khóa nào được sử dụng để khai báo một lớp con? (a) subclass (b) extends (c) class (d) child 13. Trong lập trình hướng đối tượng, tính kế thừa (inheritance) cho phép làm gì?

(a) Tạo nhiều đối tượng từ một lớp. (b) Chia sẻ mã nguồn giữa các lớp. (c) Tạo ra đối tượng cha. (d) Loại bỏ lớp cha. 14. Trong Python, từ khóa nào được sử dụng để truy cập các thuộc tính và phương thức của lớp cha trong lớp con? (a) super() (b) parent() (c) self() (d) base() 15. Trong Python, một biến thuộc tính (attribute) của một đối tượng được truy cập như thế nào?

(a) Biến.bien_thuoc_tinh (b) bien_thuoc_tinh.Biến (c) Biến->bien_thuoc_tinh (d) bien_thuoc_tinh(Biến) 16. Trong Python, để xác định kiểu của một đối tượng, chúng ta có thể sử dụng hàm nào?

(a) typeof() (b) type() (c) typeof_object() (d) object_type() 17. Trong Python, để xóa một thuộc tính của đối tượng, chúng ta sử dụng phương thức nào? (a) delattr() (c) delete() (d) discard() (b) remove() 18. Đâu là cú pháp đúng để tạo một lớp Student kế thừa từ lớp Person?

(a) class Student inherit Person: (b) class Student(Person): (c) class Student->Person: (d) class Student.Person: 19. Đâu là cách tạo một đối tượng từ lớp Animal?

(a) Animal = new() (b) object = Animal[] (c) a = Animal() (d) Animal.create() 20. Phương thức nào được gọi khi đối tượng bị xóa?

4.5 Câu hỏi và bài tập 223

(a) __create__() (b) __start__() (c) __destroy__() (d) __del__() 21. Thuộc tính lớp (class attribute) khác với thuộc tính đối tượng ở chỗ:

(a) Chỉ truy cập được bên ngoài lớp (b) Dùng chung giữa các đối tượng (c) Tồn tại tạm thời (d) Chỉ dành cho kế thừa 22. Từ khóa super() dùng để:

(a) Tạo lớp cha (b) Truy cập biến toàn cục (c) Gọi phương thức của lớp cha (d) Gọi lại đối tượng trước đó 23. Trong lập trình hướng đối tượng, tính đóng gói (encapsulation) cho phép làm gì?

(a) Bao gồm nhiều lớp con trong một lớp cha (b) Ẩn thông tin chi tiết của lớp (c) Kết hợp nhiều đối tượng thành một đối tượng lớn (d) Tạo ra các đối tượng con từ một lớp cha 24. Trong Python, từ khóa nào được sử dụng để bắt đầu một phương thức tĩnh?

(a) staticmethod (b) method (c) static (d) @staticmethod 25. Trong Python, để tạo một đối tượng lớp con và gọi một phương thức của lớp cha, chúng ta sử dụng từ khóa nào? (a) super() (b) child() (c) base() (d) parent() 26. Trong Python, từ khóa nào được sử dụng để kiểm tra xem một đối tượng có thuộc tính hay không? (a) hasattr() (b) contains() (c) property() (d) isattr() 27. Trong Python, đối tượng self trong một phương thức của lớp đại diện cho cái gì?

(a) Tên của đối tượng. (b) Lớp cha. (c) Lớp con. (d) Đối tượng hiện tại. 28. Trong Python, từ khóa nào được sử dụng để đánh dấu một lớp cha là một lớp trừu tượng (abstract)?

(c) abstractclass (d) abstractclass() (a) abstract (b) abstractmethod 29. Trong Python, một lớp trừu tượng (abstract class) có thể được khởi tạo để tạo đối tượng?

(a) Đúng (b) Sai (c) Không thực hiện được. (d) Không cho phép. 30. Trong Python, từ khóa nào được sử dụng để tạo một lớp trừu tượng?

(c) abstractclass (d) abstractclass() (a) abstract (b) abstractmethod 31. Trong Python, lớp nào được sử dụng để đóng gói dữ liệu và phương thức liên quan vào một đối tượng duy nhất?

Chương 4. Lập trình hướng đối tượng với Python 224

(a) Singleton (b) Container (c) Object (d) Namespace 32. Trong Python, một lớp con có thể kế thừa từ nhiều lớp cha?

(a) Đúng (b) Sai (c) Không thực hiện được. (d) Không cho phép. 33. Trong một lớp, nếu muốn phương thức sử dụng được mà không cần đối tượng, ta dùng:

(a) Hàm toàn cục (b) @staticmethod (c) __self__ (d) def() 34. Trong Python, từ khóa nào được sử dụng để gọi phương thức của lớp cha từ lớp con? (a) superclass (b) baseclass (c) parent (d) super()

35. Trong Python, để truy cập một phương thức tĩnh của lớp, chúng ta sử dụng từ khóa nào? (d) @staticmethod (c) method (a) static (b) self

36. Trong Python, lớp nào được sử dụng để định nghĩa một giao diện (interface)? (d) Class (a) Interface (b) Abstract (c) Protocol 37. Trong Python, từ khóa nào được sử dụng để xác định một phương thức là một phương thức lớp (class method)? (a) method (b) @classmethod (c) static (d) self 38. Từ khóa nào được sử dụng để truy cập phương thức của lớp từ bên trong lớp? (a) inner (b) self (c) cls (d) staticmethod

39. Trong Python, lớp nào được sử dụng để tạo một đối tượng đơn lẻ (singleton)? (d) Class (c) Namespace (a) Singleton (b) Object 40. Để kiểm tra xem một đối tượng là thể hiện của một lớp nào đó, dùng: (a) type() (b) match() (c) check() (d) isinstance() 41. Trong Python, từ khóa nào được sử dụng để truy cập thuộc tính của lớp từ bên trong lớp? (a) static (b) self (c) cls (d) @property 42. Trong Python, phương thức nào được tự động gọi khi một đối tượng bị hủy? (a) del() (b) delete() (c) distroy() (d) deleted() 43. Trong Python, từ khóa nào được sử dụng để kiểm tra xem một đối tượng có thuộc tính

cụ thể hay không? (a) hasattr() (b) property() (c) contains() (d) getattribute() 44. Trong Python, lớp nào được sử dụng để định nghĩa một lớp con không thể thay đổi (immutable)? (a) Immutable (b) Frozen (c) Final (d) Constant 45. Trong Python, để thực hiện đa hình (polymorphism), chúng ta sử dụng gì? (a) Kế thừa (c) Tính kế thừa (b) Ghi đè (d) Tính đóng gói 46. Trong Python, từ khóa nào được sử dụng để thực hiện kế thừa một phương thức từ lớp cha mà không cần thay đổi nó?

4.5 Câu hỏi và bài tập 225

(a) override (b) super (c) pass (d) @staticmethod 47. Trong Python, để truy cập thuộc tính của lớp từ bên ngoài lớp cần sử dụng từ khóa nào? (a) access (b) public (c) private (d) @property 48. Trong Python, lớp nào được sử dụng để tạo một đối tượng không thể thay đổi (immutable) có thể sử dụng như một key trong một dictionary? (a) Immutable (b) Hashable (c) Constant (d) Frozen 49. Để nạp thêm một file .py như một module, ta dùng: (a) import (b) include (c) extend (d) load 50. Khi nhập module với import module as m, m gọi là:

(a) Tên lớp (b) Biến cục bộ (c) Tên alias (bí danh) (d) Tên phương thức

4.5.3 Bài tập thực hành

1. Định nghĩa lớp Dog với thuộc tính name và phương thức bark(). Tạo một đối tượng dog1 từ lớp Dog và gọi phương thức bark() để in ra thông báo "Woof!". 2. Mở rộng lớp Dog ở câu 1 bằng cách thêm thuộc tính age và phương thức get_age() để trả về tuổi của con chó. Tạo một đối tượng dog2 và hiển thị tuổi của nó. 3. Định nghĩa lớp Rectangle với thuộc tính width và height, phương thức calculate_area() để tính diện tích hình chữ nhật. Tạo một đối tượng rect và tính diện tích của nó. 4. Mở rộng lớp Rectangle ở câu 3 bằng cách thêm phương thức calculate_perimeter() để tính chu vi của hình chữ nhật. Tạo một đối tượng rect và tính chu vi của nó. 5. Định nghĩa lớp Circle với thuộc tính radius và phương thức calculate_area() để tính diện tích hình tròn. Tạo một đối tượng circle và tính diện tích của nó. 6. Mở rộng lớp Circle ở câu 5 bằng cách thêm phương thức calculate_circumference() để tính chu vi của hình tròn. Tạo một đối tượng circle và tính chu vi của nó. 7. Định nghĩa lớp Student với thuộc tính name và age. Tạo một đối tượng student1 từ lớp Student và hiển thị thông tin về sinh viên.

8. Mở rộng lớp Student ở câu 7 bằng cách thêm thuộc tính grade và phương thức get_grade() để trả về điểm của học sinh. Tạo một đối tượng student2 và hiển thị điểm của học sinh.

9. Định nghĩa lớp BankAccount với thuộc tính balance và phương thức deposit() và withdraw() để thực hiện giao dịch nạp tiền và rút tiền. Tạo một đối tượng account và thực hiện một số giao dịch để kiểm tra số dư. 10. Mở rộng lớp BankAccount ở câu 9 bằng cách thêm phương thức get_balance() để trả về số dư của tài khoản. Tạo một đối tượng account và hiển thị số dư của nó. 11. Định nghĩa lớp Employee với thuộc tính name và salary. Tạo một đối tượng employee1 từ lớp Employee và hiển thị thông tin về nhân viên.

12. Mở rộng lớp Employee ở câu 11 bằng cách thêm phương thức apply_raise() để tăng lương của nhân viên. Tạo một đối tượng employee2 và tăng lương của nhân viên này.

Chương 4. Lập trình hướng đối tượng với Python 226

13. Định nghĩa lớp Car với thuộc tính make, model và year. Tạo một đối tượng car1 từ lớp Car và hiển thị thông tin về xe. 14. Mở rộng lớp Car ở câu 13 bằng cách thêm phương thức start() để bắt đầu xe. Tạo một đối tượng car2 và bắt đầu xe này. 15. Định nghĩa lớp Person với thuộc tính name, age và address. Tạo một đối tượng person1 từ lớp Person và hiển thị thông tin về người.

16. Mở rộng lớp Person ở câu 15 bằng cách thêm phương thức change_address() để thay đổi địa chỉ của người. Tạo một đối tượng person2, thay đổi địa chỉ của người này và hiển thị thông tin mới. 17. Định nghĩa lớp Book với thuộc tính title, author, và year_published. Tạo một đối tượng book1 từ lớp Book và hiển thị thông tin về sách.

18. Mở rộng lớp Book ở câu 17 bằng cách thêm phương thức is_published() để kiểm tra xem sách đã được xuất bản hay chưa. Tạo một đối tượng book2, kiểm tra xem sách này đã được xuất bản hay chưa và hiển thị kết quả.

19. Định nghĩa lớp Computer với thuộc tính brand và model, và phương thức turn_on() để bật máy tính. Tạo một đối tượng computer1 từ lớp Computer và bật máy tính này. 20. Mở rộng lớp Computer ở câu 19 bằng cách thêm phương thức turn_off() để tắt máy tính. Tạo một đối tượng computer2 và thử bật/tắt máy tính. 21. Định nghĩa lớp Product với thuộc tính name, price và quantity. Tạo một đối tượng product1 từ lớp Product và hiển thị thông tin về sản phẩm.

22. Mở rộng lớp Product ở câu 21 bằng cách thêm phương thức calculate_total() để tính tổng giá trị của sản phẩm (price * quantity). Tạo một đối tượng product2 và tính tổng giá trị của sản phẩm này.

23. Định nghĩa lớp Shape với phương thức trừu tượng calculate_area() để tính diện tích của các hình khác nhau. Tạo hai lớp con Circle và Rectangle kế thừa từ lớp Shape và định nghĩa phương thức calculate_area() trong mỗi lớp con để tính diện tích cho hình tròn và hình chữ nhật. Tạo một đối tượng circle và rectangle và tính diện tích của chúng.

24. Định nghĩa lớp Animal với phương thức trừu tượng speak() để mô phỏng âm thanh mỗi loài động vật phát ra. Tạo hai lớp con Dog và Cat kế thừa từ lớp Animal và định nghĩa phương thức speak() trong mỗi lớp con để in ra tiếng sủa cho chó và tiếng meo cho mèo. Tạo một đối tượng dog và cat và gọi phương thức speak() của chúng. 25. Định nghĩa lớp Shape với phương thức trừu tượng calculate_area() để tính diện tích của các hình khác nhau. Tạo hai lớp con Circle và Rectangle kế thừa từ lớp Shape và định nghĩa phương thức calculate_area() trong mỗi lớp con để tính diện tích cho hình tròn và hình chữ nhật. Tạo một danh sách chứa các đối tượng Circle và Rectangle, sau đó lặp qua danh sách và tính tổng diện tích của tất cả các hình. 26. Định nghĩa lớp Person với thuộc tính name, age và gender. Tạo hai lớp con Student và Teacher kế thừa từ lớp Person và thêm thuộc tính student_id cho lớp Student

4.5 Câu hỏi và bài tập 227

và employee_id cho lớp Teacher. Tạo một đối tượng student và teacher và hiển thị thông tin về họ. 27. Định nghĩa lớp Time gồm giờ, phút, giây. Thêm phương thức chuẩn hóa giờ (nếu giây > 60 thì chuyển phút, tương tự cho giờ).

28. Định nghĩa lớp Employee với thuộc tính name, salary và employment_year. Tạo hai lớp con Manager và Developer kế thừa từ lớp Employee và thêm thuộc tính bonus cho Manager và programming_language cho Developer. Định nghĩa phương thức calculate_bonus() cho Manager để tính tiền thưởng và phương thức print_info() cho Developer để hiển thị thông tin về nhân viên. Tạo một đối tượng manager và developer, sau đó tính tiền thưởng cho manager và hiển thị thông tin của developer. 29. Định nghĩa lớp Vehicle với thuộc tính make, model và year. Tạo hai lớp con Car và Motorcycle kế thừa từ lớp Vehicle và thêm thuộc tính engine_type cho Car và top_speed cho Motorcycle. Định nghĩa phương thức start() cho Car để khởi động xe và phương thức accelerate() cho Motorcycle để tăng tốc. Tạo một đối tượng car và motorcycle, sau đó khởi động xe và tăng tốc.

30. Định nghĩa lớp Person với thuộc tính name và age. Tạo lớp con Student kế thừa từ lớp Person và thêm thuộc tính student_id. Tạo lớp con Teacher kế thừa từ lớp Person và thêm thuộc tính employee_id. Tạo đối tượng student và teacher, sau đó hiển thị thông tin về họ.

31. Định nghĩa lớp Shape với phương thức trừu tượng calculate_area() để tính diện tích của các hình khác nhau. Tạo lớp con Circle kế thừa từ lớp Shape và định nghĩa phương thức calculate_area() để tính diện tích cho hình tròn. Tạo đối tượng circle và tính diện tích của nó.

32. Định nghĩa lớp Employee với thuộc tính name, salary, và employment_year. Tạo lớp con Manager kế thừa từ lớp Employee và thêm thuộc tính bonus. Định nghĩa phương thức calculate_bonus() cho Manager để tính tiền thưởng. Tạo đối tượng manager và tính tiền thưởng của anh ấy.

33. Định nghĩa lớp Person với thuộc tính name và age. Tạo lớp con Student kế thừa từ lớp Person và thêm thuộc tính student_id. Tạo đối tượng student và hiển thị thông tin về anh ấy.

34. Định nghĩa lớp BankAccount với thuộc tính balance. Tạo lớp con SavingsAccount kế thừa từ lớp BankAccount và thêm phương thức calculate_interest() để tính lãi suất và phương thức deposit() và withdraw() để thực hiện giao dịch nạp tiền và rút tiền. Tạo đối tượng savings_account, nạp tiền vào tài khoản và tính lãi suất. 35. Định nghĩa lớp Student có thuộc tính name, age, major. Viết phương thức hiển thị thông tin sinh viên.

36. Định nghĩa lớp Clock với phương thức set_time(h, m, s) và display_time(). 37. Tạo lớp Vehicle và lớp Car, Motorcycle kế thừa. Thêm phương thức đặc trưng cho từng lớp.

Chương 4. Lập trình hướng đối tượng với Python 228

38. Định nghĩa lớp Book với các thuộc tính: tên sách, tác giả, năm xuất bản. Thêm phương thức kiểm tra sách đã phát hành trên 10 năm hay chưa. 39. Định nghĩa lớp Temperature với phương thức chuyển đổi nhiệt độ từ độ C sang F và ngược lại.

40. Định nghĩa lớp Product để lưu thông tin sản phẩm và tính giá sau thuế (thuế cố định 10 41. Định nghĩa lớp Employee có thuộc tính tên, hệ số lương, lương cơ bản. Thêm phương thức tính tổng lương.

42. Định nghĩa lớp Fraction để biểu diễn phân số. Thêm phương thức cộng, trừ hai phân số. 43. Định nghĩa lớp Person (họ tên, tuổi), lớp Student kế thừa từ Person và bổ sung thuộc tính điểm, phương thức xếp loại học lực. 44. Định nghĩa lớp Vehicle, lớp Car kế thừa từ Vehicle, bổ sung thêm thuộc tính số chỗ ngồi, hãng xe, tốc độ tối đa. 45. Định nghĩa lớp Shape có phương thức area(), perimeter(). Tạo các lớp con Square, Circle, Triangle kế thừa và triển khai cụ thể các phương thức đó. 46. Định nghĩa lớp Animal, lớp Dog và Cat kế thừa Animal, thêm phương thức sound() để biểu diễn hành vi riêng của từng con vật. 47. Định nghĩa lớp Account, kế thừa tạo lớp SavingAccount có thêm lãi suất và phương thức tính lãi theo tháng. 48. Định nghĩa các lớp Bird, Duck, Sparrow, mỗi lớp có phương thức fly() với nội dung khác nhau để mô phỏng đa hình. 49. Định nghĩa lớp Calculator có phương thức calculate() sử dụng nhiều cách nạp chồng để tính toán tổng, tích, hoặc hiệu hai số. 50. Định nghĩa lớp Employee có thuộc tính __salary. Thêm getter/setter để đọc và thay đổi lương theo nguyên tắc đóng gói. 51. Định nghĩa lớp BankAccount bảo vệ số dư bằng cách sử dụng thuộc tính riêng tư __balance, và chỉ cho phép rút nếu đủ tiền. 52. Viết một chương trình tạo danh sách các đối tượng Shape và duyệt qua từng phần tử, gọi phương thức draw() (mô phỏng đa hình trong danh sách). 53. Viết một chương trình rách lớp Student và lớp Classroom ra 2 module riêng. Dùng chương trình chính để nhập danh sách sinh viên và tính điểm trung bình lớp. 54. Viết một module math_utils.py chứa các lớp Vector, Matrix, với các phương thức tính toán đơn giản. 55. Viết module geometry.py gồm các lớp Point, Line, Triangle. Thêm phương thức tính độ dài đoạn thẳng và chu vi tam giác. 56. Viết chương trình quản lý thư viện: module Book, Member, Library. Hỗ trợ thêm sách, mượn sách, kiểm tra sách còn trong kho. 57. Xây dựng mô hình ShopManagement gồm nhiều module: Product, Order, Customer, cho phép thêm sản phẩm, tạo đơn hàng, in hóa đơn. 58. Viết lớp Student có điểm __mark, phương thức set_mark() kiểm tra giá trị nhập hợp

4.5 Câu hỏi và bài tập 229

lệ (0–10), get_mark() để truy cập. 59. Viết chương trình mô phỏng hệ thống User (cid:25) Admin, Customer, mỗi lớp có phương thức login() khác nhau. 60. Viết lớp Account với các thuộc tính riêng tư và phương thức deposit(), withdraw() kiểm soát thao tác hợp lệ.

61. Sử dụng super() để gọi constructor lớp cha trong lớp con. 62. Tách lớp Student ra file student.py. Từ file main.py, import lớp Student và khởi tạo đối tượng. 63. Tạo một module mathutils.py chứa các hàm: is_prime(n), gcd(a, b), factorial(n) và gọi chúng từ chương trình chính. 64. Tạo module product.py định nghĩa lớp Product, viết chương trình chính nhập danh sách sản phẩm và tính tổng giá. 65. Tạo danh sách các đối tượng Bird, Fish, Dog có phương thức move(). Gọi move() trong vòng lặp để thể hiện tính đa hình. 66. Viết hàm show_info(animal) để in thông tin của bất kỳ đối tượng Animal kế thừa nào 67. Viết chương trình quản lý danh bạ: mỗi người là 1 đối tượng Contact (tên, điện thoại, email). Hỗ trợ thêm, xóa, tìm kiếm liên hệ. 68. Viết chương trình quản lý điểm sinh viên: nhập danh sách đối tượng Student, tính điểm trung bình, sắp xếp theo điểm giảm dần. 69. Viết hệ thống quản lý thư viện: lớp Book, Member, BorrowRecord. Cho phép mượn, trả sách, in danh sách sách đang mượn. 70. Viết chương trình quản lý nhân viên: Tạo lớp Employee với thông tin mã NV, họ tên, lương cơ bản. Viết phương thức tính lương thực lãnh = lương cơ bản + phụ cấp. 71. Viết chương trình quản lý học sinh: Lớp Student có mã SV, tên, điểm 3 môn. Viết phương thức tính điểm trung bình, phân loại học lực. 72. Viết chương trình tính toán hình học: Viết các lớp Rectangle, Circle, Triangle có phương thức tính chu vi, diện tích. 73. Viết chương trình quản lý sản phẩm: Lớp Product có mã, tên, giá, số lượng. Viết hàm nhập/xuất danh sách sản phẩm. 74. Viết chương trình quản lý sổ tiết kiệm: Lớp SavingAccount gồm tên người gửi, số tiền, lãi suất, kỳ hạn. Tính tổng tiền sau kỳ hạn. 75. Viết chương trình quản lý động vật: Lớp Animal có phương thức speak(). Các lớp con Cat, Dog, Bird kế thừa và override speak(). 76. Viết chương trình quản lý phương tiện: Lớp Vehicle, các lớp Car, Bus, Truck kế thừa, có phương thức move() khác nhau. 77. Viết chương trình quản lý hệ thống tính lương: Lớp cha Employee, các lớp con FullTime, PartTime, Contract tính lương theo cách riêng. 78. Viết chương trình quản lý hệ thống thi trắc nghiệm: Lớp Question, lớp con Multiple-

Chương 4. Lập trình hướng đối tượng với Python 230

Choice, TrueFalse, Essay. 79. Viết chương trình quản lý hình học nâng cao: Lớp cha Shape, các lớp con Square, Circle, Hexagon. Sử dụng tính đa hình để gọi phương thức tính diện tích. 80. Viết chương trình quản lý thư viện: Lớp Book với tiêu đề, tác giả, tình trạng mượn. Viết lớp Library quản lý danh sách sách. 81. Viết chương trình quản lý cửa hàng: Lớp Item, viết chương trình quản lý giỏ hàng gồm nhiều Item, tính tổng tiền, VAT. 82. Viết chương trình quản lý danh bạ cá nhân: Lớp Contact lưu tên, SĐT, email. Cho phép thêm, xóa, tìm kiếm liên hệ. 83. Viết chương trình lập thời khóa biểu: Lớp Schedule chứa danh sách môn học với thời gian, giảng viên. 84. Viết chương trình hệ thống quản lý sinh viên: Tạo lớp StudentManager chứa danh sách sinh viên, cho phép thêm, sửa, xóa, tìm kiếm. 85. Viết chương trình quản lý Mini hệ thống ATM: Gồm lớp Account, các chức năng: kiểm tra số dư, rút, nạp, chuyển khoản, thoát. 86. Viết chương trình quản lý học bạ điện tử: Lưu danh sách môn học, điểm, cho phép in học bạ, tính học lực, xếp loại. 87. Viết chương trình quản lý nhân sự công ty: Lớp Employee, Department, Payroll. Cho phép lọc theo phòng ban, thống kê lương. 88. Viết chương trình ứng dụng Quiz Game: Lưu câu hỏi và đáp án trong lớp, sinh ngẫu nhiên, chấm điểm người chơi. 89. Viết chương trình ứng dụng phân tích log file: Lớp LogRecord, đọc file log, phân tích IP, số lỗi, thống kê theo thời gian. 90. Viết chương trình Hệ thống quản lý khóa học trực tuyến. Yêu cầu:

• Lớp Course: mã khóa học, tên, mô tả, giảng viên, học phí. • Lớp User: cha của Student và Instructor • Lớp Enrollment: lưu thông tin học viên tham gia khóa học. • Chức năng: Đăng ký, huỷ đăng ký, liệt kê học viên theo khóa học, tính tổng doanh thu theo giảng viên.

91. Viết chương trình mô phỏng hệ thống ngân hàng liên chi nhánh. Yêu cầu:

• Lớp Bank, Branch, Customer, Account, Transaction • Chức năng: Mỗi ngân hàng có nhiều chi nhánh. Mỗi chi nhánh quản lý danh sách

khách hàng và tài khoản. Cho phép nạp tiền, rút tiền, chuyển liên chi nhánh. • Nâng cao: Ghi log giao dịch vào file, xuất báo cáo tổng hợp theo chi nhánh.

92. Viết chương trình Quản lý phòng khám – hệ thống đặt lịch và hồ sơ bệnh án. Yêu cầu:

• Lớp Doctor, Patient, Appointment, MedicalRecord, Prescription • Chức năng: Tạo lịch hẹn, lưu hồ sơ khám, chẩn đoán, đơn thuốc. Tra cứu lịch sử bệnh nhân. • Nâng cao: Giao tiếp giữa đối tượng qua ID, module hóa hồ sơ theo bệnh nhân.

4.5 Câu hỏi và bài tập 231

93. Viết chương trình Hệ thống quản lý thư viện đa cấp. Yêu cầu:

• Lớp Library, Section, Book, Borrower, Loan • Chức năng: Mỗi thư viện có nhiều khu (section), mỗi khu có danh mục sách riêng. Quản lý mượn/trả sách, tra cứu theo ISBN, thống kê lượt mượn theo tháng. • Nâng cao: Thống kê sách quá hạn, tự động gửi cảnh báo trả sách.

94. Viết chương trình mô phỏng hệ thống thương mại điện tử. Yêu cầu:

• Lớp User, Customer, Seller, Product, Order, Cart, Review • Chức năng: Người dùng có thể đăng nhập, mua hàng, quản lý đơn, viết đánh giá. Người bán quản lý tồn kho, doanh thu. • Nâng cao: Phân quyền và thống kê đơn hàng theo trạng thái.

95. Viết chương trình hệ thống kiểm tra – chấm điểm tự động. Yêu cầu:

• Lớp Question, Exam, Student, Submission • Chức năng: Cho phép tạo đề thi từ ngân hàng câu hỏi. Sinh viên nộp bài (cid:25) hệ thống tự chấm (trắc nghiệm). • Nâng cao: Sinh câu hỏi ngẫu nhiên theo chủ đề, ghi kết quả vào file JSON.

96. Viết chương trình hệ thống đánh giá chất lượng dịch vụ. Yêu cầu:

• Lớp Service, Feedback, Customer, SurveyForm, Report • Chức năng: Mỗi dịch vụ có thể nhận phản hồi từ khách. Tính điểm trung bình, thống kê đánh giá theo tiêu chí. • Nâng cao: Sinh báo cáo đánh giá tổng hợp theo tháng và lưu file .csv.

97. Viết chương trình mô phỏng mạng xã hội mini. Yêu cầu:

• Lớp User, Post, Comment, Like, Notification. • Chức năng: Người dùng có thể đăng bài, bình luận, like, nhận thông báo khi có tương tác. • Nâng cao: Quản lý theo dõi (follow/follower), khuyến nghị bạn bè.

98. Viết chương trình quản lý công việc cá nhân (To-do App OOP). Yêu cầu:

• Lớp Task, Category, User, ScheduleManager. • Chức năng: Tạo, sửa, xoá công việc, phân loại theo deadline và danh mục. • Nâng cao: Thống kê số việc theo trạng thái (chưa làm, đang làm, đã xong), xuất kế hoạch ra file Excel..

99. Thư viên X quản lý danh sách các loại sách. Thông tin về các loại sách: Sách giáo khoa gồm mã sách, ngày nhập (ngày, tháng, năm), đơn giá, số lượng, nhà xuất bản, tình trạng (mới, cũ). Nếu tình trạng sách là mới thì thành tiền = số lượng * đơn giá. Nếu tình trạng sách là cũ thì: thành tiền = số lượng * đơn giá * 50%; Sách tham khảo: Mã sách, ngày nhập (ngày, tháng, năm), đơn giá, số lượng, nhà xuất bản, thuế. Thành tiền = số lượng * đơn giá + thuế. Thực hiện các yêu cầu sau:

a) Xây dựng các lớp với chức năng thừa kế. b) Nhập xuất danh sách các loại sách. c) Tính tổng thành tiền cho từng loại.

Chương 4. Lập trình hướng đối tượng với Python 232

d) Tính trung bình cộng đơn giá của các sách tham khảo. e) Xuất ra các sách giáo khoa của nhà xuất bản X.

100. Viết chương trình quản lý khách hàng xếp hàng mua vé tại nhà ga. Thông tin lưu trữ cho khách hàng gồm: số CCCD khác hàng (String), tên khách hàng, ga đến, giá tiền (double). Hệ thống menu gồm các mục:

a) Thêm một khách hàng mới vào hàng đợi mua vé. b) Bán một vé cho khách hàng. c) Chỉ bán cho người đăng ký trước. d) Hiển thị danh sách khách hàng. e) Hủy một khách hàng ra khỏi danh sách. (khách hàng không mua vé nữa). f) Thống kê tình hình bán vé g) Lưu danh sách vào file h) Hiển thị danh sách các ga đang chờ mua vé. i) Hiển thị danh sách các ga đang chờ mua vé và số vé tương ứng cho ga.

Lưu ý: Số khách hàng trong danh sách hiện tại là số khách đang chờ, nhưng chưa có vé. Khi một khách hàng đã mua vé, thì loại khách hàng này ra khỏi danh sách chờ mua vé. Việc mua vé phải có thứ tự: ai vào trước thì mua vé trước (FIFO). Mỗi khi khách hàng mua được vé phải lưu lại khách hàng này để dùng cho việc thống kê. Mỗi khi thêm một khác hàng mới, nếu Số CMND khách hàng đã có thì không tạo phần tử mới mà chỉ cập nhật lại ga và giá tiền đến cho khác hàng đó. Mục thống kê tình hình: cho biết còn bao nhiêu khách hàng chờ nhận vé, bao nhiêu khách hàng đã nhận vé, tổng số tiền đã thu về là bao nhiêu. - Việc lưu danh sách: chỉ lưu các khách hàng chờ mua vé. Các khách hàng đã nhận vé xem như kết sổ trong ngày không cần lưu lại. Khi chương trình vừa được chạy, lập tức tự động nạp toàn bộ danh sách khách hàng từ file (cách khách hàng chưa có vé). Khi hiển thị danh sách các ga đến đang chờ mua vé, chỉ hiển thị tên ga đó một lần. (Ví dụ: giả sử 10 khách hàng nhưng đăng ký đi đến 2 ga, thì chỉ hiển thị 2 hàng).

5. Phát triển ứng dụng với Python

Mục tiêu: Kết thúc chương này, sinh viên có thể:

• Nắm vững và sử dụng thành thạo các câu lệnh thiết kế giao diện ứng dụng đơn giản với tkinter.

• Biết cách xây dựng các ứng dụng đơn giản với các thư viện đồ họa. • Hiểu được các bước xây dựng ứng dụng quản lý với Python. • Nắm vững và sử dụng thành thạo các thư viện xử lý dữ liệu và xây dựng ứng dụng. • Phát triển các ứng dụng trí tuệ nhân tạo đơn giản với Python.

5.1 Thiết kế giao diện với Tkinter

5.1.1 Giới thiệu Tkinter

Python cung cấp các tùy chọn khác nhau để phát triển giao diện người dùng đồ họa (GUI- Graphical User Interface). Quan trọng nhất được liệt kê dưới đây: • Tkinter: Tkinter là giao diện Python cho bộ công cụ Tk GUI. Chúng ta sẽ học Tkinter trong chương này.

• wxPython: Đây là một giao diện Python mã nguồn mở cho wxWindows https://wxpython.org/ • JPython: JPython là một cổng Python dành cho Java, cho phép các tập lệnh Python truy cập vào các thư viện Java trên máy cục bộ https://www.jython.org/

Chương 5. Phát triển ứng dụng với Python 234

5.1.2.1 Giới thiệu về Tkinter và tạo giao diện đầu tiên

5.1.2 Thiết kế giao diện với Tkinter

Tkinter là thư viện GUI tiêu chuẩn cho Python. Tkinter trong Python cung cấp một cách nhanh chóng và dễ dàng để tạo các ứng dụng GUI. Tkinter cung cấp giao diện hướng đối tượng cho bộ công cụ Tk GUI.

#Them thu vien tkinter

#Tao mot cua so moi

1 2 3 4 5

from tkinter import * window = Tk() window.title(’Welcome to VniTeach app’) #Them tieu de cho cua so window.geometry(’350x200’) #Dat kich thuoc cua cua so #Lap vo tan de hien thi cua so window.mainloop()

5.1.2.2 Các điều khiển giao diện với Tkinter

Dòng cuối cùng gọi hàm mainloop() là vòng lặp vô tận của cửa sổ, vì vậy cửa sổ sẽ chờ bất kỳ tương tác người dùng nào cho đến khi chúng ta đóng nó. Nếu người dùng quên gọi hàm mainloop() sẽ không có cửa sổ xuất hiện.

a) Làm việc với điều khiển Label: Là đối tượng dùng để hiển thị văn bản hoặc hình ảnh. • Cú pháp: w = Label( master, option, ... ) • Tham số:

– master: Tên của cửa sổ chứa nhãn. – options: Là danh sách một số tùy chọn thường dùng cho nhãn, tùy chọn này có thể sử dụng cặp từ khóa và giá trị (xem Bảng 5.1).

Bảng 5.1: Một số tùy chọn với điều khiển label

Tùy chọn

Giải thích ý nghĩa

anchor bg bitmap bd cursor font fg height image justify padx pady relief text textvariable underline

width wraplength

Căn lề của văn bản, mặc định anchor=CENTER, nghĩa là văn bản sẽ căn giữa. Màu nền của nhãn (label). Tùy chọn một bitmap hoặc đối tượng hình ảnh và nhãn sẽ hiển thị đồ họa đó. Quy định kích thước của đường viền (border) bao quanh nhãn, mặc định là 2 pixels. Thiết lập loại con trỏ chuột (arrow, dot,. . . ). Chỉ định loại phông chữ mà văn bản sẽ được hiển thị. Chỉ định màu của văn bản. Nếu hiển thị bitmap sẽ là màu xuất hiện tại vị trí các bit 1. Quy định độ cao của nhãn. Hiển thị ảnh tĩnh trong nhãn. Quy định nhiều dòng của văn bản sẽ canh lề LEFT, CENTER (mặc định) hoặc RIGHT. Thiết lập khoảng trống phía trước và sau (padding) của văn bản, mặc định là 1. Thiết lập khoảng trống phía trên và phía dưới (padding) của văn bản, mặc định là 1. Chỉ định sự xuất hiện của đường viền quanh nhãn, mặc định là FLAT; có nhiều giá trị khác. Hiển thị nội dung của một hoặc nhiều dòng văn bản chứa trong nhãn, (\n) để ngắt dòng. Văn bản được hiển thị thành biến điều khiển của lớp StringVar. Gạch chân chữ viết cho một số ký tự, bắt đầu đếm từ 0, có thể thiết lập n. Mặc định underline=-1, nghĩa là không gạch chân chữ viết. Quy định chiều rộng của nhãn phù hợp với số ký tự. Thiết lập số lượng ký tự cho mỗi dòng, mặc định bằng 0 nghĩa là dòng sẽ tự động ngắt (chỉ gồm có duy nhất một dòng).

b) Làm việc với Button: Nút bấm có thể hiển thị văn bản hoặc hình ảnh, chúng ta có thể

5.1 Thiết kế giao diện với Tkinter 235

thiết lập sự kiện khi chúng ta click vào nút bấm như tự động gọi hàm chẳng hạn.

• Cú pháp: w = Button( master, option = value,...) • Tham số:

– master: Tên của cửa sổ chứa nút bấm. – options: Là danh sách một số tùy chọn thường dùng cho nút bấm, tùy chọn này có thể sử dụng cặp từ khóa và giá trị (xem Bảng 5.2).

Bảng 5.2: Một số tùy chọn với điều khiển button

Tùy chọn

Giải thích ý nghĩa

underline

activebackground Màu nền của nút bấm khi con trỏ chuột ở phía trên nút bấm Màu chữ của nút bấm khi con trỏ chuột ở phía trên nút bấm activeforeground Độ rộng của đường biên của nút bấm, mặc định là 2. bd Màu nền của nút bấm. bg Hàm hoặc phương thức sẽ được gọi khi click vào nút bấm. command Màu chữ của nút bấm. fg Phông chữ của văn bản trên nút bấm. font Độ cao của nút bấm (số dòng) hoặc pixels đối với hình ảnh. height Màu nổi bật khi nút bấm có focus. highlightcolor Hình ảnh sẽ hiển thị trên nút bấm thay vì văn bản. image Quy định nhiều dòng của văn bản sẽ canh lề LEFT, CENTER (mặc định) hoặc RIGHT. justify Thiết lập khoảng trống phía trước và sau (padding) của văn bản, mặc định là 1. padx Thiết lập khoảng trống phía trên và phía dưới (padding) của văn bản, mặc định là 1. pady Xuất hiện của đường viền quanh nút bấm (SUNKEN, RAISED, GROOVE và RIDGE). relief Thiết lập thành DISABLED để chuyển sang nút bấm màu xám (bị ẩn) và không phản hồi. state Có giá trị là ACTIVE khi con trỏ chuột ở trên nút bấm. Mặc định là NORMAL. Mặc định là -1, văn bản trên nút bấm sẽ không gạch chân. Nếu không âm, ký tự văn bản tương ứng sẽ được gạch chân. Độ rộng của nút bấm là số ký tự (nếu hiển thị văn bản) hoặc pixels (nếu hiển thị hình ảnh). Thiết lập số lượng ký tự cho mỗi dòng, mặc định là 0 (dòng sẽ tự động ngắt).

width wraplength

Phương thức:

Bảng 5.3: Các phương thức với điều khiển Button

Phương thức Giải thích ý nghĩa

flash()

invoke()

Làm cho nút nhấp nháy nhiều lần giữa màu đang hoạt động và màu bình thường. Để nút ở trạng thái ban đầu. Bỏ qua nếu nút bị tắt. Gọi lệnh gọi lại của nút và trả về những gì mà hàm đó trả về. Không có tác dụng nếu nút bị tắt hoặc không có lệnh gọi lại.

1 2 3 4 5 6 7

from tkinter import * window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’) lbl = Label(window, text="Hello") lbl.grid(column=0, row=0) #Them mot nut nhan "Click Me"

Ví dụ 5.1.1. Tạo điều khiển nut "Click Me".

8 9 10 11

btn = Button(window, text="Click Me", bg="orange", fg="red") #Thiet lap vi tri cua nut nhan co mau nen va mau chu btn.grid(column=1, row=0) window.mainloop()

Chương 5. Phát triển ứng dụng với Python 236

from tkinter import * window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’) lbl = Label(window, text="Hello") lbl.grid(column=0, row=0) def clicked(): #Ham khi nut duoc nhan

lbl.configure(text="Button was clicked !!")

1 2 3 4 5 6 7 8 9 10 11 12

#Goi ham clicked khi nut duoc nhan btn = Button(window, text="Click Me", command=clicked) btn.grid(column=1, row=0) window.mainloop()

Ví dụ 5.1.2. Xử lý sự kiện khi nhấn nút Click Me.

c) Làm việc với Textbox:

from tkinter import * window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’) lbl = Label(window, text="Hello") lbl.grid(column=0, row=0) #Tao mot Textbox txt = Entry(window,width=10) #Vi tri xuat hien cua Textbox txt.grid(column=1, row=0) #Dat vi tri con tro tai Textbox txt.focus() #Ham xu ly khi nut duoc nhan def clicked():

res = "Welcome to " + txt.get() lbl.configure(text= res)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

btn = Button(window, text="Click Me", command=clicked) btn.grid(column=2, row=0) #De tat chuc nang nhap cua Textbox bang state #txt = Entry(window,width=10, state=’disabled’) window.mainloop()

Ví dụ 5.1.3. Tạo giao diện với Textbox.

d) Làm việc với Combobox

Ví dụ 5.1.4. Tạo giao diện với Combobox.

#Cac gia tri cua hop chon

1 2 3 4 5 6 7 8 9 10 11 12

from tkinter import * from tkinter.ttk import * window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’) combo = Combobox(window) #Tao hop chon Combobox combo[’values’]= (1, 2, 3, 4, 5, "Text") #Thiet lap gia tri duoc chon combo.current(1) #set the selected item combo.grid(column=0, row=0) #Lay gia tri cua hop chon bang combo.get() window.mainloop()

5.1 Thiết kế giao diện với Tkinter 237

e) Làm việc với Checkbox:

1 2 3 4 5 6 7 8 9 10 11

from tkinter import * from tkinter.ttk import * window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’) chk_state = BooleanVar() #Thiet lap trang thai cua Checkbox chk_state.set(True) #set check state #Tao Checkbox co trang thai da tich chon chk = Checkbutton(window, text=’Choose’, var=chk_state) chk.grid(column=0, row=0) window.mainloop()

Ví dụ 5.1.5. Tạo giao diện với Checkbox.

f) Làm việc với Radio:

from tkinter import * from tkinter.ttk import * window = Tk() window.title("Welcome to LikeGeeks app") selected = IntVar() rad1 = Radiobutton(window,text=’First’, value=1, variable=selected) rad2 = Radiobutton(window,text=’Second’, value=2, variable=selected) rad3 = Radiobutton(window,text=’Third’, value=3, variable=selected) def clicked():

print(selected.get())

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

btn = Button(window, text="Click Me", command=clicked) rad1.grid(column=0, row=0) rad2.grid(column=1, row=0) rad3.grid(column=2, row=0) btn.grid(column=3, row=0) window.mainloop()

Ví dụ 5.1.6. Tạo giao diện với Radio.

Chương 5. Phát triển ứng dụng với Python 238

g) Làm việc với ScrolledText:

from tkinter import * from tkinter import scrolledtext window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’) txt = scrolledtext.ScrolledText(window,width=40,height=10) txt.grid(column=0,row=0) window.mainloop()

1 2 3 4 5 6 7 8

Ví dụ 5.1.7. Tạo giao diện với ScrolledText.

h) Làm việc với Messagebox:

from tkinter import * from tkinter import messagebox window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’) def clicked():

messagebox.showinfo(’Message title’, ’Message content’)

btn = Button(window,text=’Click here’, command=clicked) btn.grid(column=0,row=0) window.mainloop()

1 2 3 4 5 6 7 8 9 10

Ví dụ 5.1.8. Tạo hộp thoại thông báo Messagebox.

messagebox.showwarning(’Message title’, ’Message content’) #Hop thoai canh bao messagebox.showerror(’Message title’, ’Message content’) #Hop thoai bao loi

1 2

Ví dụ 5.1.9. Tạo hộp thoại cảnh báo và lỗi Messagebox.

from tkinter import messagebox res = messagebox.askquestion(’Message title’,’Message content’) res = messagebox.askyesno(’Message title’,’Message content’) res = messagebox.askyesnocancel(’Message title’,’Message content’) res = messagebox.askokcancel(’Message title’,’Message content’) res = messagebox.askretrycancel(’Message title’,’Message content’)

1 2 3 4 5 6

Ví dụ 5.1.10. Tạo hộp thoại câu hỏi Messagebox.

i) Làm việc với SpinBox:

from tkinter import *

window = Tk() window.title("Welcome to VniTeach app") window.geometry(’350x200’)

1 2 3 4 5

Ví dụ 5.1.11. Tạo spinbox.

6 7 8 9 10

#Tao spinbox co chieu rong 5, gia tri tu 0 den 100 spin = Spinbox(window, from_=0, to=100, width=5) spin.grid(column=0,row=0) window.mainloop()

5.1 Thiết kế giao diện với Tkinter 239

1 2

#spinbox chi gom co 3 gia tri la 3, 5 va 10 spin = Spinbox(window, values=(3, 5, 10), width=5)

- Liệt kê các giá trị của spinbox:

1 2 3

var =IntVar() var.set(25) #Dat gia tri mac dinh la 25 spin = Spinbox(window, from_=0, to=100, width=5, textvariable=var)

- Đặt giá trị mặc định cho spinbox:

j) Làm việc với trình chọn tệp và thư mục:

1 2 3

from tkinter import filedialog file=filedialog.askopenfilename(filetypes =(("Text files","*.txt"),("all files","*.*"))) dir = filedialog.askdirectory()

Ví dụ 5.1.12. Mở hộp thoại mở file *.txt và tất cả các file.

1 2 3

from tkinter import filedialog from os import path file = filedialog.askopenfilename(initialdir= path.dirname(__file__))

Chỉ định thư mục ban đầu cho hộp thoại tệp bằng cách chỉ định initialdir như sau:

k) Làm việc với Menu:

from tkinter import * from tkinter import Menu

1 2 3 4 5 6 7 8 9 10 11 12 13

window = Tk() window.title("Welcome to VniTeach app") menu = Menu(window) new_item = Menu(menu) new_item.add_command(label=’New’) new_item.add_separator() new_item.add_command(label=’Edit’) menu.add_cascade(label=’File’, menu=new_item) window.config(menu=menu) window.mainloop()

Ví dụ 5.1.13. Tạo Menu với Tinker.

1 2

#Thuc hien ham clicked khi nguoi dung chon New new_item.add_command(label=’New’, command=clicked)

Sự kiện khi người dùng click chọn một bảng chọn nào đó:

Chương 5. Phát triển ứng dụng với Python 240

l) Làm việc với các Tabs: Để tạo một điều khiển tab, có một vài bước. • Bước 1: Chúng ta tạo một điều khiển tab bằng cách sử dụng lớp Notebook. • Bước 2: Tạo một tab bằng cách sử dụng Frame lớp. • Bước 3: Thêm tab đó vào điều khiển tab. • Bước 4: Đóng gói điều khiển tab để nó hiển thị trong cửa sổ.

from tkinter import * from tkinter import ttk

1 2 3 4 5 6 7 8 9 10

window = Tk() window.title("Welcome to VniTeach app") tab_control = ttk.Notebook(window) tab1 = ttk.Frame(tab_control) tab_control.add(tab1, text=’First’) tab_control.pack(expand=1, fill=’both’) window.mainloop()

Ví dụ 5.1.14. Tạo các tab.

from tkinter import * from tkinter import ttk

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

window = Tk() window.title("Welcome to LikeGeeks app") tab_control = ttk.Notebook(window) tab1 = ttk.Frame(tab_control) tab2 = ttk.Frame(tab_control) tab_control.add(tab1, text=’First’) tab_control.add(tab2, text=’Second’) lbl1 = Label(tab1, text= ’label1’) lbl1.grid(column=0, row=0) lbl2 = Label(tab2, text= ’label2’) lbl2.grid(column=0, row=0) tab_control.pack(expand=1, fill=’both’) window.mainloop()

Thêm Widgets vào Notebook: Sau khi tạo các tab, chúng ta có thể đặt các widget bên trong các tab này bằng cách gán thuộc tính cha cho tab mong muốn.

Kết quả:

Hình 5.1: Tạo giao diện với Tinker.

5.1 Thiết kế giao diện với Tkinter 241

5.1.3.1 Tạo cửa sổ với các nhãn khác nhau

5.1.3 Project 1. Tạo cửa sổ và hộp thoại

import tkinter as tk window = tk.Tk() window.rowconfigure(0, minsize=50) window.columnconfigure([0, 1, 2, 3], minsize=50) label1 = tk.Label(text="1", bg="black", fg="white") label2 = tk.Label(text="2", bg="black", fg="white") label3 = tk.Label(text="3", bg="black", fg="white") label4 = tk.Label(text="4", bg="black", fg="white") label1.grid(row=0, column=0) label2.grid(row=0, column=1, sticky="ew") label3.grid(row=0, column=2, sticky="ns") label4.grid(row=0, column=3, sticky="nsew") window.mainloop()

1 2 3 4 5 6 7 8 9 10 11 12 13

Tạo cửa sổ với 4 nhãn khác nhau

5.1.3.2 Tạo cửa sổ thay đổi tùy chỉnh theo kích thước

Kết quả:

import tkinter as tk window = tk.Tk() for i in range(3):

window.columnconfigure(i, weight=1, minsize=75) window.rowconfigure(i, weight=1, minsize=50) for j in range(0, 3):

frame = tk.Frame(master=window,relief=tk.RAISED,borderwidth=1) frame.grid(row=i, column=j, padx=5, pady=5) label = tk.Label(master=frame, text=f"Row {i}\nColumn {j}") label.pack(padx=5, pady=5)

window.mainloop()

1 2 3 4 5 6 7 8 9 10 11

Tạo cửa sổ với các button tự thay đổi tùy chỉnh theo kích thước cửa sổ.

Kết quả:

5.1.3.3 Tạo hộp thoại đăng nhập với Tinker

Chương 5. Phát triển ứng dụng với Python 242

from tkinter import * import re from tkinter import messagebox import sqlite3 import random from email.message import EmailMessage import smtplib # Database try:

con = sqlite3.connect(’website.db’) con.execute(’’’create table if not exists users(

fname text not null,lname text not null, email text not null,password text not null);’’’)

con.close()

except Exception as ep:

messagebox.showerror(’’, ep)

ws = Tk() ws.title(’Python Guides’) ws.geometry(’500x400’) ws.config(bg="#447c84") ws.attributes(’-fullscreen’,True) # functions def otp_gen():

pass cpy = ’’ def sendOtp(): otp_no = ’’ for _ in range(4):

r = random.randint(0, 9) otp_no += str(r)

global cpy cpy += otp_no sender = "nhuonglddhhp.edu.vn"reciever = em.get()password = "Python2023" msg_body = f’otp is {cpy}’ msg = EmailMessage() msg[’subject’] = ’OTP’ msg[’from’] = sender msg[’to’] = reciever msg.set_content(msg_body) with smtplib.SMTP_SSL(’smtp.gmail.com’, 465) as smtp:

smtp.login(sender,password) smtp.send_message(msg)

print(cpy) return cpy

def clr():

fname.delete(0, END) lname.delete(0, END)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

Tạo hộp thoại đăng nhập với Tinker.

em.delete(0, END) pwd.delete(0, END)

def submit():

enteredOtp = otp.get() expectedOtp = cpy print(expectedOtp) fname_check = fname.get() lname_check = lname.get() em_check = em.get() pwd_check = pwd.get() otp_check = otp.get() check_count = 0 if fname_check == "": warn = "First name can’t be empty!" else: check_count += 1 if lname_check == "": warn = "Last name can’t be empty!" else: check_count += 1 if em_check == "": warn = "Email can’t be empty!" else: check_count += 1 if pwd_check == "": warn = "Password can’t be empty!" else: check_count += 1 if otp_check == "": warn = "Otp can’t be empty!" else: check_count += 1 # if fname_check, lname_check, pwd_check, otp_check: if check_count == 5:

if (expectedOtp == enteredOtp):

con = sqlite3.connect(’website.db’) c = con.cursor() c.execute("insert into users VALUES (:fname, :lname, :em, :pwd)",{

’fname’: fname.get(), ’lname’: lname.get(), ’em’: em.get(), ’pwd’: pwd.get()})

con.commit() ws.destroy() import app

else: messagebox.showerror(’’,’Incorrect Otp’)

else: messagebox.showerror(’’, warn)

# frames frame = Frame(ws, padx=20, pady=20) frame.pack(expand=True) # labels Label(frame,text="Create New Account",font=("Times","24","bold"))

.grid(row=0, columnspan=3, pady=10)

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

Label(frame,text=’First Name’,font=("Times", "14")).grid(row=1, column=0, pady=5) Label(frame,text=’Last Name’,font=("Times", "14")).grid(row=2, column=0, pady=5) Label(frame,text=’Email Address’,font=("Times", "14")).grid(row=3, column=0, pady=5) Label(frame,text=’Password’,font=("Times", "14")).grid(row=4, column=0, pady=5) Label(frame,text=’Enter OTP’,font=("Times", "14")).grid(row=5, column=0, pady=5) # Entry fname = Entry(frame, width=30)

5.1 Thiết kế giao diện với Tkinter 243

lname = Entry(frame, width=30) em = Entry(frame, width=30) pwd = Entry(frame, width=30) otp = Entry(frame, width=30) fname.grid(row=1, column=1) lname.grid(row=2, column=1) em.grid(row=3, column=1) pwd.grid(row=4, column=1) otp.grid(row=5, column=1) # button clr = Button(frame, text="Clear", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=clr)

reg = Button(frame, text="Register", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=submit)

ext = Button(frame, text="Exit", padx=20, pady=10, relief=SOLID,

font=("Times", "14", "bold"), command=lambda:ws.destroy())

otpp = Button(frame, text="verify email", padx=10, relief=RAISED,

font=("Times", "10", "bold"), command=sendOtp)

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

clr.grid(row=6, column=0, pady=20) reg.grid(row=6, column=1, pady=20) ext.grid(row=6, column=2, pady=20) otpp.grid(row=5, column=2) ws.mainloop()

Chương 5. Phát triển ứng dụng với Python 244

Kết quả:

Hình 5.2: Tạo giao diện đăng nhập với Tinker.

5.1.4 Project 2. Tạo ứng dụng trắc nghiệm với Python Tinker

from tkinter import * from tkinter import messagebox as mb import json class Quiz:

1 2 3 4 5 6 7 8

def __init__(self): self.qno=0 self.disp_title() self.disp_ques()

Tạo ứng dụng trắc nghiệm đơn giản với Python Tinker

self.opt_sel=IntVar() self.opts=self.radio_buttons() self.disp_opt() self.buttons() self.total_size=len(question) self.correct=0

def disp_res(self):

wrong_count = self.total_size - self.correct correct = f"Correct: {self.correct}" wrong = f"Wrong: {wrong_count}" score = int(self.correct / self.total_size * 100) result = f"Score: {score}%" mb.showinfo("Result", f"{result}\n{correct}\n{wrong}")

def check_ans(self, qno):

if self.opt_sel.get() == answer[qno]: return True def next_btn(self):

if self.check_ans(self.qno):

self.correct += 1

self.qno += 1 if self.qno==self.total_size:

self.disp_res() ws.destroy()

else:

self.disp_ques() self.disp_opt()

def buttons(self):

next_button = Button(ws,text="Next",command=self.next_btn,width=10,

bg="#F2780C",fg="white",font=("ariel",16,"bold"))

next_button.place(x=350,y=380) quit_button = Button(ws,text="Quit",command=ws.destroy,width=5,

bg="black", fg="white",font=("ariel",16," bold"))

quit_button.place(x=700,y=50)

def disp_opt(self):

val=0 self.opt_sel.set(0) for option in options[self.qno]: self.opts[val][’text’]=option val+=1 def disp_ques(self):

qno = Label(ws,text=question[self.qno],width=60,font=(’ariel’,16,’bold’)

,anchor= ’w’,wraplength=700,justify=’center’)

qno.place(x=70, y=100)

def disp_title(self):

title = Label(ws,text="PythonGuides QUIZ",width=50,

bg="#F2A30F",fg="white",font=("ariel", 20, "bold"))

title.place(x=0, y=2)

def radio_buttons(self):

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

q_list = []

5.1 Thiết kế giao diện với Tkinter 245

y_pos = 150 while len(q_list) < 4:

radio_btn = Radiobutton(ws,text=" ",variable=self.opt_sel,

value = len(q_list)+1,font = ("ariel",14))

q_list.append(radio_btn) radio_btn.place(x = 100, y = y_pos) y_pos += 40

return q_list

ws = Tk() ws.geometry("800x450") ws.title("PythonGuides Quiz") with open(’data.json’) as f: data = json.load(f)

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

question = (data[’question’]) options = (data[’options’]) answer = (data[ ’answer’]) quiz = Quiz() ws.mainloop()

Chương 5. Phát triển ứng dụng với Python 246

Kết quả:

Hình 5.3: Tạo ứng dụng trắc nghiệm với Python Tinker.

5.1.5 Project 3. Sinh mã QR Code với Tinker sử dụng thư viện pyqrcode

from tkinter import * from tkinter import messagebox import pyqrcode ws = Tk() ws.title("PythonGuides") ws.config(bg=’#F25252’)

1 2 3 4 5 6 7 8

def generate_QR():

Sinh mã QR Code với Tinker sử dụng thư viện pyqrcode. Mã QR là mã phản hồi nhanh được phát minh bởi một công ty ô tô Nhật Bản vào năm 1994. Mã QR là một loại mã vạch ma trận, dùng nhãn quang học mà máy có thể đọc được, chứa thông tin về vật phẩm được đính kèm. Một mã QR bao gồm các ô vuông màu đen được sắp xếp theo lưới ô vuông trên nền trắng, có thể được đọc bởi một thiết bị hình ảnh chẳng hạn như máy ảnh.

if len(user_input.get())!=0 :

global qr,img qr = pyqrcode.create(user_input.get()) img = BitmapImage(data = qr.xbm(scale=8))

else: messagebox.showwarning(’warning’, ’All Fields are Required!’) try: display_code() except: pass def display_code():

img_lbl.config(image = img) output.config(text="QR code of " + user_input.get())

lbl = Label(ws,text="Enter message or URL",bg=’#F25252’) lbl.pack()

user_input = StringVar() entry = Entry(ws,textvariable = user_input) entry.pack(padx=10)

button = Button(ws,text = "generate_QR",width=15,command = generate_QR) button.pack(pady=10)

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

img_lbl = Label(ws,bg=’#F25252’) img_lbl.pack() output = Label(ws,text="",bg=’#F25252’) output.pack() ws.mainloop()

5.1 Thiết kế giao diện với Tkinter 247

Kết quả:

Hình 5.4: Sinh mã QR Code với Tinker sử dụng thư viện pyqrcode.

1 2 3 4 5

from tkinter import * window = Tk() # Tao cua so Tkinter window # Dinh nghia cua so chieu rong (312) va cao (324) dung phuong thuc ’geometry’ window.geometry("312x324") # Phuong thuc ’resizable’ ngan cho thay doi kich thuoc cua so

5.1.6 Project 4. Tạo máy tính cá nhân với Python Tinker

window.resizable(0, 0) window.title("Calcualtor") #Thiet lap tieu de cua so # Dinh nghia cac ham tinh toan. # 1. Click nut ’btn_click’ de cap nhat. def btn_click(item): global expression expression = expression + str(item) input_text.set(expression)

# 2. Dinh nghia nut xoa du lieu ’btn_clear’ "C" def btn_clear():

global expression expression = "" input_text.set("")

# 3. Dinh nghia nut equal ("=") ’btn_equal’ tinh toan bieu thuc truong du lieu. def btn_equal():

global expression result = str(eval(expression)) # ’eval’ tinh gia tri bieu thuc truc tiep input_text.set(result) expression = ""

expression = "" # In order to get the instance of the input field ’StringVar()’ is used input_text = StringVar() # The first thing is to create a frame for the input field input_frame = Frame(window, width = 312, height = 50, bd = 0, highlightbackground = "black", highlightcolor = "black", highlightthickness = 1) input_frame.pack(side = TOP) input_field = Entry(input_frame,font=(’arial’,18,’bold’),textvariable=input_text,

width=50,bg="#eee",bd = 0, justify = RIGHT)

input_field.grid(row = 0, column = 0) # ’ipady’ is an internal padding to increase the height of input field input_field.pack(ipady = 10) btns_frame = Frame(window, width = 312, height = 272.5, bg = "grey") btns_frame.pack() # The first row will comprise of the buttons ’Clear (C)’ and ’Divide (/)’ clear = Button(btns_frame, text ="C", fg="black", width=32, height=3, bd=0, bg="#eee", cursor="hand2", command=lambda: btn_clear() ).grid(row=0, column=0, columnspan=3, padx=1, pady=1) divide = Button(btns_frame,text="",fg="black",width=10,height=3,bd=0,bg="#eee", cursor="hand2",command=lambda:btn_click("")).grid(row=0,column=3,padx=1,pady=1)

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

# The second row will comprise of the buttons ’7’, ’8’, ’9’ and ’Multiply (*)’ seven= Button(btns_frame, text="7", fg ="black", width=10, height=3, bd=0, bg ="#fff",cursor="hand2",command=lambda:btn_click(7) ).grid(row=1,column=0,padx=1,pady=1) eight= Button(btns_frame,text="8",fg ="black",width=10,height=3,bd=0,bg="#fff", cursor ="hand2",command=lambda:btn_click(8)).grid(row=1, column=1,padx=1,pady=1) nine= Button(btns_frame,text="9",fg ="black",width=10,height=3, bd=0,bg="#fff", cursor="hand2",command=lambda:btn_click(9)).grid(row=1,column=2,padx=1,pady=1) multiply=Button(btns_frame,text="*",fg="black",width=10,height=3,bd=0,bg="#eee", cursor="hand2",command=lambda:btn_click("*")).grid(row=1,column=3,padx=1,pady=1)

Chương 5. Phát triển ứng dụng với Python 248

#The third row will comprise of the buttons ’4’, ’5’, ’6’ and ’Subtract (-)’ four = Button(btns_frame,text="4",fg ="black",width=10,height=3,bd=0,bg ="#fff", cursor="hand2",command=lambda:btn_click(4)).grid(row=2,column=0,padx=1,pady=1) five = Button(btns_frame,text="5",fg="black",width=10, height=3,bd=0,bg="#fff", cursor="hand2",command=lambda:btn_click(5)).grid(row=2,column=1,padx=1,pady=1) six = Button(btns_frame,text="6",fg="black",width=10,height=3,bd=0,bg="#fff", cursor="hand2",command=lambda:btn_click(6)).grid(row=2,column=2,padx=1,pady=1) minus = Button(btns_frame,text="-",fg="black",width=10,height=3,bd =0,bg="#eee", cursor="hand2",command=lambda: btn_click("-")).grid(row=2,column=3,padx=1,pady=1)

# The fourth row will comprise of the buttons ’1’, ’2’, ’3’ and ’Addition (+)’ one = Button(btns_frame,text ="1",fg ="black",width=10,height=3,bd=0,bg="#fff", cursor="hand2",command=lambda:btn_click(1)).grid(row=3,column=0,padx=1,pady=1) two = Button(btns_frame,text ="2",fg ="black",width=10,height=3,bd=0,bg="#fff", cursor="hand2",command=lambda:btn_click(2)).grid(row=3,column=0,padx=1,pady=1) three = Button(btns_frame,text ="1",fg ="black",width=10,height=3,bd=0,bg="#fff", cursor="hand2",command=lambda:btn_click(3)).grid(row=3,column=0,padx=1,pady=1) plus = Button(btns_frame,text="+",fg="black",width=10,height=3,bd=0,bg="#eee", cursor="hand2",command=lambda:btn_click("+")).grid(row=3,column=3,padx=1,pady=1)

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

# Finally, the fifth row will comprise of the buttons ’0’,’Decimal(.)’,and’Equal To(=)’ zero=Button(btns_frame,text="0",fg="black",width=21,height=3,bd=0,bg="#fff",cursor="hand2", command=lambda:btn_click(0)).grid(row=4,column=0,columnspan=2,padx=1,pady=1) point=Button(btns_frame,text=".",fg ="black",width=10,height=3,bd=0,bg ="#eee", cursor="hand2",command=lambda: btn_click(".")).grid(row=4,column=2,padx=1,pady=1) equals =Button(btns_frame, text="=",fg="black",width=10,height=3,bd=0,bg="#eee", cursor="hand2",command=lambda:btn_equal()).grid(row=4,column=3,padx=1,pady=1) window.mainloop()

5.1 Thiết kế giao diện với Tkinter 249

Kết quả:

Hình 5.5: Tạo máy tính cá nhân với Python Tinker.

5.1.7 Project 5. Tạo game rắn Snake Game

Trò chơi rắn là một trong những trò chơi 2D truyền thống được mọi Millennials chơi. Trong trò chơi này có một con rắn đang chuyển động liên tục. Người chơi phải đảm bảo rằng con rắn

Chương 5. Phát triển ứng dụng với Python 250

from tkinter import * from random import randint from PIL import Image, ImageTk movement = 20 steps_per_sec = 10 speed = 1100 // steps_per_sec

class Snake(Canvas):

def __init__(self):

super().__init__(width=700,height=700,background=’#53ff1a’,highlightthickness=0) self.snake_pos = [(100, 80), (80, 100), (80, 100)] self.food_pos = self.set_new_food_pos() self.direction = ’Right’ self.score = 0 self.load_img() self.create_objects() self.bind_all(’’, self.on_key_press) self.pack() self.after(speed, self.perform_actions)

def load_img(self):

try:

self.snake_body = ImageTk.PhotoImage(Image.open(’game.png’)) self.food = ImageTk.PhotoImage(Image.open(’game.png’))

except IOError as error:

ws.destroy() raise

def create_objects(self):

self.create_text(35,12,text=f’Score: {self.score}’,

tag=’score’,fill=’black’,font=10)

for x_position, y_position in self.snake_pos:

self.create_image(x_position,y_position, image=self.snake_body,tag=’snake’)

self.create_image(*self.food_pos,image=self.food,tag=’food’) self.create_rectangle(7, 27, 690, 690, outline=’#d9d8d7’)

def finish_game(self): self.delete(ALL) self.create_text(

self.winfo_width() / 2,self.winfo_height() / 2, text=f’Game over! You have scored {self.score}!’, fill=’black’,font=20)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

không va vào tường hoặc không tự va chạm vào nhau. Người chơi có thể điều khiển con rắn bằng các phím Phải, Trái, Dưới, Trên. Con rắn bắt đầu thời điểm theo đúng hướng theo mặc định. Có n đối tượng trên màn hình được gọi là ’thức ăn’. Mỗi khi rắn va chạm với thức ăn, thức ăn biến mất và kích thước cơ thể rắn tăng lên. Có một số điểm cho mỗi va chạm thành công của con rắn với thức ăn.

def consume_food(self):

if self.snake_pos[0] == self.food_pos:

self.score += 10 self.snake_pos.append(self.snake_pos[-1])

self.create_image(

*self.snake_pos[-1], image=self.snake_body, tag=’snake’)

self.food_pos = self.set_new_food_pos() self.coords(self.find_withtag(’food’), *self.food_pos)

score = self.find_withtag(’score’) self.itemconfigure(score,text=f’Score:{self.score}’,tag=’score’)

def boundry(self):

head_x_position, head_y_position = self.snake_pos[0]

return (

head_x_position in (0, 700) or head_y_position in (20, 700) or (head_x_position, head_y_position) in self.snake_pos[1:])

def snake_movement(self):

head_x_position, head_y_position = self.snake_pos[0] if self.direction == ’Left’:

new_head_position = (head_x_position - movement, head_y_position)

elif self.direction == ’Right’:

new_head_position = (head_x_position + movement, head_y_position)

elif self.direction == ’Down’:

new_head_position = (head_x_position, head_y_position + movement)

elif self.direction == ’Up’:

new_head_position = (head_x_position, head_y_position - movement)

self.snake_pos = [new_head_position] + self.snake_pos[:-1] for segment, position in zip(self.find_withtag(’snake’), self.snake_pos):

self.coords(segment, position)

def on_key_press(self, e):

new_direction = e.keysym all_directions = (’Up’, ’Down’, ’Left’, ’Right’) opposites = ({’Up’, ’Down’}, {’Left’, ’Right’}) if (new_direction in all_directions

and {new_direction, self.direction} not in opposites): self.direction = new_direction

def perform_actions(self): if self.boundry():

self.finish_game()

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

self.consume_food()

5.1 Thiết kế giao diện với Tkinter 251

self.snake_movement() self.after(speed, self.perform_actions)

def set_new_food_pos(self):

while True:

x_position = randint(1, 29) * movement y_position = randint(3, 30) * movement food_pos = (x_position, y_position) if food_pos not in self.snake_pos:

return food_pos

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

ws = Tk() ws.title(’PythonGuides - Snake Game’) ws.resizable(False, False) board = Snake() ws.mainloop()

Chương 5. Phát triển ứng dụng với Python 252

Kết quả:

Hình 5.6: Tạo trò chơi rắn với Python Tinker.

5.2 Phát triển các ứng dụng cơ bản với Python

5.2.1.1 Thư viện Turtle Graphics

5.2.1 Projec 1. Vẽ hình với thư viện Turtle

1 2

import turtle as t import time as ti

Turtle Graphics là thư viện đồ họa con rùa có sẵn trong Python. Hình ảnh con rùa tưởng tượng giống như nó cầm cây bút để vẽ, di chuyển đến đâu là nó vẽ đường thẳng đến đó thông qua các chấm (dots-pixels) trên màn hình. Để vẽ các hình với thư viện Turtle, ta sử dụng 2 thư viện: turtle và time. Muốn sử dụng chúng ta khai báo thư viện dùng lệnh import turtle và cài đặt bằng cách gõ 2 dòng lệnh sau:

1

turtle = Turtle()

Để tạo đối tượng của Turle chúng ta dùng lệnh:

5.2.1.2 Cài đặt, triển khai các thiết lập với Turtle Graphics

5.2 Phát triển các ứng dụng cơ bản với Python 253

def rectangle(hor,ver,col): t.pendown() #tao con tro t.pensize(1) #kich co t.color(col) t.begin_fill() for counter in range(1,3): #day la mot vong lap (loop)

t.forward(hor) t.right(90) t.forward(ver) t.right(90)

1 2 3 4 5 6 7 8 9 10 11 12

t.end_fill() t.penup()

Trong phần này, chúng ta cùng thiết lập các phương thức chuyển động của rùa như sau:

1 2 3 4

>>> t.right(90) >>> t.forward(100) >>> t.left(90) >>> t.backward(100)

Có bốn hướng có thể di chuyển con trỏ gồm: di chuyển về trước .forward() hoặc về sau .backward() theo hướng đối diện, xoay trái .left() hoặc xoay phải .right(). Ví dụ:

1 2 3 4 5

t.penup() t.speed(’slow’) #Toc do ve cua con tro t.bgcolor(’Dodger blue’) ti.sleep(10) t.hideturtle()

Thiết lập con trỏ vẽ với các hàm .penup(), .speed():

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

t.goto(-100,-150) #Ve ban chan rectangle(50,20,’blue’) t.goto(-30,-150) rectangle(50,20,’blue’) t.goto(-25,-50) #Ve chan rectangle(15,100,’grey’) t.goto(-55,-50) rectangle(-15,100,’grey’) t.goto(-90,100) #Ve than rectangle(100,150,’red’) t.goto(-150,70) #Ve tay rectangle(60,15,’grey’) t.goto(-150,110) rectangle(15,40,’grey’) t.goto(10,70) rectangle(60,15,’grey’) t.goto(55,110) rectangle(15,40,’grey’)

Theo tác vẽ từng bộ phận:

t.goto(-50,120) #Ve co rectangle(15,20,’grey’) t.goto(-85,170) #Ve dau rectangle(80,50,’red’) t.goto(-60,160) rectangle(30,10,’white’) #Ve mat mieng t.goto(-60,160) rectangle(5,5,’black’) t.goto(-45,155) rectangle(5,5,’black’) t.goto(-65,135) t.right(5) rectangle(40,5,’black’) t.goto(-155,130) #Ve ban tay rectangle(25,25,’green’) t.goto(-147,130) rectangle(10,15,t.bgcolor()) t.goto(50,130) rectangle(25,25,’green’) t.goto(58,130) rectangle(10,15,t.bgcolor())

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

5.2.1.3 Thực hành vẽ với Turtle Graphics

Chương 5. Phát triển ứng dụng với Python 254

import turtle as t import time as ti def rectangle(hor,ver,col):

t.pendown() # Tao con tro t.pensize(1) t.color(col) t.begin_fill() for counter in range(1,3):

t.forward(hor) t.right(90) t.forward(ver) t.right(90)

t.end_fill() t.penup()

t.penup() t.speed(’slow’) t.bgcolor(’Dodger blue’) t.goto(-100,-150) rectangle(50,20,’blue’) t.goto(-30,-150) rectangle(50,20,’blue’) t.goto(-25,-50) rectangle(15,100,’grey’) t.goto(-55,-50) rectangle(-15,100,’grey’)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

Ví dụ 5.2.1. Vẽ robot đơn giản.

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

t.goto(-90,100) rectangle(100,150,’red’) t.goto(-150,70) rectangle(60,15,’grey’) t.goto(-150,110) rectangle(15,40,’grey’) t.goto(10,70) rectangle(60,15,’grey’) t.goto(55,110) rectangle(15,40,’grey’) t.goto(-50,120) rectangle(15,20,’grey’) t.goto(-85,170) rectangle(80,50,’red’) t.goto(-60,160) rectangle(30,10,’white’) t.goto(-60,160) rectangle(5,5,’black’) t.goto(-45,155) rectangle(5,5,’black’) t.goto(-65,135) t.right(5) rectangle(40,5,’black’) t.goto(-155,130) rectangle(25,25,’green’) t.goto(-147,130) rectangle(10,15,t.bgcolor()) t.goto(50,130) rectangle(25,25,’green’) t.goto(58,130) rectangle(10,15,t.bgcolor()) t.hideturtle() ti.sleep(10) t.hideturtle()

5.2 Phát triển các ứng dụng cơ bản với Python 255

Kết quả:

Hình 5.7: Vẽ robot đơn giản với Python Turtle

Chương 5. Phát triển ứng dụng với Python 256

import turtle t = turtle.Pen() turtle.bgcolor("black") colors = ["red", "yellow", "blue", "green"] for x in range(200):

t.pencolor(colors[x%4]) t.forward(x) t.left(91)

1 2 3 4 5 6 7 8

Ví dụ 5.2.2. Vẽ hình theo ý thích với nhiều màu sắc.

Kết quả:

Hình 5.8: Vẽ hình theo ý thích với nhiều màu sắc.

Ví dụ 5.2.3. Vẽ bông hoa màu.

Hình 5.9: Vẽ hoa với Python Turtle

1 2 3

import turtle NUM_SQUARES = 8 # Number of squares along one size of board. SQUARE_SIZE = 40 # Pixels

Ví dụ 5.2.4. Vẽ bàn cờ.

BOARD_SIZE = SQUARE_SIZE * NUM_SQUARES BORDER_FRACTION = 1.025 #Add a slight border to the board. STAMP_SIZE = 20 #Size of turtle square image.

screen = turtle.Screen() screen.title("Turtle Stamps") screen.setup(400, 400) screen.tracer(0) # Disable animation. pen = turtle.Turtle(shape=’square’, visible=False) pen.shapesize(BOARD_SIZE/STAMP_SIZE*BORDER_FRACTION) pen.color(’red’) pen.stamp()

pen.shapesize(SQUARE_SIZE / STAMP_SIZE) pen.color(’green’) pen.penup() for y in range(-NUM_SQUARES // 2, NUM_SQUARES // 2):

parity = y % 2 == 0 for x in range(-NUM_SQUARES // 2, NUM_SQUARES // 2):

if parity:

pen.goto(x*SQUARE_SIZE+SQUARE_SIZE//2, y*SQUARE_SIZE+SQUARE_SIZE//2) pen.stamp() parity = not parity

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

turtle.done()

5.2 Phát triển các ứng dụng cơ bản với Python 257

Kết quả:

Hình 5.10: Vẽ bàn cờ với Python Turtle

5.2.2.1 Thư viện 2D Matplotlib

5.2.2 Projec 2. Trực quan hóa dữ liệu với Matplotlib và Seaborn

Matplotlib là một thư viện Python sử dụng Python Script để giúp chúng ta tạo ra các đồ thị 2D thường được ứng dụng trong toán học và khoa học dữ liệu. Thư viện này có hỗ trợ tạo nhiều giao điểm giữa hai trục số trong cùng một lúc. Bên cạnh đó, chúng ta cũng có thể dùng Matplotlib để thao tác trực tiếp đến các đặc điểm khác nhau của đồ thị.

Chương 5. Phát triển ứng dụng với Python 258

Hình 5.11: Thư viện vẽ đồ thị 2D Matplotlib

5.2.2.2 Vẽ các biểu đồ cơ bản line, barchart, pie, scatter trên Matplotlib

Matplotlib có thể tạo ra những đồ thị chất lượng và xuất ra một cách dễ dàng và thuận tiện, hoàn toàn đáp ứng nhu cầu của mọi ngành học. Các đồ thị được tạo ra bằng Matplotlib có sẵn bản sao cứng trên các nền tảng tương tác khác nhau. Chúng ta có thể dùng Matplotlib với nhiều bộ công cụ như Python Scripts, IPython Shells, Jupyter Notebook, và nhiều công cụ khác. Một số thư viện của bên thứ ba có thể được tích hợp với các ứng dụng Matplotlib như seaborn, ggplot, và các bộ công cụ chiếu xạ, mapping khác như basemap. Matplotlib có cộng đồng nhà phát triển tích cực luôn sẵn sàng trợ giúp, chúng ta có thể theo dõi bất kỳ lỗi nào phát sinh trong quá trình coding, các bản vá mới, đồng thời còn có thể đóng góp các tính năng mới tại GitHub. Để tải và cài đặt Matplotlib, ta truy cập địa chỉ sau: https://matplotlib.org/downloads.html

1 2 3 4 5 6

# Vẽ biểu đồ line độ dài cánh hoa trung bình giữa các loài hoa plt.figure(figsize=(16, 8)) plt.plot(x, y, marker=’o’, markersize=10, linestyle=’-.’, linewidth=2) plt.xlabel(’Species’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Average of Petal Length", fontsize=18)

Biểu đồ line: là biểu đồ mà các điểm được nối với nhau bằng những đoạn thẳng. Biểu đồ line thường phù hợp với mục đích thể hiện trend tăng/giảm ở chuỗi thời gian và dữ liệu so sánh giữa các nhóm trong biến category. Để vẽ biểu đồ line chúng ta dùng hàm plt.plot(). Bên trong cần khai báo trục x và y hoặc chỉ trục y (giá trị index của x khi đó sẽ tự được sinh ra).

Các đối số marker và linestyles lần lượt qui định: • marker: Qui định hình dạng của point đánh dấu các điểm (x, y) trên toạ độ. Marker nhận các kiểu o, ∧, s lần lượt tương ứng với hình tròn, hình tam giác, hình vuông (s là viết tắt của square).

• markersize: Kích thước của point. • linestyles: Qui định kiểu của đoạn thẳng nối các points. Có thể nhận các giá trị −−, −., −, : • linewidth: Kích thước của đoạn thẳng.

5.2 Phát triển các ứng dụng cơ bản với Python 259

Hình 5.12: Vẽ biểu đồ line với Matplotlib

1 2 3 4 5 6 7

# Vẽ biểu đồ line độ dài cánh hoa trung bình giữa các loài hoa plt.figure(figsize=(16, 8)) plt.bar(x, y) plt.plot(x, y, marker=’o’, markersize=10, linestyle=’-.’, linewidth=2) plt.xlabel(’Species’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Average of Petal Length", fontsize=18)

Biểu đồ barchart: Biểu đồ này phù hợp với mục đích so sánh giá trị giữa các nhóm khác nhau như so sánh độ dài cánh hoa trung bình giữa các nhóm. Để vẽ biểu đồ barchart chúng ta sử dụng hàm plt.bar() như biểu đồ đầu tiên. Chúng ta cũng có thể kết hợp nhiều loại biểu đồ trong cùng một biểu đồ bằng cách dùng liên tiếp các câu lệnh vẽ biểu đồ như sau:

Hình 5.13: Vẽ biểu đồ line với Matplotlib

x, y = np.unique(df_iris[’Species’], return_counts = True) # Thống kê các loài hoa print(x) print(y)

1 2 3

Biểu đồ Pie: Khi chúng ta muốn thể hiện thị phần của từng phân khúc hoặc tỷ lệ phần trăm của từng nhóm thì biểu đồ tròn sẽ rất phù hợp. Chúng ta sẽ visualize đếm số lượng các loài hoa như sau:

# Vẽ biểu đồ line độ dài cánh hoa trung bình giữa các loài hoa plt.figure(figsize=(16, 8)) plt.pie(y,labels = x, # Nhãn của các nhóm

1 2 3

Dữ liệu vào: [’setosa’ ’versicolor’ ’virginica’], [35 35 35]

4 5

colors = [’red’,’blue’,’green’], # Màu sắc của các nhóm autopct = ’%1.1f%%’, # Format hiển thị giá trị shadow = False)plt.title("Average

of Petal Length", fontsize=18)

Chương 5. Phát triển ứng dụng với Python 260

Hình 5.14: Vẽ biểu đồ pie với Matplotlib

1 2 3 4 5 6 7 8 9

# lấy x, y x = df_iris[’Petal.Length’].values y = df_iris[’Petal.Width’].values # Vẽ biểu đồ line độ dài cánh hoa trung bình giữa các loài hoa plt.figure(figsize=(16, 8)) plt.scatter(x, y, color=’green’, ) plt.xlabel(’Petal.Length’, fontsize=16) plt.ylabel(’Petal.Width’, fontsize=16) plt.title("Average of Petal Length", fontsize=18)

Biểu đồ scatter: Được sử dụng để biểu diễn từng điểm (x, y) trong đồ thị hai chiều. Trong machine learning, khi cần biểu diễn các cụm hoặc trong các tình huống muốn tìm ra phân phối của các điểm dữ liệu theo các chiều chúng ta sẽ thường dùng biểu đồ scatter. Chúng ta cần tìm ra phân phối của các điểm dữ liệu.

Như vậy chúng ta có thể thấy kích thước của cánh hoa có thể được phân thành hai cụm một cách khá rõ ràng.

Hình 5.15: Vẽ biểu đồ scatter với Matplotlib

5.2.2.3 Vẽ các biểu đồ nâng cao box-plot, swarm, histogram, density, heatmap matrix, trên

matplotlib

5.2 Phát triển các ứng dụng cơ bản với Python 261

Các biểu đồ nâng cao trên matplotlib là những biểu đồ thường ít được sử dụng hơn. Nó đòi hỏi người đọc phải am hiểu về thống kê và có thể phải tìm hiểu trước về nội dung được thể hiện trong những biểu đồ này để có thể đọc được. Việc đưa ra kết luận về dữ liệu từ biểu đồ này cũng khó hơn so với các biểu đồ cơ bản vì nó có độ phức tạp cao hơn. Nhưng qua chương này mình sẽ hướng dẫn các bạn đọc hiểu các biểu đồ như thế.

Biểu đồ box-plot: Giúp xác định outliers và tìm ra kiểu phân phối của dữ liệu. Cụ thể biểu đồ này xác định các ngưỡng chia tại các mức phân vị 25% (là giá trị mà có 25% quan sát nhỏ hơn giá trị này), median (hoặc mức phân vị 50%), mức phân vị 75% được ký hiệu lần lượt là Q1, Q2, Q3. Các miền giá trị được xác định từ các ngưỡng trên sẽ tương ứng với:

• Miền giá trị thấp nhất: Chứa các quan sát từ thấp nhất (không bao gồm outliers) tới Q1. • Miền giá trị thấp: Chứa các quan sát nằm trong khoảng từ [Q1, Q2). • Miền giá trị cao: Chứa các quan sát trong khoảng [Q2, Q3). • Miền giá trị cao nhất: Chứa các quan sát từ Q3 tới giá trị cao nhất (không bao gồm outliers).

1 2 3 4 5 6 7 8 9 10

# Lấy ra list các chiều dimension cần khảo sát dims = list(df_iris.select_dtypes(’float’).columns) print(dims) # Vẽ biểu đồ bboxplot plt.figure(figsize=(16, 8)) plt.boxplot([df_iris[col] for col in dims]) plt.xlabel(’Scale’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.xticks(np.arange(len(dims))+1, dims, rotation=45, fontsize=16) plt.title("Boxplot of Dimensions", fontsize=18)

Chỉ số IQR (interquartile range) được xác định chính bằng độ dài của hai miền giá trị cao và thấp: IQR = Q3 − Q1. Dựa trên IRQ, outliers sẽ được xác định nếu nằm ngoài miền giá trị cao nhất và miền giá trị thấp nhất. Tức là nếu x > Q3 + 1.5 ∗ IQR hoặc x < Q1 − 1.5 ∗ IQR thì sẽ được xác định là outliers.

Dữ liệu: [’Sepal.Length’, ’Sepal.Width’, ’Petal.Length’, ’Petal.Width’]

Hình 5.16: Vẽ biểu đồ boxplot với Matplotlib

Chương 5. Phát triển ứng dụng với Python 262

Nhìn vào biểu đồ ta có thể thấy Sepal.Width có một giá trị outlier nằm ở vị trí lớn nhất. Các phân phối Petal.Width, Petal.Length có xu hướng lệch phải khi median nằm gần ngưỡng Q3 (ứng với quantile 75%) hơn. Sepal.Length có phân phối tương đối cân đối về hai phía trong khi Sepal.Width có phân phối lệch trái. Biểu đồ cũng cho thấy độ lớn giữa các biến khi so sánh median đó là Sepal.Length > Petal.Length > Sepal.Width > Petal.Width.

1

sns.swarmplot(x=None, y=None, hue=None, data=None)

Biểu đồ swarm (đôi khi được gọi là beeswarm): là một dạng biểu đồ cho phép ta biểu diễn phân phối của các điểm rất tốt. Các điểm trong biểu đồ swarm được giữ đúng như giá trị thật của nó chứ không bị biến đổi như histogram hay density nên chúng ta có thể theo dõi được chính xác phân phối thực tế của dữ liệu và nhận biết outlier hiệu quả. Để vẽ biểu đồ swarm thì chúng ta sẽ dùng package seaborn. Đây là package mở rộng của matplotlib nhằm cung cấp các biểu đồ mà trong matplotlib chưa hỗ trợ. Khi visualize các biểu đồ liên quan tới phân phối như swarm, histogram, density thì đây là một package rất hiệu quả. Cấu trúc chung của biểu đồ swarm như sau:

1 2 3 4 5 6

import seaborn as sns plt.figure(figsize=(16, 8)) # Vẽ biểu đồ swarm sns.swarmplot(x=’Species’, y=’Sepal.Width’, data = df_iris) plt.xlabel(’Scale’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Swarm of Dimensions", fontsize=18)

Trong đó, data là bảng dữ liệu dạng pandas Dataframe chứa thông tin để vẽ biểu đồ. x là trục hoành, y là trục tung. Thông thường x sẽ là một biến chiều xoay (dimension) và y là một biến đo lường (measurement). hue là biến về phân loại màu sắc. Chúng ta sẽ visualize độ dài cánh hoa Sepal.Length cho các điểm thuộc về 3 loài hoa thông qua biểu đồ swarm:

Hình 5.17: Vẽ biểu đồ swarm với Matplotlib

1 2 3 4 5 6

import seaborn as sns plt.figure(figsize=(16, 8)) sns.swarmplot(y=’Species’, x=’Sepal.Width’, data = df_iris) plt.xlabel(’Scale’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Swarm of Dimensions", fontsize=18)

Chúng ta cũng có thể xoay ngang đồ thị bằng cách đảo ngược trục x, y cho nhau.

5.2 Phát triển các ứng dụng cơ bản với Python 263

Hình 5.18: Vẽ biểu đồ swarm xoay ngang với Matplotlib

1 2 3 4 5 6

import seaborn as sns plt.figure(figsize=(16, 8)) sns.swarmplot(x=’Species’, y=’Sepal.Width’, hue=’Species’, data = df_iris) plt.xlabel(’Scale’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Swarm of Dimensions", fontsize=18)

Khi muốn thay đổi màu sắc theo từng loài hoa ta có thể thêm hue=Species.

Hình 5.19: Vẽ biểu đồ swarm thay đổi màu sắc với Matplotlib

1 2 3 4 5 6

import seaborn as sns plt.figure(figsize=(16, 8)) sns.violinplot(x=’Species’, y=’Sepal.Width’, hue=’Species’, data = df_iris) plt.xlabel(’Scale’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Swarnplot of Sepal.Width", fontsize=18)

Nhìn vào biểu đồ swarm ta có thể thấy toàn bộ các điểm đều được thể hiện trên đồ thị. Chúng ta sẽ nhận biết được đâu là miền giá trị tập trung nhiều dữ liệu nhất, đâu là các vị trí outliers. Ngoài ra ta cũng có thể sử dụng một dạng biểu đồ khác giống như swarm nhưng đã được biến đổi thành distribution theo kernel distribution. Đó chính là biểu đồ violin.

Chương 5. Phát triển ứng dụng với Python 264

Hình 5.20: Vẽ biểu đồ violin với Matplotlib

1 2 3 4 5 6

import seaborn as sns plt.figure(figsize=(16, 8)) sns.histplot(x=’Sepal.Width’, data = df_iris, bins=10) plt.xlabel(’Scale’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Histogram of Sepal.Width", fontsize=18)

Biểu đồ Histogram: Là biểu đồ biểu diễn phân phối của các biến liên tục bằng cách chia nhỏ chúng thành những bins có độ dài bằng nhau và thống kê số lượng các quan sát rơi vào từng bins.

Hình 5.21: Vẽ biểu đồ Histogram với Matplotlib

1 2 3 4 5 6

import seaborn as sns plt.figure(figsize=(16, 8)) sns.histplot(x=’Sepal.Width’, data = df_iris, bins=50, kde=True) plt.xlabel(’Scale’, fontsize=16) plt.ylabel(’cm’, fontsize=16) plt.title("Histogram of Sepal.Width", fontsize=18)

Biểu đồ histogram sẽ không thể hiện rõ được xu hướng phân phối nếu ta chia các vùng của bin quá nhỏ. Vì vậy chúng ta có thể thêm một lựa chọn kde=True để vẽ thêm một đường density plot thể hiện mật độ phân phối liên tục hơn bên cạnh histogram.

5.2 Phát triển các ứng dụng cơ bản với Python 265

Hình 5.22: Vẽ biểu đồ Histogram có đường density với Matplotlib

1

df_iris.describe()

Density: Mỗi một trường dữ liệu đều có một đặc trưng riêng của nó. Để lượng hóa những đặc trưng này, thống kê học sử dụng các đại lượng thống kê mô tả như mean, max, median, standard deviation, percentile. Để tính thống kê mô tả cho một dataset dạng pandas dataframe đơn giản là ta sử dụng hàm describe().

Bảng 5.4: Dữ liệu vẽ dạng pandas dataframe đơn giản

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

count mean std min 25% 50% 75% max

105 5.812381 0.784305 4.4 5.2 5.7 6.3 7.9

105 3.07619 0.455843 2.2 2.8 3 3.4 4.4

105 3.726667 1.74908 1 1.6 4.2 5.1 6.9

105 1.18381 0.74616 0.1 0.3 1.3 1.8 2.5

Tuy nhiên không phải lúc nào thống kê mô tả cũng là duy nhất đối với một trường dữ liệu. Một ví dụ tiêu biểu mà chúng ta có thể xem xét là phân phối hình chú khủng long. Phân phối hình chú khủng long và các hình bên dưới có hình dạng hoàn toàn khác biệt nhau nhưng đều dựa trên 2 biến (x, y) có chung thống kê mô tả mean, phương sai và hệ số tương quan.

Chương 5. Phát triển ứng dụng với Python 266

Hình 5.23: Vẽ biểu đồ density phân phố chú khủng long với Matplotlib

Tất cả những phân phối trên đều có chung thống kê mô tả nhưng chúng khác xa nhau về bản chất của phân phối. Do đó không nên hoàn toàn tin tưởng vào thống kê mô tả mà bên cạnh đó chúng ta cần visualize phân phối của dữ liệu. Trong thống kê mỗi một biến liên tục được đặc trưng bởi một hàm mật độ xác suất (pdf - probability density function). Các phân phối điển hình như standard normal, T-student, poisson, fisher, chi-squared đều có những hình dạng phân phối xác suất khác nhau.

Hình 5.24: Đồ thị hàm mật độ xác suất của những phân phối xác suất standard normal, T-student, poisson, fisher, chi-squared.

Về mặt lý thuyết (theoreotical) những phân phối này đều dựa trên những phương trình đáng tin cậy. Trong thực nghiệm (empirical) nhiều bộ dữ liệu cho thấy có hình dạng tương đồng với những phân phối này. Để tìm ra một hình dạng tương đối cho hàm mật độ xác suất của một bộ

5.2 Phát triển các ứng dụng cơ bản với Python 267

dữ liệu chúng ta sẽ sử dụng phương pháp KDE (kernel density estimate). Hãy tưởng tượng tại mỗi một quan sát ta có đường cong phân phối đặc trưng. Hàm kernel sẽ giúp xác định hình dạng của đường cong trong khi độ rộng của đường cong được xác định bởi bandwidth - h (bandwidth horizontal, là độ rộng của KDE xác định theo chiều ngang). Phương pháp KDE sẽ tính tổng của các đường cong chạy dọc theo trục để hình thành nên đường cong mật độ xác suất tổng quát cho dữ liệu.

Phương pháp KDE giúp xây dựng hình dạng phân phối của dữ liệu. Ở những nơi có nhiều điểm dữ liệu tập trung thì số lượng các đường cong chồng lấn lên nhau sẽ nhiều hơn và do đó khi tính tổng cộng dồn của nó ta sẽ thu được một giá trị lũy kế kernel density lớn hơn và trái lại với những nơi có nhiều ít điểm dữ liệu tập trung.

Hình 5.25: Đồ thị KDE.

import seaborn as sns plt.figure(figsize=(16, 8)) sns.distplot(df_iris[’Sepal.Width’],hist = True, bins=int(180/5), kde = True,

color=’darkblue’,hist_kws={’edgecolor’:’black’},kde_kws={’linewidth’:2})

1 2 3 4 5

plt.title("Density of Sepal.Width", fontsize=18)

Ngoài ra hình dạng bandwidth - h sẽ giúp xác định mức độ khái quát hoặc chi tiết của đường cong. Nếu ta muốn đường cong smoothing hơn thì cần thiết lập h lớn hơn và đường cong mấp mô hơn thì h cần nhỏ hơn. Tuy nhiên bạn đọc cũng không cần quá quan tâm đến bandwidth vì cách tốt hơn là sử dụng giá trị mặc định được tính trong matplotlib. Bên dưới ta sẽ thực hành vẽ hàm mật độ xác suất của Sepal.Width thông qua hàm distplot() của package seaborn.

Hình 5.26: Đồ thị density với sepal.width.

Chương 5. Phát triển ứng dụng với Python 268

1 2 3

# Thống kê trung bình các measurements của các loài hoa df_summary = df_iris.groupby(’Species’).mean() df_summary

Heatmap maxtrix: là biểu đồ biểu diễn các giá trị của các ma trận có độ lớn thay đổi theo màu sắc. Biều đồ này hay ở chỗ các giá trị càng lớn thì màu sắc càng sáng và giá trị nhỏ thì màu sắc sẽ tối hơn. Đây là biểu đồ thường được sử dụng để visualize kết quả confusion-matrix của mô hình phân loại hay kết quả của ma trận hệ số tương quan giữa các biến. Chúng ta sẽ thống kê trung bình của các measurements theo các loài hoa và vẽ biểu đồ heatmap matrix thể hiện độ lớn giữa từng loài hoa theo các metric.

Bảng 5.5: Dữ liệu vẽ biểu đồ heatmap matrix

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species setosa versicolor virginica

5.071429 5.825714 6.54

3.517143 2.748571 2.962857

1.471429 4.182857 5.525714

0.251429 1.311429 1.988571

1 2

sns.heatmap(df_summary)

Vẽ biểu đồ heatmap thể hiện tương quan giữa độ lớn của giá trị trung bình theo màu sắc.

Hình 5.27: Đồ thị heatmap theo màu sắc.

1 2

sns.heatmap(df_summary, annot=True)

Trong trường hợp, chúng ta muốn thể hiện con số trên biểu đồ thì dùng thêm annot=True. Như vậy nhìn vào biểu đồ ta có thể thấy Virginica là loài hoa có Sepal.Length và Petal.Length rất cao thể hiện qua màu sắc rất sáng. Sentosa thì có kích thước Petal.Length và Petal.Width khá nhỏ. Versicolor thì có độ dài Petal.Length và Sepal.Length cao nhưng Petal.Width và Sepal.Width thấp, điều này chứng tỏ một kiến trúc dẹt của giống hoa này.

5.2 Phát triển các ứng dụng cơ bản với Python 269

5.2.2.4 Vẽ nhiều biểu đồ con trên một biểu đồ

Hình 5.28: Đồ thị heatmap với trục số liệu theo màu sắc.

1 2

import matplotlib.pyplot as plt fg, ax = plt.subplots(2, 2, figsize=(16, 12)) # Khoi tao grid matrix

Trong các báo cáo và phân tích nhiều tình huống đòi hỏi chúng ta cần đưa ra thông tin từ nhiều biểu đồ liên quan. Do đó ta cần thể hiện nhiều biểu đồ trên cùng một đồ thị để dễ đối chiếu và kết luận. Matplotlib cho phép chúng ta vẽ các biểu đồ con trên cùng một biểu đồ thông qua một grid matrix.

Hình 5.29: Vẽ nhiều biểu đồ con.

# Thống kê số lượng loài hoa x1, y1 = np.unique(df_iris[’Species’], return_counts=True) # Sepal.Length and Sepal.Width x2, y2 = df_iris[’Sepal.Length’].values, df_iris[’Sepal.Width’].values

1 2 3 4

#Khởi tạo grid matrix fg, ax = plt.subplots(2, 2, figsize=(16, 12))

1 2

Như vậy lưới ma trận này sẽ giúp xác định có bao nhiêu biểu đồ con nằm trong nó. Trong ví dụ này chúng ta đã xác định plt.subplots(row, height) để tạo ra ma trận biểu đồ kích thước 2x2 (số dòng trước, cột sau). figsize chính là kích thước cho toàn bộ biểu đồ cha. Để truy cập vào một biểu đồ con thì chúng ta truy cập như đối với mảng trong numpy.

3 4 5 6 7 8 9 10 11 12 13 14 15 16

# Visualize từng biểu đồ Biểu đồ [0, 0] ax[0, 0].pie(y1, labels=x1, autopct=’%1.1f%%’) ax[0, 0].set_xlabel("Ty le % cac loai hoa", fontsize=12) # Biểu đồ [0, 1] sns.heatmap(df_summary, annot=True, ax=ax[0, 1]) ax[0, 1].set_xlabel(’Trung bình các measurements’, fontsize=12) # Biểu đồ [1, 0] ax[1, 0].scatter(x2, y2) ax[1, 0].set_xlabel(’Sepal.Length’, fontsize=12) ax[1, 0].set_ylabel(’Sepal.Width’, fontsize=12) # Biểu đồ [1, 1] sns.swarmplot(data=df_iris, x=’Species’, y=’Sepal.Width’, ax=ax[1, 1]) ax[1, 1].set_xlabel(’Chiều rộng đài hoa’, fontsize=12) fg.suptitle(’Biểu đồ Tổng hợp’, fontsize=18)

Chương 5. Phát triển ứng dụng với Python 270

5.2.2.5 Vẽ biểu đồ động từ gif file

Hình 5.30: Vẽ biểu đồ tổng hợp.

1 2 3 4

import numpy as np import matplotlib.pyplot as plt import imageio import os

Chúng ta thường dùng biểu đồ gif trong matplotlib để biểu diễn kết quả của những thuật toán một cách trực quan. Ví dụ như biểu diễn sự di chuyển của các điểm theo gradient descent, chúng ta cần import các thư viện cần thiết.

5.2 Phát triển các ứng dụng cơ bản với Python 271

def animate(i):

1 2 3 4

x = np.linspace(0, 2, 1000) y = np.sin(2 * np.pi * (x - 0.01 * i)) return x, y

Khởi tạo một hàm số có đồ thị dạng sin theo công thức: y = sin(2π(x − 0.01i))

def plot(i):

1 2 3 4 5 6 7 8 9

x, y = animate(i) fig = plt.figure(figsize=(8, 6)) plt.plot(x, y) plt.xlabel(’x’) plt.ylabel(’y’) plt.title("iteration {}".format(i)) fig.savefig("gifplot/{:03d}.png".format(i)) plt.close(fig)

Tiếp theo ta sẽ sinh các chuỗi dữ liệu (x,y) thay đổi theo giá trị của i và lưu những đồ thị này vào folder gifplot

for i in range(20):

1 2

plot(i)

Thực hiện vòng for vẽ liên tiếp 20 vòng lặp cho i

with imageio.get_writer(’mygif.gif’, mode=’I’) as writer:

for filename in os.listdir(’gifplot’):

1 2 3 4

image = imageio.imread(’gifplot/{}’.format(filename)) writer.append_data(image)

Bản chất của file gif là một tập hợp các file ảnh thường được xếp chồng lên nhau. Do đó để tạo ra được một ảnh động gif thì chúng ta sẽ append các ảnh vào trong writer của imageio.

1 2

from IPython.display import Image Image(open(’mygif.gif’,’rb’).read())

Như vậy toàn bộ các file ảnh đã được lưu theo thứ tự của vòng lặp vào file mygif.gif. Chúng ta có thể hiển thị đồ thị vừa được tạo ra như sau:

5.2.3.1 Thư viện Pillow

5.2.3 Projec 3. Xử lý hình ảnh với thư viện Pillow

Pilow là một phần của thư viện PIL (Python Image Libary) của Python được sử dụng để xử lý hình ảnh. So với PIL thì Pillow được cập nhật thường xuyên và đánh giá cao hơn. Pillow và PIL không thể cùng tồn tại trong cùng một môi trường, trước khi cài Pillow hãy xóa PIL. Pillow có thể mở và lưu hình ảnh, xử lý đặc điểm của hình ảnh, chẳng hạn như màu sắc, độ mờ, độ sáng, tối,... Pillow hỗ trợ xử lý nhiều tệp hình ảnh khác nhau như PDF, WebP, PCX, PNG, JPEG, GIF, PSD, WebP, PCX, GIF, IM, EPS, ICO, BMP. Chúng ta có thể dễ dàng tạo ra những ảnh thu nhỏ (thumbnails) cho hình ảnh mang hầu hết đặc điểm của hình ảnh và gần như không khác gì ảnh gốc ngoại trừ chúng được thu nhỏ lại. Bên cạnh đó, Pillow còn hỗ

Chương 5. Phát triển ứng dụng với Python 272

5.2.3.2 Sử dụng class Image

trợ một bộ sưu tập các bộ lọc hình ảnh như: FIND_EDGES, DETAIL, SMOOTH, BLUR, CONTOUR, SHARPEN, SMOOTH_MORE. Chúng ta có thể tải và cài đặt Pilow tại đây: https://pypi.org/project/Pillow/

1

>>> from PIL import Image

Chúng ta có thể sử dụng thẳng Python từ trong shell. Sau khi đã cài môi trường và thư viện Pillow, ta mở shell và gõ trực tiếp lệnh import thư viện PIL như sau:

1

>>> img = Image.open("the_catch.jpg")

Để mở và load ảnh trong thư mục hiện tại sử dụng lệnh:

1 2

>>> print(f"format:{img.format},size:{img.size},mode:{img.mode},name:{img.filename}") format: JPEG, size: (1000, 800), mode: RGB, name: the_catch.jpg

Khi đã có 1 Instance của class Image, chúng ta có thể xem các thông tin về ảnh bằng cách truy cập thuộc tính của nó.

1

>>> dir(img)

Để truy cập toàn bộ các thuộc tính của img, gõ lệnh:

1

>>> img.show()

5.2.3.3 Đọc và ghi ảnh

Nếu muốn hiển thị ảnh đã có, ta sử dụng phương thức show:

>>> try:

new_img_name = "the_catch.png" img.save(new_img_name)

except IOerror:

print("Cannot convert file")

1 2 3 4 5 6 7 8

>>> new_img = Image.open("the_catch.png") >>> new_img

Chúng ta không cần phải truyền vào dạng ảnh vì Pillow tự biết phân biệt các loại ảnh khác nhau. Muốn đọc ảnh bạn chỉ cần gọi hàm open của class Image. Nếu phần mở rộng (extension) của file ảnh của bạn là một trong những đuôi thông dụng, thì không cần phải cụ thể hóa đuôi file, Pillow sẽ lưu file ảnh mới theo đuôi của ảnh cũ. Nếu muốn đổi đuôi file ảnh, ta hàm save và truyền vào nó tên file kèm theo đuôi mà mình muốn.

>>> size = (256, 256) >>> try:

1 2 3 4

new_thumbnail = "the_catch_thumbnail.png" with Image.open("the_catch.png") as im:

Chúng ta có thể tạo 1 file thumbnail kích cỡ 256 × 256 bằng cách gọi hàm thumbnail như sau:

im.thumbnail(size) im.save(new_thumbnail, "PNG")

except IOError:

5 6 7 8

print("Cannot create thumbnail")

5.2.3.4 Cắt dán và ghép ảnh

5.2 Phát triển các ứng dụng cơ bản với Python 273

1 2 3 4

>>> box = (120, 120, 360, 360) >>> region = im.crop(box) >>> region

Để cắt một khu trong ảnh ta sử dụng hàm crop. Cách làm là bạn truyền vào 1 tuple gồm 4 tọa độ. Vị trí các toạ độ lần lượt là (trái, trên, phải, dưới ). Lưu ý là Pillow dùng hệ tọa độ (0, 0) từ góc trên bên trái, và các tọa độ này chỉ đến vị trí giữa các pixel.

1 2 3 4

>>> region = region.transpose(Image.ROTATE_180) >>> region.show() >>> img.paste(region, box) >>> img.show()

Phần được cắt ra đã được lưu trong biến region, ta có thể xử lý và dán nó lại.

def merge(im1: Image.Image, im2: Image.Image) -> Image.Image:

1 2 3 4 5 6 7

w = im1.size[0] + im2.size[0] h = max(im1.size[1], im2.size[1]) im = Image.new("RGBA", (w, h)) im.paste(im1) im.paste(im2, (im1.size[0], 0)) return im

5.2.3.5 Biến đổi hình học, màu sắc, chuyển đổi định dạng ảnh

Để ghép 2 bước ảnh với nhau, chúng ta thực hiện như sau:

1 2

>>> resized_img = img.resize((128, 128)) >>> resized_img.show()

Chúng ta có thể thay đổi lại kích thước ảnh với hàm resize

1 2

>>> rotated_img = img.rotate(90) >>> rotated_img.show()

Để xoay ảnh, chúng ta sử dụng hàm rotate. (Lưu ý, Pillow xẽ xoay ảnh theo chiều ngược kim đồng hồ).

1 2

>>> converted_img = img.convert("L") >>> converted_img.show()

Để biến đổi màu, chúng ta sử dụng hàm convert. Pillow có thể chuyển giữa 2 chế độ màu thông dụng là đen trắng (L) và có màu (RGB). Nếu muốn chuyển sang chế độ màu khác bạn sẽ phải dùng một hình ảnh trung gian (thường là ảnh RGB).

Chương 5. Phát triển ứng dụng với Python 274

1 2 3

>>> r, g, b = img.split() >>> changed_img = Image.merge("RGB", (r, b, g)) >>> changed_img.show()

Với các ảnh RGB, ảnh được phân thành các tầng màu (band). Chúng ta có thể tách các tầng màu này ra, chỉnh sửa và sắp xếp lại chúng rồi nhập lại vào hình ảnh.

import os, sys from PIL import Image size = (128, 128) for infile in sys.argv[1:]:

outfile = os.path.splitext(infile)[0] + ".thumbnail" if infile != outfile:

try:

with Image.open(infile) as im:

im.thumbnail(size) im.save(outfile, "JPEG")

except OSError:

1 2 3 4 5 6 7 8 9 10 11 12

print("cannot create thumbnail for", infile)

Để chuyển đổi định dạng file ảnh chúng ta thực hiện như sau:

5.2.4.1 Thư viện Requests

5.2.4 Projec 4. Xử lý yêu cầu http với thư viện Requests

Requests là một thư viện HTTP vô cùng phong phú và đa dạng được cấp phép hoạt động theo giấy phép Apache 2.0. Requests được tạo ra nhằm mục đích tập trung vào các yêu cầu HTTP, giúp đáp ứng nhanh hơn và thân thiện hơn với người dùng. Thư viện Python này thực sự rất dễ dàng cho người mới bắt đầu vì nó cho phép sử dụng hầu hết các phương thức phổ biến của HTTP. Bạn có thể dễ dàng tùy chỉnh, kiểm tra, ủy quyền và định cấu hình các yêu cầu HTTP bằng thư viện này, ngoài ra, chúng ta còn có thể trích xuất HTML của bất kỳ trang web nào từ URL tương ứng.

Hình 5.31: Thư viện http - Requests

5.2 Phát triển các ứng dụng cơ bản với Python 275

Sử dụng từ điển Python cơ bản trong Requests, chúng ta có thể thêm các tham số, tiêu đề, multi-part file và dữ liệu biểu mẫu với rất nhiều tính năng cho phép xử lý các tiêu đề tùy chỉnh, xác minh chứng chỉ SSL và quét các tham số về URL. Với Requests, chúng ta có thể dễ dàng tải lên nhiều tệp cùng một lúc, cho phép làm việc trong một môi trường nhanh hơn và hiệu quả hơn. Requests có tính năng giải nén tự động cho phép bạn khôi phục và phục hồi dữ liệu đã nén thành dạng xác thực của nó ngay lập tức. Với việc hỗ trợ proxy HTTP với Requests cho phép người dùng truy cập nhanh hơn và đơn giản hơn đến các tệp và trang web. Requests cũng có các cookie giá trị, cơ quan phản hồi Unicode, xác thực Basic/Digest, an toàn luồng, tổng hợp kết nối. Để tải và cài đặt Requests, truy cập địa chỉ sau: https://pypi.org/project/requests/.

5.2.4.2 Tạo và xử lý yêu cầu GET

Để cài đặt, chúng ta thực hiện lệnh sau đây trong terminal: pip install requests

Rất dễ dàng để gửi một yêu cầu HTTP bằng Requests.Chúng ta bắt đầu bằng cách import module và sau đó thực hiện yêu cầu như sau:

1 2

import requests req = requests.get(’https://dhhp.edu.vn/’)

Ví dụ 5.2.5. Gửi yêu cầu GET.

Tất cả các thông tin về yêu cầu của chúng ta bây giờ được lưu trữ trong một đối tượng Response được gọi là req. Ví dụ: Chúng ta có thể lấy mã hóa của trang web bằng thuộc tính req.encoding và lấy mã trạng thái của yêu cầu bằng thuộc tính req.status_code.

1 2

req.encoding # returns ’utf-8’ req.status_code # returns 200

Ví dụ 5.2.6. Lấy trạng thái của yêu cầu GET.

Chúng ta có thể truy cập các cookie mà máy chủ gửi lại bằng thuộc tính req.cookie. Thuộc tính req.headers trả về một dictionary chứa các header phản hồi không phân biệt chữ hoa chữ thường. Điều này có nghĩa là req.headers[’Content-Length’], req.headers[’content-length’] và req.headers[’CONTENT-LENGTH’] tất cả sẽ trả về giá trị của header phản hồi ’Content-Length’.

Để kiểm tra xem phản hồi có phải là một redirect HTTP đúng ngữ pháp đã được xử lý tự động, ta sử dụng thuộc tính req.is_redirect. Thuộc tính này trả về True hay False dựa trên phản hồi. Để lấy được thời gian trôi qua giữa gửi yêu cầu và nhận lại phản hồi , ta sử dụng thuộc tính req.elapseed.

URL truyền cho hàm get() có thể khác với URL sau cùng của phản hồi vì nhiều lý do, kể cả redirect. Để xem URL phản hồi sau cùng ta sử dụng thuộc tính req.url.

Ví dụ 5.2.7. Xem URL phản hồi dùng get.

1 2 3 4 5 6 7 8 9 10

import requests req = requests.get(’http://www.tutsplus.com/’) req.encoding # returns ’utf-8’ req.status_code # returns 200 req.elapsed # returns datetime.timedelta(0, 1, 666890) req.url # returns ’https://tutsplus.com/’ req.history # returns [, ] req.headers[’Content-Type’] # returns ’text/html; charset=utf-8’

Chương 5. Phát triển ứng dụng với Python 276

Để nhận tất cả các thông tin này về trang web đang truy cập, nếu nội dung truy cập là văn bản, chúng ta có thể sử dụng thuộc tính req.text để truy xuất thông tin. Nội dung sẽ được phân tích thành unicode, để truyền mã hoá để giải mã văn bản chúng ta sử dụng thuộc tính req.encoding. Trong trường hợp phản hồi không phải là văn bản mà ở dạng nhị phân, ta sử dụng thuộc tính req.content. Thuộc tính này sẽ tự động giải mã gzip và deflate, điều này rất hữu ích khi đang xử lý các tập tin media. Tương tự, để truy cập nội dung đã được mã hóa dạng json của phản hồi, chúng ta sử dụng phương thức req.json().

Chúng ta cũng có thể lấy được phản hồi gốc từ máy chủ bằng thuộc tính req.raw nhưng phải truyền vào stream=True trong yêu cầu để có được phản hồi gốc. Một số tập tin tải xuống từ Internet sử dụng môđun Requests có thể có kích thước rất lớn. Trong những trường hợp này, không nên tải toàn bộ phản hồi hoặc tập tin vào bộ nhớ cùng một lúc. Chúng ta có thể tải xuống từng phần hoặc khối của một tập tin bằng phương thức iter_content(chunk_size = 1, decode_unicode = False). Phương thức này lặp qua dữ liệu phản hồi bằng số byte chunk_size tại một thời điểm. Khi stream=True được thiết lập trong yêu cầu, phương thức này sẽ tránh đọc toàn bộ tập tin vào bộ nhớ cùng một lúc cho các phản hồi lớn. Tham số chunk_size có thể là một số nguyên hoặc None. Khi thiết lập một giá trị số nguyên, chunk_size xác định số byte cần đọc vào bộ nhớ. Khi chunk_size được thiết lập thành None và stream được thiết lập thành True thì dữ liệu sẽ được đọc khi nó đến trong bất kỳ khối kích thước nào nhận được. Khi chunk_size được thiết lập thành None và stream được thiết lập thành False thì tất cả các dữ liệu sẽ được trả về như một khối đơn.

import requests req = requests.get(’path/to/forest.jpg’, stream=True) req.raise_for_status() with open(’Forest.jpg’, ’wb’) as fd:

for chunk in req.iter_content(chunk_size=50000):

1 2 3 4 5 6 7

print(’Received a Chunk’) fd.write(chunk)

Ví dụ 5.2.8. Tải hình ảnh khu rừng trên Pixabay bằng Requests.

Trong đó, ’path/to/forest.jpg’ là URL hình ảnh thực tế. Chúng ta có thể thiết lập URL của bất kỳ hình ảnh nào khác vào đây để tải về cái khác. Tập tin hình ảnh đó có kích

5.2 Phát triển các ứng dụng cơ bản với Python 277

thước 185kb và bạn đã thiết lập chunk_size thành 50.000 byte. Điều này có nghĩa là thông điệp "Received a Chunk" sẽ được in bốn lần trong terminal. Kích thước của khối cuối cùng sẽ chỉ là 39350 byte bởi vì phần còn lại của tập tin nhận được sau ba lần lặp đầu tiên là 39350 byte.

Requests cũng cho phép truyền các tham số trong một URL. Điều này hữu ích khi đang tìm kiếm trang web để lấy một số kết quả như hình ảnh hoặc bài hướng dẫn cụ thể. Chúng ta có thể cung cấp các chuỗi truy vấn này như là một dictionary bằng từ khóa params trong yêu cầu GET.

1 2 3 4

import requests query = {’q’:’Forest’,’order’:’popular’,’min_width’:’800’,’min_height’:’600’} req = requests.get(’https://pixabay.com/en/photos/’, params=query) req.url

5.2.4.3 Tạo và xử lý yêu cầu POST

Ví dụ 5.2.9. Tìm kiếm trang web lấy hình ảnh.

Tạo một yêu cầu POST cũng tương tự như yêu cầu GET. Bạn chỉ cần sử dụng hàm post() thay cho get(). Việc này có thể hữu ích khi bạn tự động submit các form. Ví dụ, đoạn code sau sẽ tải toàn bộ trang Wikipedia về Công nghệ Nano và lưu nó trên máy tính của bạn.

import requests req=requests.post(’https://en.wikipedia.org/w/index.php’,data={’search’:’Nanotechnology’}) req.raise_for_status() with open(’Nanotechnology.html’, ’wb’) as fd:

for chunk in req.iter_content(chunk_size=50000):

1 2 3 4 5 6

fd.write(chunk)

5.2.4.4 Gởi Cookie và Header

Ví dụ 5.2.10. Tải toàn bộ trang web Wikipedia về công nghệ nano.

Request hỗ trợ truy cập các cookie và header mà máy chủ gửi lại cho người dùng bằng req.cookies và req.headers. Requests cũng cho phép gửi các cookie và header tùy biến của riêng bạn cùng với một yêu cầu. Điều này có thể hữu ích khi ta muốn, giả sử thiết lập một user agent tùy biến cho yêu cầu của mình. Để thêm các header HTTP vào yêu cầu, chúng ta chỉ cần truyền chúng trong một dict vào tham số headers. Tương tự, để gửi cookie của riêng mình đến một máy chủ bằng cách sử dụng dict truyền vào tham số cookie.

1 2 3 4 5

import requests url = ’http://some-domain.com/set/cookies/headers’ headers = {’user-agent’: ’your-own-user-agent/0.0.1’} cookies = {’visit-month’: ’February’} req = requests.get(url, headers=headers, cookies=cookies)

Ví dụ 5.2.11. Gửi cookie đến máy chủ.

Chương 5. Phát triển ứng dụng với Python 278

Cookie cũng có thể được truyền thông qua trong một Cookie Jar. Chúng cung cấp một giao diện đầy đủ hơn để cho phép sử dụng các cookie đó trên nhiều đường dẫn.

1 2 3 4 5 6 7 8 9

import requests jar = requests.cookies.RequestsCookieJar() jar.set(’first_cookie’, ’first’, domain=’httpbin.org’, path=’/cookies’) jar.set(’second_cookie’, ’second’, domain=’httpbin.org’, path=’/extra’) jar.set(’third_cookie’, ’third’, domain=’httpbin.org’, path=’/cookies’) url = ’http://httpbin.org/cookies’ req = requests.get(url, cookies=jar) req.text # returns ’{ "cookies": { "first_cookie": "first", "third_cookie": "third" }}’

5.2.4.5 Các đối tượng Session

Ví dụ 5.2.12. Gửi cookie đến máy chủ.

Đôi khi cần phải giữ nguyên các tham số nhất định trên nhiều yêu cầu. Đối tượng Session xử lý chính xác điều đó. Ví dụ, nó sẽ giữ dữ liệu cookie trên tất cả các yêu cầu được thực hiện bằng cùng một session. Đối tượng Session sử dụng connection-pooling của urllib3. Điều này có nghĩa là kết nối TCP bên dưới sẽ được sử dụng lại cho tất cả các yêu cầu được thực hiện đến cùng một máy chủ. Điều này có thể gia tăng đáng kể hiệu suất. Bạn cũng có thể sử dụng các phương thức của đối tượng Requests với đối tượng Session. Xét ví dụ về nhiều yêu cầu được gửi bằng cách sử dụng và không sử dụng session:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

import requests reqOne = requests.get(’https://tutsplus.com/’) reqOne.cookies[’_tuts_session’] #returns ’cc118d94a84f0ea37c64f14dd868a175’ reqTwo = requests.get(’https://code.tutsplus.com/tutorials’) reqTwo.cookies[’_tuts_session’] #returns ’3775e1f1d7f3448e25881dfc35b8a69a’ ssnOne = requests.Session() ssnOne.get(’https://tutsplus.com/’) ssnOne.cookies[’_tuts_session’] #returns ’4c3dd2f41d2362108fbb191448eab3b4’ reqThree = ssnOne.get(’https://code.tutsplus.com/tutorials’) reqThree.cookies[’_tuts_session’] #returns ’4c3dd2f41d2362108fbb191448eab3b4’

Ví dụ 5.2.13. Gửi nhiều yêu cầu không sử dụng session.

Trong ví dụ trên, cookie session có một giá trị khác nhau trong yêu cầu thứ nhất và thứ hai, nhưng nó có cùng giá trị khi chúng ta sử dụng đối tượng Session. Chúng ta sẽ nhận được một giá trị khác khi chạy thử đoạn code này, tương tự cookie cho các yêu cầu được thực hiện bằng cách sử dụng đối tượng Session sẽ có cùng giá trị. Session hữu ích khi muốn gửi dữ liệu tương tự trên tất cả các yêu cầu. Ví dụ, nếu quyết định gửi một cookie hoặc một header user-agent với tất cả các yêu cầu đến một tên miền nhất định, chúng ta có thể sử dụng các đối tượng Session.

5.2 Phát triển các ứng dụng cơ bản với Python 279

1 2 3 4 5 6 7 8 9 10 11 12

import requests ssn = requests.Session() ssn.cookies.update({’visit-month’: ’February’}) reqOne = ssn.get(’http://httpbin.org/cookies’) print(reqOne.text) # prints information about "visit-month" cookie reqTwo = ssn.get(’http://httpbin.org/cookies’, cookies={’visit-year’: ’2017’}) print(reqTwo.text) # prints information about "visit-month" and "visit-year" cookie reqThree = ssn.get(’http://httpbin.org/cookies’) print(reqThree.text) # prints information about "visit-month" cookie

Ví dụ 5.2.14. Gửi nhiều yêu cầu sử dụng session.

Lúc này, cookie session "visit-month" được gửi cùng với cả ba yêu cầu. Tuy nhiên, cookie "visit-year" chỉ được gửi trong yêu cầu thứ hai. Còn chưa đề cập đến cookie "vist-year" trong yêu cầu thứ ba. Điều này xác nhận thực tế rằng cookie hoặc tập dữ liệu khác trên các yêu cầu riêng lẻ sẽ không được gửi cùng với các yêu cầu session khác.

5.2.5.1 Thư viện Fire

5.2.5 Projec 5. Tạo giao diện dòng lệnh với thư viện Fire

Thư viện tạo giao diện dòng lệnh (Fire) là một thư viện python mã nguồn mở tự động tạo CLI (giao diện dòng lệnh). Thông thường, nếu muốn tạo ra một giao diện dòng lệnh sẽ rất tốn thời gian và công sức, tuy nhiên, với Fire chúng ta sẽ chỉ cần một vài dòng code ngắn gọn là có thể tạo được một giao diện có đầy đủ chức năng và hiệu suất cao. Fire là một thư viện mạnh mẽ có thể lấy CLI từ bất kỳ đối tượng Python nào. Fire cũng được Google sử dụng để tạo dòng lệnh và các công cụ quản lý thử nghiệm khác nhau.

Hình 5.32: Thư viện tạo giao diện dòng lệnh - Fire

Các đối tượng Python mà Fire có thể hoạt động là môđun, đối tượng, lớp, danh sách, dicts. Các CLI được tạo bằng Fire có thể tương thích với bất kỳ thay đổi nào mỗi khi ta thay đổi mã nguồn. CLI ở dạng hoàn chỉnh với các trang trợ giúp tự động, hoàn thành tab và trong một hệ thống tương tác rất tốt. CLI là một thư viện rất đơn giản có thể viết và gửi lệnh tại một phiên bản bằng cú pháp gọi Fire(). Fire đi kèm với một đầu ra tuyến tính. Khi bạn sử dụng Fire,

Chương 5. Phát triển ứng dụng với Python 280

5.2.5.2 Cài đặt và tạo CLI

chúng ta không cần tới bất kỳ chuỗi docstrings nào. Để tải và cài đặt Fire truy cập địa chỉ sau: https://github.com/google/python-fire

1 2 3

pip install fire import fire fire.Fire(function_name)

Để cài đặt thư viện Fire chúng ta sử dụng lệnh sau:

Cách dễ nhất để sử dụng Fire là lấy bất kỳ chương trình Python nào, sau đó chỉ cần gọi fire.Fire() ở cuối chương trình. Điều này sẽ hiển thị toàn bộ nội dung của chương trình cho dòng lệnh.

import fire def hello(name="world"):

return "Hello " + name + "!"

if __name__== ’__main__’: fire.Fire(hello)

# Fire now creates a CLI for our program as shown below. > hello # Hello world! > hello @My_Name # Hello @My_Name! > hello --name=WWC # Hello WWC!

1 2 3 4 5 6 7 8 9

5.2.5.3 Sử dụng đa dòng lệnh - Multiple Commands

Ví dụ 5.2.15. Tạo dòng chữ Hello World.

Chúng ta hãy xem một ví dụ đơn giản về máy tính bao gồm các phương thức cộng và nhân, mỗi phương thức có hai đối số và lần lượt tính tổng và tích.

import fire class Calculator(object):

def add(self,x,y): return x + y

def multiply(self,x,y):

return x * y

if __name__== ’__main__’:

fire.Fire(Calculator)

> calculator add 1 2 # 3 > calculator multiply 3 4 # 12 > calculator Usage: calculator add

1 2 3 4 5 6 7 8 9 10 11 12 13

calculator multiply

Ví dụ 5.2.16. Sử dụng đa dòng lệnh.

Fire sẽ tạo ra một CLI, từ đó chúng ta có thể chạy nhiều lệnh bao gồm kiểm tra lớp, thêm và nhân các hàm.

5.2.5.4 Sử dụng lệnh phân cấp - Hierarchical Commands

5.2 Phát triển các ứng dụng cơ bản với Python 281

Trong đoạn mã sau, chúng ta có một lớp Tools, khi được khởi tạo sẽ lần lượt khởi tạo các lớp Calculator và Widget.

import fire class Tools(object):

def __init__(self):

self.calculator = Calculator() self.widget = Widget()

if __name__== ’__main__’: fire.Fire(Tools)

1 2 3 4 5 6 7 8 9 10 11 12 13 14

# The CLI that Fire generates looks allows us to access the respective classes # and class methods > tools calculator add 1 2 # 3 > tools calculator multiply 3 4 # 12 > tools Usage: tools calculator tools widget

5.2.5.5 Gỡ lỗi và phát triển, khám phá các dự án Python của bên thứ ba

Ví dụ 5.2.17. Sử dụng lệnh phân cấp.

Thư viện Python Fire thực sự rất hữu ích trong việc gỡ lỗi và phát triển, nơi chúng ta có thể tiếp tục và gọi fire.Fire() trên bất kỳ tập lệnh Python nào mà không cần bất kỳ đối số nào và sử dụng trong dòng lệnh.

Ngoài ra còn có tùy chọn sử dụng cờ ’tương tác’, như được hiển thị bên dưới, nhập các đối tượng hữu ích và cho phép chúng ta sử dụng trực tiếp chúng từ shell IPython mà không cần phải nhập các môđun, lệnh gọi hàm,...

1 2 3 4 5 6 7

> calc -- --interactive Fire is starting Python REPL with the following objects: Modules: fire Objects: Calculator, calc, component, result, trace IPython -- An enhanced Interactive Python [1]: calc.add(1,2) [2]: calc.multiply(3,4)

Ví dụ 5.2.18. Sử dụng lệnh phân cấp.

Cũng như các ví dụ đã giải thích ở trên, chúng ta cũng có thể gọi fire.Fire() trên các môđun của bên thứ ba mà không nhất thiết phải có quyền truy cập vào mã nguồn. Trong bản phát hành mới nhất của fire, chúng ta có thể trực tiếp gọi python -m fire từ dòng lệnh.

Xét ví dụ với thư viện xử lý hình ảnh PIL. Giả sử chúng ta có một tập lệnh Python imagefire.py với các dòng sau và chúng ta muốn mở một hình ảnh giraffe.png và thực hiện một số thao tác trên hình ảnh.

Ví dụ 5.2.19. Khám phá các dự án Python của bên thứ ba.

1 2 3 4

from PIL import Image import fire fire.Fire(Image) > imagefire.py open giraffe.png - convert L - resize 100,100 - save giraffe_out.png

Chương 5. Phát triển ứng dụng với Python 282

1 2

# NEW release of Fire > python -m fire PIL.Image open giraffe.png -convert L -resize 100,100 -save giraffe_out.png

Đoạn mã trên mở hình ảnh, chuyển đổi sang thang độ xám, thay đổi kích thước theo kích thước đã chỉ định, sau đó lưu hình ảnh kết quả dưới tên giraffe_out.png. Bản phát hành gần đây của fire cho phép chúng ta thực hiện điều tương tự dễ dàng hơn nhiều!

5.3 Phát triển các ứng dụng quản lý với Python

5.3.1 Kết nối và truy vấn cơ sở dữ liệu trong Python

Lập trình cơ sở dữ liệu (Database Programming) trong Python là quá trình sử dụng ngôn ngữ lập trình Python để tương tác, thao tác và quản lý cơ sở dữ liệu. Các tác vụ trong lập trình cơ sở dữ liệu bao gồm việc kết nối đến cơ sở dữ liệu, truy vấn dữ liệu, thêm, sửa đổi và xóa dữ liệu, cũng như thực hiện các thao tác khác liên quan đến quản lý dữ liệu. Với tính linh hoạt và khả năng thao tác dữ liệu mạnh mẽ, Python là một công cụ hữu ích cho việc kết nối và làm việc với các cơ sở dữ liệu khác nhau. Trong phần này, chúng ta sẽ tìm hiểu về cách kết nối Python với các cơ sở dữ liệu thông qua các ví dụ về MySQL, MongoDB, SQL Server và PostgreSQL.

5.3.1.1 Kết nối và truy vấn cơ sở dữ liệu MySQL trong Python

Trước khi đi vào chi tiết cách kết nối Python với các cơ sở dữ liệu, chúng ta cần hiểu cơ bản về quá trình kết nối này. Khi làm việc với dữ liệu, cần phải có một giao diện để truy xuất và thao tác với dữ liệu đó. Trong trường hợp này, chúng ta sử dụng các giao diện (drivers) để kết nối và truy vấn dữ liệu từ các cơ sở dữ liệu khác nhau. Với Python, có thể sử dụng các giao diện này thông qua các module và thư viện như mysql.connector, pymongo, pyodbc và psycopg2. Mỗi module hỗ trợ giao diện để kết nối với một loại cơ sở dữ liệu cụ thể. Bằng cách sử dụng các giao diện này, chúng ta có thể tạo kết nối và thực hiện các câu lệnh SQL hoặc các truy vấn để lấy và xử lý dữ liệu.

MySQL là một cơ sở dữ liệu quan hệ mã nguồn mở phổ biến được sử dụng trong nhiều ứng dụng web và khoa học dữ liệu. Để kết nối Python với MySQL, chúng ta có thể sử dụng module mysql.connector như sau:

1

import mysql.connector

Cài đặt và import module mysql.connector: Trước tiên, chúng ta cần cài đặt module mysql.connector bằng lệnh pip install mysql-connector-python trong Command line hoặc Terminal. Sau khi cài đặt thành công, chúng ta import module này vào trong code Python của mình như sau:

5.3 Phát triển các ứng dụng quản lý với Python 283

mydb = mysql.connector.connect(

1 2 3 4

host="localhost", user="username", passwd="password")

Thiết lập kết nối: Để thiết lập một kết nối đến cơ sở dữ liệu MySQL, chúng ta cần cung cấp các thông tin như tên máy chủ, tên người dùng và mật khẩu. Các thông tin này được sử dụng để xác thực và thiết lập kết nối đến cơ sở dữ liệu. Chúng ta có thể sử dụng hàm connect() của module mysql.connector để thiết lập kết nối như sau:

1 2

mycursor = mydb.cursor() mycursor.execute("CREATE TABLE customers (name VARCHAR(255), address VARCHAR(255))")

Thực hiện các câu lệnh SQL: Sau khi đã thiết lập kết nối thành công, chúng ta có thể sử dụng đối tượng mydb để thực hiện các câu lệnh SQL. Ví dụ, để tạo một bảng mới trong cơ sở dữ liệu, chúng ta có thể sử dụng câu lệnh CREATE TABLE như sau:

5.3.1.2 Kết nối và truy vấn cơ sở dữ liệu MongoDB trong Python

Lưu ý rằng chúng ta phải sử dụng hàm cursor() để tạo một đối tượng cursor, từ đó có thể thực hiện các câu lệnh SQL. Sau khi tạo bảng, chúng ta có thể thêm và lấy dữ liệu từ bảng đó bằng cách sử dụng các câu lệnh như INSERT và SELECT.

MongoDB là một cơ sở dữ liệu phi quan hệ (NoSQL) phổ biến được sử dụng trong các ứng dụng web, đặc biệt là khi làm việc với dữ liệu phi cấu trúc. Để kết nối Python với MongoDB, chúng ta có thể sử dụng module pymongo như sau:

1

import pymongo

Cài đặt và import module pymongo: Giống như việc kết nối với MySQL, chúng ta cần cài đặt module pymongo bằng lệnh pip install pymongo và import module này vào code Python của mình:

1 2

myclient = pymongo.MongoClient("mongodb://localhost:27017/") mydb = myclient["mydatabase"]

Thiết lập kết nối: Để thiết lập kết nối đến cơ sở dữ liệu MongoDB, chúng ta cần cung cấp thông tin như đường dẫn đến máy chủ và tên database. Các thông tin này được sử dụng để xác thực và thiết lập kết nối đến cơ sở dữ liệu. Chúng ta có thể sử dụng hàm MongoClient() của module pymongo để thiết lập kết nối như sau:

1 2 3

mycol = mydb["customers"] mydict = { "name": "John", "address": "Highway 37" } x = mycol.insert_one(mydict)

Thực hiện các truy vấn: Có thể sử dụng các truy vấn để thêm, sửa đổi và truy xuất dữ liệu. Ví dụ, để tạo mt collection mới trong database, chúng ta có thể sử dụng hàm insert_one() như sau:

Lưu ý rằng chúng ta cần tạo một đối tượng mycol bằng cách gọi hàm [] trên đối tượng mydb. Sau đó, chúng ta có thể sử dụng các phương thức của đối tượng này để thực hiện các truy vấn.

5.3.1.3 Kết nối và truy vấn cơ sở dữ liệu SQL Server trong Python

Chương 5. Phát triển ứng dụng với Python 284

1

import pyodbc

SQL Server là một cơ sở dữ liệu quan hệ được phát triển bởi Microsoft và được sử dụng rộng rãi trong các hệ thống doanh nghiệp. Python cũng có thể kết nối với SQL Server thông qua module pyodbc. Cài đặt và import module pyodbc: Để kết nối Python với SQL Server, chúng ta cần cài đặt module pyodbc bằng lệnh pip install pyodbc và import module này vào code:

mydb = pyodbc.connect(’DRIVER={SQL Server}; SERVER=server_name;

DATABASE=database_name; UID=username;PWD=password’)

1 2

Thiết lập kết nối: Tương tự các cách kết nối với MySQL và MongoDB, chúng ta cần cung cấp thông tin xác thực và tên database cho SQL Server. Chúng ta có thể sử dụng hàm connect() của module pyodbc để thiết lập kết nối như sau:

1 2

mycursor = mydb.cursor() mycursor.execute("CREATE TABLE customers (name VARCHAR(255), address VARCHAR(255))")

Thực hiện các câu lệnh SQL: Sau khi đã thiết lập kết nối thành công, chúng ta có thể sử dụng đối tượng mydb để thực hiện các câu lệnh SQL. Ví dụ, để tạo một bảng mới trong SQL Server, chúng ta có thể sử dụng câu lệnh CREATE TABLE như sau:

5.3.1.4 Kết nối và truy vấn cơ sở dữ liệu PostgreSQL trong Python

Lưu ý rằng chúng ta cũng phải sử dụng hàm cursor() để tạo một đối tượng cursor trước khi thực hiện các câu lệnh SQL.

PostgreSQL là một cơ sở dữ liệu quan hệ mã nguồn mở được sử dụng rộng rãi trong các ứng dụng web và khoa học dữ liệu. Chúng ta cũng có thể kết nối Python vi PostgreSQL thông qua module psycopg2. Cài đặt và import module psycopg2: Để kết nối Python với PostgreSQL, chúng ta cần cài

1

import psycopg2

đặt module psycopg2 bằng lệnh pip install psycopg2-binary hoặc pip install psycopg2, tùy vào phiên bản Python của bạn. Sau đó, import module này vào code:

mydb = psycopg2.connect( host="localhost", user="username",

password="password", database="database_name")

1 2

Thiết lập kết nối: Để thiết lập kết nối đến cơ sở dữ liệu PostgreSQL, cần cung cấp các thông tin xác thực và tên database. Có thể sử dụng hàm connect() của module psycopg2 để thiết lập kết nối như sau:

1 2

mycursor = mydb.cursor() mycursor.execute("CREATE TABLE customers (name VARCHAR(255), address VARCHAR(255))")

Thực hiện các câu lệnh SQL: Sau khi đã thiết lập kết nối thành công, có thể sử dụng đối tượng mydb để thực hiện các câu lệnh SQL. Ví dụ, để tạo một bảng mi trong PostgreSQL, chúng ta có thể sử dụng câu lệnh CREATE TABLE như sau:

5.3 Phát triển các ứng dụng quản lý với Python 285

5.3.1.5 Kết nối và truy vấn cơ sở dữ liệu SQLite trong Python

Lưu ý rằng chúng ta cũng phải sử dụng hàm cursor() để tạo một đối tượng cursor trước khi thực hiện các câu lệnh SQL.

Python cung cấp môđun sqlite3, một driver tương thích với DB-API để làm việc với SQLite. Đây là một cơ sở dữ liệu nhẹ, không cần máy chủ, lý tưởng cho các ứng dụng nhỏ. Đối với các hệ quản trị cơ sở dữ liệu khác, cần sử dụng các gói Python phù hợp.

Sử dụng module sqlite3 có sẵn trong Python: Python cung cấp môđun sqlite3 tích hợp sẵn để làm việc với SQLite, giúp dễ dàng quản lý cơ sở dữ liệu mà không cần cài đặt thêm phần mềm. Thiết lập kết nối (Connection Establishment): Dùng sqlite3.connect("tên_file.db")

để kết nối đến database SQLite. Nếu file chưa tồn tại, SQLite sẽ tự động tạo mới. Quản lý Transaction: Kết nối (conn) giúp kiểm soát giao dịch, bao gồm: • commit() – Lưu thay đổi vào database. • rollback() – Hoàn tác nếu có lỗi xảy ra. • close() – Đóng kết nối sau khi hoàn tất công việc. Cursor Object: Đối tượng cursor (conn.cursor()) giúp gửi lệnh SQL và truy xuất kết quả từ database. Chúng ta sẽ xem xét cách truy cập cơ sở dữ liệu bằng Python, lưu trữ dữ liệu trong SQLite và truy xuất dữ liệu để xử lý trong chương trình Python.

Tạo kết nối bằng sqlite3.connect(): SQLite là một hệ quản trị cơ sở dữ liệu quan hệ nhẹ, hỗ trợ giao dịch ACID và không yêu cầu server. Cơ sở dữ liệu được lưu trữ trong một file đơn lẻ, giúp dễ dàng quản lý và triển khai. Python tích hợp sẵn môđun sqlite3, nên bạn có thể làm việc với SQLite mà không cần cài đặt thêm phần mềm. Môđun sqlite3 của Python cung cấp triển khai DB-API cho SQLite, được viết bởi Gerhard H¨aring. Hãy cùng tìm hiểu cách sử dụng sqlite3 để truy cập cơ sở dữ liệu trong Python.

1 2

import sqlite3 print(sqlite3.sqlite_version)

Ví dụ 5.3.1. Kiểm tra phiên bản SQLite được tích hợp trong Python.

Chúng ta có thể kết nối đến SQLite bằng sqlite3.connect("database.db"), trong đó "database.db" là file chứa dữ liệu. Nếu file chưa tồn tại, SQLite sẽ tự động tạo mới.

Connection Object: Đối tượng kết nối (Connection) trong SQLite được tạo bằng hàm connect() của môđun sqlite3. Đối số đầu tiên của hàm là một chuỗi đại diện cho đường dẫn (tương đối hoặc tuyệt đối) đến tệp cơ sở dữ liệu SQLite. Nếu tệp chưa tồn tại, SQLite sẽ tự động tạo mới.

1 2

import sqlite3 # Tạo kết nối đến database file

Ví dụ 5.3.2. Tạo kết nối đến database file.

3 4 5

conn = sqlite3.connect("testdb.sqlite3") # Kiểm tra kiểu dữ liệu của đối tượng kết nối print(type(conn))

Chương 5. Phát triển ứng dụng với Python 286

Các phương thức quan trọng trong connection object: • cursor() – Trả về một đối tượng con trỏ (Cursor) để thực thi truy vấn SQL. • commit() – Lưu các thay đổi vào database sau khi thực hiện thao tác thêm, sửa, xóa. • rollback() – Hoàn tác các thay đổi nếu có lỗi xảy ra. • close() – Đóng kết nối khi không còn cần sử dụng. Object Cursor: Sau khi tạo kết nối đến cơ sở dữ liệu, chúng ta cần lấy đối tượng con trỏ (Cursor). Con trỏ là công cụ giúp thực hiện các truy vấn SQL và thao tác với dữ liệu. Để lấy con trỏ, ta sử dụng phương thức cursor() của đối tượng kết nối:

import sqlite3 # Tạo kết nối đến database file conn = sqlite3.connect("testdb.sqlite3") # Lấy đối tượng con trỏ cur = conn.cursor() # Kiểm tra kiểu dữ liệu của con trỏ print(type(cur))

1 2 3 4 5 6 7

Ví dụ 5.3.3. Lấy đối tượng con trỏ truy cập SQLite.

Chúng ta có thể thực hiện tất cả các thao tác truy vấn SQL, với sự trợ giúp của phương thức execute() có sẵn trong đối tượng con trỏ. Phương thức này cần một đối số chuỗi là một lệnh SQL hợp lệ. Sau khi thực thi truy vấn, phải gọi commit() để lưu các thay đổi vào database.

cur.execute("""

CREATE TABLE IF NOT EXISTS users (

id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL,age INTEGER ) """)

conn.commit() #

Lưu thay đổi

1 2 3 4 5

Ví dụ 5.3.4. Thực thi tạo bảng trong SQLite.

Cách tạo bảng trong database: Để thêm bảng Employee vào cơ sở dữ liệu testdb.sqlite3 vừa được tạo. Trong script dưới đây, chúng ta gọi phương thức execute() của object cursor để thực thi câu lệnh CREATE TABLE.

import sqlite3 # Kết nối hoặc tạo database nếu chưa tồn tại conn = sqlite3.connect("testdb.sqlite3") cur = conn.cursor() # Câu lệnh SQL tạo bảng Employee qry = """

1 2 3 4 5 6

Ví dụ 5.3.5. Tạo bảng Employee.

CREATE TABLE IF NOT EXISTS Employee (EmpID INTEGER PRIMARY KEY AUTOINCREMENT,

FIRST_NAME TEXT(20), LAST_NAME TEXT(20), AGE INTEGER, SEX TEXT(1), INCOME FLOAT);

""" try:

cur.execute(qry) conn.commit() # Lưu thay đổi print("Table created successfully")

except sqlite3.Error as e:

print(f"Error creating table: {e}")

# Đóng kết nối sau khi hoàn thành conn.close()

7 8 9 10 11 12 13 14 15 16 17

5.3 Phát triển các ứng dụng quản lý với Python 287

Các thao tác với dữ liệu: Khi làm việc với SQLite trong Python, việc thao tác với dữ liệu là một phần quan trọng. Các thao tác cơ bản bao gồm chèn (INSERT), đọc (READ), cập nhật (UPDATE) và xóa (DELETE) dữ liệu từ bảng trong database. Python cung cấp các phương thức thông qua module sqlite3 để thực hiện những thao tác này một cách dễ dàng. Thao tác insert trong sqlite: Thao tác INSERT được yêu cầu khi bạn muốn tạo bản ghi vào một bảng trong cơ sở dữ liệu.

import sqlite3 # Kết nối đến cơ sở dữ liệu conn = sqlite3.connect("testdb.sqlite3") cur = conn.cursor() # Câu lệnh INSERT qry = """ INSERT INTO Employee (FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES ("Mac", "Mohan", 20, "M", 2000) """ try:

cur.execute(qry) conn.commit() print("Thêm bản ghi thành công.")

except Exception as e: conn.rollback() print("Lỗi khi chèn dữ liệu:", e)

conn.close() # Đóng kết nối

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Ví dụ 5.3.6. Insert dữ liệu trực tiếp.

import sqlite3 conn = sqlite3.connect("testdb.sqlite3") cur = conn.cursor() # Câu lệnh INSERT sử dụng tham số qry = """ INSERT INTO Employee (FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES (?, ?, ?, ?, ?) """

1 2 3 4 5 6 7 8

Ví dụ 5.3.7. Dùng tham số giúp mã an toàn hơn và tránh lỗi SQL Injection..

try:

data = ("Makrand", "Mohan", 21, "M", 5000) cur.execute(qry, data) conn.commit() print("Thêm bản ghi thành công.")

except Exception as e: conn.rollback() print("Lỗi khi chèn dữ liệu:", e)

9 10 11 12 13 14 15 16 17

conn.close

Chương 5. Phát triển ứng dụng với Python 288

Thao tác READ trong SQLite bằng Python: Thao tác READ trên bất kỳ cơ sở dữ liệu nào có nghĩa là lấy thông tin hữu ích từ cơ sở dữ liệu. Khi kết nối cơ sở dữ liệu đã được thiết lập, bạn sẵn sàng thực hiện một truy vấn vào cơ sở dữ liệu này. Bạn có thể sử dụng phương thức fetchone() để lấy một bản ghi hoặc fetchall() để lấy nhiều giá trị từ một bảng cơ sở dữ liệu. • Fetchone() – Lấy hàng tiếp theo của tập kết quả truy vấn. Một tập kết quả là một đối tượng được trả về khi đối tượng con trỏ được sử dụng để truy vấn một bảng. • Fetchall() – Lấy tất cả các hàng trong một tập kết quả. Nếu một số hàng đã được trích xuất từ tập kết quả, thì nó sẽ truy xuất các hàng còn lại từ tập kết quả. • Rowcount – Thuộc tính chỉ đọc, trả về số hàng bị ảnh hưởng bởi phương thức execute().

import sqlite3 conn = sqlite3.connect("testdb.sqlite3") cur = conn.cursor() qry = "SELECT * FROM EMPLOYEE" try:

# Execute the SQL command cur.execute(qry) # Fetch all the rows in a list of lists. results = cur.fetchall() for row in results: fname = row[1] lname = row[2] age = row[3] sex = row[4] income = row[5] # Now print fetched result print("Fname={},Lname={},Age={},Sex={},Income={}".format(fname,lname,age,sex,income))

except Exception as e:

print(e) print("Error: Unable to fetch data")

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

conn.close()

Ví dụ 5.3.8. Đọc dữ liệu từ bảng Employee.

1

import sqlite3

Ví dụ 5.3.9. Cập nhật tất cả các bản ghi có INCOME = 2000, tăng thu nhập thêm 1000..

conn = sqlite3.connect("testdb.sqlite3") cur = conn.cursor() qry = "UPDATE EMPLOYEE SET INCOME = INCOME + 1000 WHERE INCOME = ?" try:

cur.execute(qry, (2000,)) # Thực thi truy vấn với tham số conn.commit() # Lưu thay đổi vào cơ sở dữ liệu print("Records Updated Successfully")

except Exception as e: print("Error:", e)

conn.close()

2 3 4 5 6 7 8 9 10 11

5.3 Phát triển các ứng dụng quản lý với Python 289

import sqlite3 conn = sqlite3.connect("testdb.sqlite3") cur = conn.cursor() qry = "DELETE FROM EMPLOYEE WHERE INCOME < ?" try:

cur.execute(qry, (2000,)) conn.commit() print("Records Deleted Successfully")

except Exception as e: print("Error:", e)

conn.close()

1 2 3 4 5 6 7 8 9 10 11

Ví dụ 5.3.10. Xóa tất cả các nhân viên có INCOME < 2000:.

5.3.2 Projec 1. Quản lý thư viện

import tkinter as tk from tkinter import messagebox class BookBorrowingSystem: def __init__(self):

self.master = tk.Tk() self.master.title("Book Borrowing System") self.master.geometry("750x600") self.master.config(bg=’#708090’) self.books = [] self.lend_list = [] self.record = {} self.setup_gui() self.librarians = []

1 2 3 4 5 6 7 8 9 10 11 12 13

Đầu tiên, chúng ta cần cài đặt Tkinter và xây dựng màn hình đăng nhập/đăng ký cho người dùng. Nhập môđun cần thiết và xác định một class, BookBorrowingSystem. Xác định một phương thức khởi tạo cho class và cửa sổ gốc, đặt tiêu đề, kích thước và màu nền cho ứng dụng. Xác định hai danh sách, books và lend_list, chúng ta sẽ dùng nó để lưu tiêu đề của sách và sách đã được mượn. Xác định một từ điển, record dùng để update trạng thái của sách. Dùng phương thức setup_gui() để tạo giao diện người dùng đồ họa và khởi tạo một danh sách trống, librarians dùng để lưu trữ thông tin đăng nhập.

Chương 5. Phát triển ứng dụng với Python 290

def setup_gui(self):

self.login_label = tk.Label(self.master, text="Book Borrowing System", font=("Helvetica", 24), bg=’#708090’, fg=’white’) self.login_label.pack(pady=(30, 10)) self.login_button = tk.Button(self.master, text="Login", command=self.login,

font=("Helvetica", 14))

self.login_button.pack(pady=10) # Tương tự, tạo username_label,username_entry,password_label,password_entry và register

1 2 3 4 5 6 7 8

Xác định phương thức setup_gui(). Đối với màn hình đăng ký/đăng nhập, chúng ta sẽ tạo 3 nhãn tên login_label, username_label và password_label. Đối với mỗi nhãn, xác định thành phần gốc muốn đặt nó vào bên trong, text mà nó sẽ hiện, bao gồm cả kiểu và màu font. Cùng với các label, cần tạo 2 widget đầu vào tên username_entry và password_entry để nhận và lưu trữ thông tin đăng nhập của thủ thư. Dùng trình quản lý pack để sắp xếp tất cả những widget này và thêm padding phù hợp tạo điểm nhấn thị giác.

elf.username_entry.get()

password = self.password_entry.get() for librarian in self.librarians:

if username == librarian[0] and password == librarian[1]:

self.username_entry.delete(0, tk.END) self.password_entry.delete(0, tk.END) self.login_label.destroy() # Phá hủy toàn bộ entries, labels, và buttons self.book_management_screen() return

messagebox.showerror("Error", "Invalid username or password. Please register if not done already.")

1 2 3 4 5 6 7 8 9 10 11

Định nghĩa phương thức login(), dùng get() trên widget đầu vào để truy xuất giá trị thông tin đăng nhập mà thủ thư nhập vào. Lặp lại danh sách thủ thư và kiểm tra xem liệu tên người dùng và mật khẩu có khớp với dữ liệu đã nhập. Nếu đúng, xóa giá trị đã nhập từ lúc bắt đầu tới khi kết thúc. Hủy tất cả widget đã tạo và gọi book_management_screen() để hiện màn hình quản lý của hệ thống mượn sách. Trường hợp khác, thông tin đăng nhập sai hoặc thủ thư chưa đăng ký. Hiện thông báo phù hợp qua widget box thông báo của Tkinter. Trong trường hợp muốn mã hóa mật khẩu, cần cài đặt môđun bcrypt.

def register(self):

username = self.username_entry.get() password = self.password_entry.get() self.librarians.append([username, password]) self.username_entry.delete(0, tk.END) self.password_entry.delete(0, tk.END)

1 2 3 4 5 6

Xác định một phương thức register(). Truy xuất giá trị thông tin đăng nhập mà thủ thư nhập vào, thêm chúng vào danh sách của thủ thư và xóa hoàn toàn các mục nhập.

Xác định một phương thức book_management_screen(): Tạo 4 nhãn tên add_book_label, return_book_label, remove_book_label và issue_book_label. Tạo thêm 4 mục và 4

5.3 Phát triển các ứng dụng quản lý với Python 291

def book_management_screen(self):

self.add_book_label = tk.Label(self.master, text="Add Book", font=("Helvetica", 18), bg=’#708090’, fg=’white’)

self.add_book_label.pack(pady=(20, 5)) self.add_book_entry = tk.Entry(self.master, font=("Helvetica", 14)) self.add_book_entry.pack() self.add_book_button = tk.Button(self.master, text="Add Book",

command=self.add_book, font=("Helvetica", 14))

self.add_book_button.pack(pady=5) # Lặp lại code tương tự cho return_book, remove_book, issue_book self.view_books_button = tk.Button(self.master, text="View Books", command=self.view_books, font=("Helvetica", 14))

1 2 3 4 5 6 7 8 9 10 11 12 13

self.view_books_button.pack(pady=10)

nút bấm tương ứng với những nhãn này và nút bấm khác để xem danh sách toàn bộ sách cùng trạng thái của chúng. Dùng trình quản lý gói để sắp xếp các phần tử và thêm một chút padding.

def add_book(self):

1 2 3 4 5 6

book = self.add_book_entry.get() self.books.append(book) self.record[book] = "added" messagebox.showinfo("Success", "Book added successfully") self.add_book_entry.delete(0, tk.END)

Xây dựng chức năng cho hệ thống mượn sách: Hàm add_book() truy xuất nội dụng của widget đầu vào và thêm nó vào danh sách. Ở từ điển record, thêm từ khóa làm tiêu đề sách và giá trị dưới dạng added. Hiện một box thông báo thành công cho biết chương trình đã hoàn thành việc thêm sách. Xóa nội dung của add_book_entry từ đầu tới cuối.

def remove_book(self):

book = self.remove_book_entry.get() if book in self.books:

self.books.remove(book) if book in self.record:

del self.record[book]

messagebox.showinfo("Success", "Book removed successfully")

else:

messagebox.showerror("Error", "Book not found")

1 2 3 4 5 6 7 8 9 10

self.remove_book_entry.delete(0, tk.END)

Xác định một phương thức remove_book(). Truy xuất tiêu đề sách và kiểm tra xem liệu nó có hiện trong danh sách books hay không. Nếu tồn tại, hãy loại bỏ nó và các bản ghi tương ứng khỏi từ điển. Sau khi hoàn thành, hiện một hộp thoại thông báo thành công cho biết chương trình đó đã loại bỏ cuốn sách đó. Nếu không, hiện box thông báo lỗi cho biết không tìm thấy cuốn sách đó. Xóa hoàn toàn mục nhập remove_book_entry.

Xác định một phương thức issue_book(). Truy xuất tên sách và kiểm tra xem nó có tồn tại trong danh sách books. Nếu đúng, hãy gắn nó vào danh sách sách. Update giá trị sách là issued. Nếu không, hiện box thông báo lỗi cho biết không tim thấy sách đó. Xóa nội dung của issue_book_entry().

def issue_book(self):

book = self.issue_book_entry.get() if book in self.books:

self.lend_list.append(book) self.books.remove(book) self.record[book] = "issued" messagebox.showinfo("Success", "Book issued successfully")

else:

messagebox.showerror("Error", "Book not found")

self.issue_book_entry.delete(0, tk.END)

1 2 3 4 5 6 7 8 9 10

Chương 5. Phát triển ứng dụng với Python 292

def return_book(self):

book = self.return_book_entry.get() if book in self.lend_list:

self.lend_list.remove(book) self.books.append(book) self.record[book] = "returned" messagebox.showinfo("Success", "Book returned successfully")

elif book in self.books and self.record.get(book) == "added":

messagebox.showerror("Error", "Book can’t be returned. It hasn’t been issued.")

else: messagebox.showerror("Error", "Book not found.") self.return_book_entry.delete(0, tk.END)

1 2 3 4 5 6 7 8 9 10 11

Xác định phương thức return_book(). Truy xuất tiêu đề và kiểm tra xem nó có tồn tại trong danh sách lend_list. Nếu có, loại bỏ nó và gắn nó trở lại danh sách sách và update giá trị trong bản ghi là returned. Hiện box thông báo rằng người mượn đã trả sách. Nếu tên sách đã tồn tại trong danh sách và trạng thái của bản ghi đọc added, hiện box thông báo lỗi cho biết người đó không thể trả lại sách vì chưa ai tiếp nhận. Nếu không, hiển thị hộp thông báo lỗi nói rằng không tìm thấy sách.

def view_books(self): message = "" for book, status in self.record.items(): message += f"{book}: {status}\n"

if not message:

message = "No book records available."

messagebox.showinfo("Books", message)

1 2 3 4 5 6 7

Định nghĩa phương thức view_books(). Khởi tạo biến message là trống. Tạo thông báo thực hiện phép nội suy chuỗi và hiện tên sách cùng với trạng thái của nó. Nếu thông báo trống, hiện không có sẵn sách. Hiện kết quả tương ứng trong một box thông báo.

def run(self):

self.master.mainloop()

if __name__ == "__main__":

book_borrowing_system = BookBorrowingSystem() book_borrowing_system.run()

1 2 3 4 5

Tạo một phiên bản class và chạy mainloop() Tkinter để lắng nghe sự kiện cho tới khi bạn đóng cửa sổ. Dùng __name__ == "__main__" để chạy chương trình.

5.3 Phát triển các ứng dụng quản lý với Python 293

Kết quả của project trên: Màn hình đăng nhập khi chạy chương trình. Nhập thông tin và click nút Register, chương trình sẽ thêm bạn làm thủ thư. Nhập cùng thông tin đó và nhấn Login sẽ đưa bạn tới màn hình quản lý.

Hình 5.33: Giao diện đăng nhập hệ thống quản lý thư viện

Khi nhập tên sách và nhấn Add Book, chương trình hiện một box thông báo đã thêm sách thành công. Nếu click vào nút issue, return hay remove, chương trình hiện hộp thoại thông báo phù hợp trong khi cập nhật trạng thái.

Hình 5.34: Giao diện thêm, xem, trả, sách trong hệ thống quản lý thư viện

Khi click nút View Books, chương trình hiện tên sách cùng với trạng thái của nó. Nếu loại bỏ sách, chương trình xóa tên và không thể xem. Trường hợp trả sách chưa phát hành hay xóa sách đã phát hành, chương trình sẽ hiện thông báo lỗi.

5.3.3 Projec 2. Quản lý sinh viên

a) Mô tả project: Viết chương trình quản lý sinh viên trong Python. Mỗi đối tượng sinh viên có các thuộc tính sau: id, tên, giới tính, tuổi, điểm toán, điểm lý, điểm hóa, điểm trung bình và học lực. Id là mã sinh viên tự động tăng, điểm trung bình là giá trị trung bình của 3 môn toán, lý và hóa. Học lực được tính như sau, Giỏi nếu điểm trung bình lớn hơn hoặc bằng 8, Khá nếu điểm trung bình nhỏ hơn 8 và lớn hơn hoặc bằng 6.5; Trung bình nếu điểm trung bình nhỏ hơn 6.5 và lớn hơn hoặc bằng 5; Yếu nếu điểm trung bình nhỏ hơn 5.

Yêu cầu tạo ra một menu với các chức năng sau: 1) Thêm sinh viên; 2) Cập nhật thông tin sinh viên bởi ID; 3) Xóa sinh viên bởi ID; 4) Tìm kiếm sinh viên theo tên; 5) Sắp xếp sinh

Chương 5. Phát triển ứng dụng với Python 294

viên theo điểm trung bình (GPA); 6) Sắp xếp sinh viên theo tên; 6) Sắp xếp sinh viên theo ID; 8) Hiển thị danh sách sinh viên.

Chúng ta sẽ tạo ra một class để định nghĩa sinh viên và một class để quản lý danh sách sinh viên nhập từ bàn phím. Sau đây là các bước cụ thể để cài đặt chương trình quản lý sinh viên trong Python bằng lập trình hướng đối tượng.

class SinhVien:

def __init__(self, id, name, sex, age, diemToan, diemLy, diemHoa):

1 2 3 4 5 6 7 8 9 10 11

self._id = id self._name = name self._sex = sex self._age = age self._diemToan = diemToan self._diemLy = diemLy self._diemHoa = diemHoa self._diemTB = 0 self._hocLuc = ""

Tạo class sinh viên: Chúng ta sẽ tạo một class sinh viên như sau, DiemTB sẽ được tính bằng trung bình của các môn toán, lý và hóa. HocLuc sẽ được tính toán dựa vào DiemTB như yêu cầu của bài toán (class SinhVien.py).

1

listSinhVien = []

Tạo class quản lý sinh viên: Dầu tiên, chúng ta nên tạo ra một biến để lưu trữ danh sách sinh viên, bạn có thể tham khảo một trong các Collections trong Python, ở đây chúng tôi sử dụng List.

1 2 3 4 5 6 7 8 9 10 11 12 13

def generateID(self) def soLuongSinhVien(self) def nhapSinhVien(self) def updateSinhVien(self, ID) def sortByID(self) def sortByName(self) def sortByDiemTB(self) def findByID(self, ID) def findByName(self, keyword) def deleteById(self, ID) def tinhDTB(self, sv:SinhVien) def showSinhVien(self, listSV) def getListSinhVien(self)

Tạo danh sách các hàm mà chúng ta sẽ sử dụng trong chương trình quản lý sinh viên:

# Hàm tạo ID tăng dần cho nhân viên def generateID(self):

1 2 3 4

maxId = 1 if (self.soLuongSinhVien() > 0):

Hàm generateID(): Yêu cầu của bài toán là id của sinh viên tự động tăng. Nên chúng ta sẽ tạo hàm này để lấy ra id lớn nhất của danh sách sinh viên.

maxId = self.listSinhVien[0]._id for sv in self.listSinhVien: if (maxId < sv._id): maxId = sv._id

maxId = maxId + 1

return maxId

5 6 7 8 9 10

5.3 Phát triển các ứng dụng quản lý với Python 295

def soLuongSinhVien(self):

return self.listSinhVien.__len__()

1 2

Hàm trả về số lượng sinh viên soLuongSinhVien() hiện tại trong ListSinhVien:

def nhapSinhVien(self):

# Khởi tạo một sinh viên mới svId = self.generateID() name = input("Nhap ten sinh vien: ") sex = input("Nhap gioi tinh sinh vien: ") age = int(input("Nhap tuoi sinh vien: ")) diemToan = float(input("Nhap diem toan: ")) diemLy = float(input("Nhap diem Ly: ")) diemHoa = float(input("Nhap diem Hoa: ")) sv = SinhVien(svId, name, sex, age, diemToan, diemLy, diemHoa) self.tinhDTB(sv) self.xepLoaiHocLuc(sv) self.listSinhVien.append(sv)

1 2 3 4 5 6 7 8 9 10 11 12 13

Hàm nhập thông tin sinh viên: Hàm này được sử dụng để thêm mới sinh viên vào danh sách sinh viên ListSinhVien:

def updateSinhVien(self, ID):

# Tìm kiếm sinh viên trong danh sách listSinhVien sv:SinhVien = self.findByID(ID) # Nếu sinh viên tồn tại thì cập nhập thông tin sinh viên if (sv != None):

# nhập thông tin sinh viên name = input("Nhap ten sinh vien: ") sex = input("Nhap gioi tinh sinh vien: ") age = int(input("Nhap tuoi sinh vien: ")) diemToan = float(input("Nhap diem toan: ")) diemLy = float(input("Nhap diem Ly: ")) diemHoa = float(input("Nhap diem Hoa: ")) # cập nhật thông tin sinh viên sv._name = name sv._sex = sex sv._age = age sv._diemToan = diemToan sv._diemLy = diemLy sv._diemHoa = diemHoa self.tinhDTB(sv)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Hàm cập nhật thông tin sinh viên: Cập nhật thông tin sinh viên theo ID. Trong trường hợp không nhập gì cho các thuộc tính của sinh viên thì thuộc tính đó không được thay đổi.

self.xepLoaiHocLuc(sv)

else:

21 22 23

print("Sinh vien co ID = {} khong ton tai.".format(ID))

Chương 5. Phát triển ứng dụng với Python 296

def deleteById(self, ID): isDeleted = False # Tìm kiếm sinh viên theo ID sv = self.findByID(ID) if (sv != None):

self.listSinhVien.remove(sv) isDeleted = True

1 2 3 4 5 6 7 8

return isDeleted

Hàm xóa sinh viên theo ID: Hàm này được sử dụng để xóa sinh viên khỏi danh sách theo ID. Tình sinh viên có ID đã cho trong danh sách, nếu tồn tại thì thực hiện xóa sinh viên.

# Hàm tìm kiếm sinh viên theo tên. Trả về một danh sách sinh viên def findByName(self, keyword):

listSV = [] if (self.soLuongSinhVien() > 0): for sv in self.listSinhVien:

if (keyword.upper() in sv._name.upper()):

listSV.append(sv)

1 2 3 4 5 6 7 8

return listSV

Hàm tìm kiếm sinh viên theo tên: Sử dụng để tìm kiếm sinh viên trong danh sách theo tên. Không phân biệt chữ hoa, chữ thường.

def tinhDTB(self, sv:SinhVien):

1 2 3 4

diemTB = (sv._diemToan + sv._diemLy + sv._diemHoa) / 3 # Làm tròn điểm trung binh với 2 chữ số thập phân sv._diemTB = math.ceil(diemTB * 100) / 100

#Hàm xếp loại học lực cho nhân viên def xepLoaiHocLuc(self, sv:SinhVien):

if (sv._diemTB >= 8):

sv._hocLuc = "Gioi" elif (sv._diemTB >= 6.5): sv._hocLuc = "Kha"

elif (sv._diemTB >= 5):

sv._hocLuc = "Trung Binh"

else:

1 2 3 4 5 6 7 8 9 10

sv._hocLuc = "Yeu"

Hàm tính điểm trung bình và xếp loại học lực

def sortByDiemTB(self):

1 2

self.listSinhVien.sort(key=lambda x: x._diemTB, reverse=False)

Hàm sắp xếp danh sách sinh viên theo điểm trung bình: Sử dụng để sắp xếp sinh viên theo điểm trung bình theo thứ tự tăng dần.

5.3 Phát triển các ứng dụng quản lý với Python 297

def sortByName(self):

self.listSinhVien.sort(key=lambda x: x._name, reverse=False)

1 2

Hàm sắp xếp danh sách sinh viên theo tên: Sử dụng để sắp xếp sinh viên theo tên theo thứ tự tăng dần và không phân biệt chữ hoa, chữ thường.

def showSinhVien(self, listSV): # hien thi tieu de cot print("{:<8} {:<18} {:<8} {:<8}{:<8} {:<8} {:<8} {:<8} {:<8}"

.format("ID", "Name", "Sex", "Age", "Toan", "Ly", "Hoa", "Diem TB", "Hoc Luc"))

# hien thi danh sach sinh vien if (listSV.__len__() > 0): for sv in listSV:

print("{:<8} {:<18} {:<8} {:<8}{:<8} {:<8} {:<8} {:<8} {:<8}"

.format(sv._id, sv._name, sv._sex, sv._age, sv._diemToan, sv._diemLy,

sv._diemHoa,sv._diemTB, sv._hocLuc))

print("\n")

1 2 3 4 5 6 7 8 9 10 11

Hàm hiện thị danh sách sinh viên ra màn hình.

import math from main.SinhVien import SinhVien class QuanLySinhVien: listSinhVien = [] # Hàm tạo ID tăng dần cho nhân viên def generateID(self):

maxId = 1 if (self.soLuongSinhVien() > 0):

maxId = self.listSinhVien[0]._id for sv in self.listSinhVien: if (maxId < sv._id): maxId = sv._id

maxId = maxId + 1

return maxId

def soLuongSinhVien(self):

return self.listSinhVien.__len__()

def nhapSinhVien(self):

# Khởi tạo một sinh viên mới svId = self.generateID() name = input("Nhap ten sinh vien: ") sex = input("Nhap gioi tinh sinh vien: ") age = int(input("Nhap tuoi sinh vien: ")) diemToan = float(input("Nhap diem toan: ")) diemLy = float(input("Nhap diem Ly: ")) diemHoa = float(input("Nhap diem Hoa: ")) sv = SinhVien(svId, name, sex, age, diemToan, diemLy, diemHoa) self.tinhDTB(sv) self.xepLoaiHocLuc(sv) self.listSinhVien.append(sv)

def updateSinhVien(self, ID):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Class QuanLySinhVien.py chứa toàn bộ các hàm trên.

# Tìm kiếm sinh viên trong danh sách listSinhVien sv:SinhVien = self.findByID(ID) # Nếu sinh viên tồn tại thì cập nhập thông tin sinh viên if (sv != None):

# nhập thông tin sinh viên name = input("Nhap ten sinh vien: ") sex = input("Nhap gioi tinh sinh vien: ") age = int(input("Nhap tuoi sinh vien: ")) diemToan = float(input("Nhap diem toan: ")) diemLy = float(input("Nhap diem Ly: ")) diemHoa = float(input("Nhap diem Hoa: ")) # cập nhật thông tin sinh viên sv._name = name sv._sex = sex sv._age = age sv._diemToan = diemToan sv._diemLy = diemLy sv._diemHoa = diemHoa self.tinhDTB(sv) self.xepLoaiHocLuc(sv)

else:

print("Sinh vien co ID = {} khong ton tai.".format(ID))

# Hàm sắp xếp danh sach sinh vien theo ID tăng dần def sortByID(self):

self.listSinhVien.sort(key=lambda x: x._id, reverse=False)

#Hàm sắp xếp danh sach sinh vien theo tên tăng dần def sortByName(self):

self.listSinhVien.sort(key=lambda x: x._name, reverse=False)

# Hàm sắp xếp danh sach sinh vien theo điểm TB tăng dần def sortByDiemTB(self):

self.listSinhVien.sort(key=lambda x: x._diemTB, reverse=False)

# Hàm tìm kiếm sinh viên theo ID Trả về một sinh viên def findByID(self, ID): searchResult = None if (self.soLuongSinhVien() > 0): for sv in self.listSinhVien:

if (sv._id == ID):

searchResult = sv

return searchResult

# Hàm tìm kiếm sinh viên theo tên Trả về một danh sách sinh viên def findByName(self, keyword):

listSV = [] if (self.soLuongSinhVien() > 0): for sv in self.listSinhVien:

if (keyword.upper() in sv._name.upper()):

listSV.append(sv)

return listSV

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

# Hàm xóa sinh viên theo ID def deleteById(self, ID): isDeleted = False

Chương 5. Phát triển ứng dụng với Python 298

sv = self.findByID(ID) # tìm kiếm sinh viên theo ID if (sv != None):

self.listSinhVien.remove(sv) isDeleted = True

return isDeleted

# Hàm tính điểm TB cho sinh viên def tinhDTB(self, sv:SinhVien):

diemTB = (sv._diemToan + sv._diemLy + sv._diemHoa) / 3 # làm tròn điểm trung binh với 2 chữ số thập phân sv._diemTB = math.ceil(diemTB * 100) / 100

#Hàm xếp loại học lực cho nhân viên def xepLoaiHocLuc(self, sv:SinhVien):

if (sv._diemTB >= 8):

sv._hocLuc = "Gioi" elif (sv._diemTB >= 6.5): sv._hocLuc = "Kha"

elif (sv._diemTB >= 5):

sv._hocLuc = "Trung Binh"

else:

sv._hocLuc = "Yeu"

# Hàm hiển thị danh sách sinh viên ra màn hình console def showSinhVien(self, listSV): # hien thi tieu de cot print("{:<8} {:<18} {:<8} {:<8}{:<8} {:<8} {:<8} {:<8} {:<8}"

.format("ID", "Name", "Sex", "Age", "Toan", "Ly", "Hoa", "Diem TB", "Hoc Luc"))

# hien thi danh sach sinh vien if (listSV.__len__() > 0): for sv in listSV:

print("{:<8} {:<18} {:<8} {:<8}{:<8} {:<8} {:<8} {:<8} {:<8}"

.format(sv._id, sv._name, sv._sex, sv._age, sv._diemToan, sv._diemLy,

sv._diemHoa,sv._diemTB, sv._hocLuc))

print("\n")

# Hàm trả về danh sách sinh viên hiện tại def getListSinhVien(self):

return self.listSinhVien

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

5.3 Phát triển các ứng dụng quản lý với Python 299

from main.QuanLySinhVien import QuanLySinhVien # khởi tạo một đối tượng QuanLySinhVien để quản lý sinh viên qlsv = QuanLySinhVien() while (1==1):

print("\nCHUONG TRINH QUAN LY SINH VIEN C#") print("*************************MENU**************************") print("** 1. Them sinh vien. **") print("** 2. Cap nhat thong tin sinh vien boi ID. **") print("** 3. Xoa sinh vien boi ID. **") print("** 4. Tim kiem sinh vien theo ten. **") print("** 5. Sap xep sinh vien theo diem trung binh (GPA). **")

1 2 3 4 5 6 7 8 9 10 11

Hàm main của chúng ta được sử dụng để khởi tạo menu và điều khiển chương trình quản lý sinh viên được đặt trong class Main:

print("** 6. Sap xep sinh vien theo ten. **") print("** 7. Sap xep sinh vien theo ID. **") print("** 8. Hien thi danh sach sinh vien. **") print("** 0. Thoat **") print("*******************************************************") key = int(input("Nhap tuy chon: ")) if (key == 1):

print("\n1. Them sinh vien.") qlsv.nhapSinhVien() print("\nThem sinh vien thanh cong!")

elif (key == 2):

if (qlsv.soLuongSinhVien() > 0):

print("\n2. Cap nhat thong tin sinh vien. ") print("\nNhap ID: ") ID = int(input()) qlsv.updateSinhVien(ID)

else:

print("\nSanh sach sinh vien trong!")

elif (key == 3):

if (qlsv.soLuongSinhVien() > 0): print("\n3. Xoa sinh vien.") print("\nNhap ID: ") ID = int(input()) if (qlsv.deleteById(ID)):

print("\nSinh vien co id = ", ID, " da bi xoa.")

else:

print("\nSinh vien co id = ", ID ," khong ton tai.")

else:

print("\nSanh sach sinh vien trong!")

elif (key == 4):

if (qlsv.soLuongSinhVien() > 0):

print("\n4. Tim kiem sinh vien theo ten.") print("\nNhap ten de tim kiem: ") name = input() searchResult = qlsv.findByName(name) qlsv.showSinhVien(searchResult)

else:

print("\nSanh sach sinh vien trong!")

elif (key == 5):

if (qlsv.soLuongSinhVien() > 0):

print("\n5. Sap xep sinh vien theo diem trung binh (GPA).") qlsv.sortByDiemTB() qlsv.showSinhVien(qlsv.getListSinhVien())

else:

print("\nSanh sach sinh vien trong!")

elif (key == 6):

if (qlsv.soLuongSinhVien() > 0):

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

print("\n6. Sap xep sinh vien theo ten.") qlsv.sortByName() qlsv.showSinhVien(qlsv.getListSinhVien())

Chương 5. Phát triển ứng dụng với Python 300

else:

print("\nSanh sach sinh vien trong!")

elif (key == 7):

if (qlsv.soLuongSinhVien() > 0):

print("\n6. Sap xep sinh vien theo ID.") qlsv.sortByID() qlsv.showSinhVien(qlsv.getListSinhVien())

else:

print("\nSanh sach sinh vien trong!")

elif (key == 8):

if (qlsv.soLuongSinhVien() > 0):

print("\n7. Hien thi danh sach sinh vien.") qlsv.showSinhVien(qlsv.getListSinhVien())

else:

print("\nSanh sach sinh vien trong!")

elif (key == 0):

print("\nBan da chon thoat chuong trinh!") break

else:

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

print("\nKhong co chuc nang nay!") print("\nHay chon chuc nang trong hop menu.")

5.3 Phát triển các ứng dụng quản lý với Python 301

Kết quả thực hiện chương trình:

Hình 5.35: Hệ thống quản lý sinh viên

5.3.4 Projec 3. Quản lý bán hàng với Django

Django là một Framework lập trình web bậc cao được viết bằng ngôn ngữ lập trình Python. Django nhanh và đơn giản giúp chúng ta có thể lập trình web trong thời gian ngắn. Django tuân theo nguyên tắc DRY (Don’t repeat yourself - Đừng lặp lại chính mình), trong khi những Framework khác lại không coi trọng điều này. Django cũng hỗ trợ ORM (Object Relistic Mapping), tuân theo mô hình MTV (Model-Template-View) thay vì mô hình MVC (Model-View-Controller). Mô hình được dùng khi tạo ứng dụng tương tác với người dùng. Mô hình này bao gồm code HTML với DJango Template Language (DTL), View (tương ứng với Controller của MVC) là mã được viết để kiểm soát sự tương tác giữa Model và Template, nói

Chương 5. Phát triển ứng dụng với Python 302

cách khác là điều ướng các Request từ Client gửi lên Server và trả về kết quả từ Server xuống Client.

1 2 3

$ mkdir GreatKart && cd GreatKart # folder chua code project $ pipenv install Django # Django==3.2 $ pipenv shell

Khởi tạo project: Việc đầu tiên là cài đặt môi trường ảo để phát triển dự án, có rất nhiều thư viện python có thể làm được điều này từ virtualenv đến pipenv. Để thuận tiện, mình sử dụng luôn pipenv để triển khai cài đặt. Ta chạy lệnh pip3 install pipenv. Tiếp theo là tạo folder chứa project và chạy môi trường ảo:

1 2

(GreatKart)...$ python3 manage.py migrate (GreatKart)...$ python3 manage.py runserver

Khi command line có dạng (GreatKart)...$ tức là chúng ta đang trong môi trường ảo là GreatKart. Tạo code project với lệnh django-admin startproject greatkart. Lệnh này sẽ tạo tất cả code cần có cho project Django ban đầu, thêm dấu . vào cuối, sẽ hơi khác so với thông thường khi không có dấu .

Lúc này, command line sẽ xuất hiện đường dẫn http://127.0.0.1:8000/ và chúng ta truy cập vào đường dẫn này sẽ có dạng:

Hình 5.36: Giao diện phát triển ứng dụng django

---GreatKart

1 2 3 4 5 6 7 8

|---greatkart (folder) |---manage.py |---db.sqlite3 |---Pipfile |---Pipfile.lock (Nếu chưa có, tạo bằng cách chạy ‘pipenv lock‘) |---requirements.txt ( Tạo bằng lệnh) |---.gitignore ( Tự tạo thêm)

Cấu trúc thư mục của project:

5.3 Phát triển các ứng dụng quản lý với Python 303

DATABASES = {

’default’: {

’ENGINE’: ’django.db.backends.sqlite3’, ’NAME’: os.path.join(BASE_DIR, ’db.sqlite3’),}

}

1 2 3 4 5

Kết nối với MySQL: Mỗi Framework lập trình web nào cũng cần phải có cơ sở dữ liệu để quản lý dữ liệu người dùng. Nhìn thoáng qua file GreatKart/greatkart/settings.py và kéo xuống phần DATABASES:

DATABASES = {

’default’: {

’ENGINE’: "django.db.backends.mysql", ’HOST’: "localhost", ’NAME’: "GreatKart", # Phải tạo trước Schema có tên ’GreatKart’ trong MySQL ’USER’: "root", ’PASSWORD’: "12345678",}

}

1 2 3 4 5 6 7 8

Ở đây, mặc định thì Django đang sử dụng hệ quản trị CSDL là sqlite3 cũng chính vì thế khi chạy lệnh migrate bên trên, folder code sẽ tự tạo file GreatKart/db.sqlite3. Django hỗ trợ rất nhiều hệ quản trị CSDL phổ biến cả sql lẫn nosql, vì thế chúng ta sẽ sử dụng luôn MySQL làm hệ quản trị cơ sở dữ liệu thay cho sqlite3. Để sử dụng được MySQL, chúng ta có thể cài đặt MySQL, cần làm đến bước FLUSH PRIVILEGES. Ngoài ra, để thuận tiên cho quản lý MySQL bằng giao diện, chúng ta có thể cài luôn MySQL Workbench và thư viện mysqlclient để Python kết nối đến MySQl bằng lệnh pip3 install mysqlclient. Code DATABASES được chỉnh sửa lại trong file settings.py như sau:

SECRET_KEY= ... # SECRET_KEY trong file settings.py DATABASE_ENGINE=django.db.backends.mysql DATABASE_NAME=GreatKart DATABASE_USER=root DATABASE_PASSWORD=12345678 DATABASE_HOST=localhost DATABASE_PORT=3306 TIME_ZONE=Asia/Ho_Chi_Minh LANGUAGE_CODE=vi

1 2 3 4 5 6 7 8 9

Chạy lại lệnh python3 manage.py migrate, nếu command line không báo lỗi thì chúng ta đã kết nối thành công, lúc này có thể xóa file db.sqlite3. Chúng ta phải tạo thêm biến env để không bị lộ thông tin cần cài đặt django-environ, sau đó tạo file .env cùng cấp với manage.py với nội dung sau:

import environ env = environ.Env(

DEBUG=(bool, False))

environ.Env.read_env()

1 2 3 4

Điều chỉnh thêm file settings.py như sau:

Chương 5. Phát triển ứng dụng với Python 304

SECRET_KEY = env("SECRET_KEY") DATABASES = {

"default": {

"ENGINE": env("DATABASE_ENGINE"), "NAME": env("DATABASE_NAME"), "USER": env("DATABASE_USER"), "PASSWORD": env("DATABASE_PASSWORD"), "HOST": env("DATABASE_HOST"), "PORT": env("DATABASE_PORT"),}

} LANGUAGE_CODE = env("LANGUAGE_CODE") TIME_ZONE = env("TIME_ZONE")

1 2 3 4 5 6 7 8 9 10 11 12

Thay những thứ tương ứng từ file .env vào:

1 2

$ touch Dockerfile $ touch docker-compose.yml

Chúng ta lại chạy lại câu lênh migrate và runserver như bên trên, nếu không có lỗi gì thì quá trình thiết lập đã xong. Docker cho project: Thoát khỏi môi trường ảo bằng lệnh exit, tạo 2 file Dockerfile và docker-compose.yml:

# Pull base image FROM python:3.12 # Set environmental variables ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # Set work directory WORKDIR /code

# Install dependencies COPY Pipfile Pipfile.lock requirements.txt /code/ RUN pip3 install pipenv && pipenv install --system && pip3 install -r requirements.txt

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

# Copy project COPY .env /code/ COPY . /code/

Nội dung file Dockerfile như sau:

version: ’3’ services:

web:

build: . command: python3 /code/manage.py runserver 0.0.0.0:8000 volumes:

- .:/code

ports:

1 2 3 4 5 6 7 8 9

- 8000:8000

Nội dung file docker-compose.yml như sau:

depends_on: - db

env_file: - .env

db:

image: mysql:8.0.20 restart: always command: --default-authentication-plugin=mysql_native_password --mysqlx=0 environment:

MYSQL_DATABASE: GreatKart MYSQL_USER: root MYSQL_PASSWORD: 12345678 MYSQL_ROOT_PASSWORD: 12345678

volumes:

- ".dbdata:/var/lib/mysql"

ports:

- ’3305:3306’

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

env_file: - .env

5.3 Phát triển các ứng dụng quản lý với Python 305

1 2 3

$ sudo docker build $ sudo docker-compose build $ sudo docker-compose up

Trong file docker-compose.yml, chúng ta tạo 2 container là web (để chạy ứng dụng web) và db (để chạy phần cơ sở dữ liệu MySQL). Cần chú ý là giá trị của depends_on phải là tên container cơ sở dữ liệu (db). Trong container db chứa image có tên mysql:8.0.20 tức là phải là phiên bản MySQl trong máy chúng ta, giá trị volumes bắt đầu với - .db... cũng phải tương ứng với tên container, giá trị ports phải đặt thành {x}/3306 (x không phải là 3306 để không bị trùng port). Cả 2 container phải có giá trị env_file do chúng ta đang dùng biến môi trường. Ngoài ra, file .env cũng cần đổi lại giá trị của DATABASE_HOST=localhost thành DATABASE_HOST=db (tên container db). Chúng ta chạy các lệnh sau:

Mở thêm tab command line và chạy sudo docker-compose exec web python3 manage.py migrate

để kết nối CSDL với container db của Docker. Nếu cả các lệnh trên không báo lỗi và chúng ta truy cập lại trang http://127.0.0.1:8000/ vẫn như cũ thì ổn rồi. Khi đó chúng ta đang chạy web với docker mà không cần phải vào môi trường ảo (pipenv shell). Nếu xảy ra một số lỗi khi chạy thì cần phải fix lỗi.

STATIC_URL = ’/static/’ STATIC_ROOT = BASE_DIR / ’static’ STATICFILES_DIRS = [

1 2 3 4

’greatkart/static’]

Cài đặt Static và Media: Thư mục static trong Django là nơi chứa các folder, file tĩnh bao gồm: folder css, javascipt, font và các file ảnh cố định cho trang web. Ngoài ra, cần dowload các file cần thiết trong bootstrap 4 để sử dụng thư viện django-bootstrap4. Tiếp theo, mở file settings.py thêm đoạn code sau để Django nhận biết thư mục static:

Chương 5. Phát triển ứng dụng với Python 306

1 2

MEDIA_URL = ’/media/’ MEDIA_ROOT = BASE_DIR / ’media’

Trong đó, STATIC_URL và STATIC_ROOT là nơi Django lưu trữ các file static thông qua lệnh quản lý collectstatic khi deploy. STATICFILES_DIRS để Django thông qua đó tìm kiếm tất cả các file static rồi nạp vào nơi lưu trữ. Thư mục static vừa tải xuống để ở trong thư mục con greatkart cùng cấp với file settings.py. Tiếp theo, chúng ta chạy lệnh python3 manager.py collectstatic thì Django sẽ tạo thư mục có đường dẫn như trong biến STATIC_URL cùng cấp với thư mục greatkart. Nếu sau này muốn thay đổi thư mục static, ta chỉ cần sửa thư mục static cùng cấp với settings.py, rồi chạy lại lệnh collectstatic để khởi tạo lại thư mục static mới. Media là thư mục lưu trữ các file có kiểu media như các ảnh, video. Từ đó, server có thể truy cập để thêm, sửa, xóa trong đó. Cấu hình cho media như sau:

class Account(AbstractBaseUser):

first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) username = models.CharField(max_length=50, unique=True) email = models.EmailField(max_length=100, unique=True) phone_number = models.CharField(max_length=50) # required date_joined = models.DateTimeField(auto_now_add=True) last_login = models.DateTimeField(auto_now_add=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=False) is_superadmin = models.BooleanField(default=False) USERNAME_FIELD = ’email’ # Trường quyêt định khi login REQUIRED_FIELDS = [’username’, ’first_name’, ’last_name’]

# Các trường yêu cầu khi đk tài khoản (mặc định đã có email), mặc định có password

objects = MyAccountManager() def __str__(self):

return self.email

def has_perm(self, perm, obj=None):

return self.is_admin # Admin có tất cả quyền trong hệ thống

def has_module_perms(self, add_label):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

return True

Nếu có lệnh truy cập thì Django sẽ tìm thư mục Media hoặc sẽ tạo nó nếu chưa có. Tùy chỉnh user model, category, product model: Trong Django, framework này đã tạo mô hình mặc định cho người dùng có tên là user. Chúng ta nên tùy chỉnh và kế thừa các hàm từ đó vì việc mặc định này thường hạn chế yêu cầu của nhà phát triển. Tạo app mới có tên accounts với lệnh python3 manager.py startapp accounts, thêm ’ac- counts’ vào biến mảng INSTALLED_APPS trong file settings.py, cũng như thêm 1 biến mới AUTH_USER_MODEL = ’accounts.Account’, biến này thông báo cho Django biết ta không còn dùng mô hình user mặc định nữa mà thay vào đó là accounts. Thêm class như sau vào file accounts/model.py:

5.3 Phát triển các ứng dụng quản lý với Python 307

class MyAccountManager(BaseUserManager):

def create_user(self,first_name,last_name,username,email,password=None):

if not email:

raise ValueError(’Email address is required’)

if not username:

raise ValueError(’User name is required’)

# Tạo đối tượng user mới user = self.model(

email=self.normalize_email(email=email),#Chuyển email về dạng bình thường username=username,first_name=first_name, last_name=last_name, )

user.set_password(password) user.save(using=self._db) return user

def create_superuser(self, first_name, last_name, email, username, password):

user = self.create_user(

email=self.normalize_email(email=email), username=username,password=password, first_name=first_name,last_name=last_name,)

user.is_admin = True user.is_active = True user.is_staff = True user.is_superadmin = True user.save(using=self._db) return user

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

Thông tin các trường cần thiết cho bảng mới Account mình đã comment bên cạnh để mọi người hiểu chức năng. Tạo thêm class MyAccountManager để quản lý các thao tác người dùng:

Chạy lệnh python3 manager.py makemigrations, sau đó là python3 manager.py migrate

class AccountAdmin(UserAdmin):

list_display = (’email’,’username’,’first_name’,’last_name’,’last_login’,

’date_joined’,’is_active’)

# Các trường có gắn link dẫn đến trang detail

list_display_links = (’email’, ’username’, ’first_name’, ’last_name’) readonly_fields = (’last_login’, ’date_joined’) # Chỉ cho phép đọc ordering = (’-date_joined’,) # Sắp xếp theo chiều ngược # Bắt buộc phải khai báo filter_horizontal = () list_filter = () fieldsets = ()

admin.site.register(Account, AccountAdmin)

1 2 3 4 5 6 7 8 9 10 11 12

để tạo bảng Account trong mysql. Và chạy lệnh python3 manager.py createsuperuser để tạo 1 superadmin cho hệ thống. Lúc này các trường phải điền đã giống với hàm create_superuser đã tùy chỉnh. Trong file accounts/admin.py ta tạo thêm class để superadmin có thể quản lý bảng này:

Chúng ta truy cập đường dẫn http://127.0.0.1:8000/admin/ để đăng nhập và được các màn hình như sau:

Chương 5. Phát triển ứng dụng với Python 308

Hình 5.37: Giao diện hệ thống quản lý bán hàng

from django.urls import reverse from category.models import Category from django.db import models class Product(models.Model):

product_name = models.CharField(max_length=200, unique=True) slug = models.SlugField(max_length=200, unique=True) description = models.TextField(max_length=500, blank=True) price = models.IntegerField() images = models.ImageField(upload_to=’photos/products’) stock = models.IntegerField() is_available = models.BooleanField(default=True)

# Khi xóa category thì Product bị xóa

category = models.ForeignKey(Category, on_delete=models.CASCADE) created_date = models.DateTimeField(auto_now_add=True) modified_date = models.DateTimeField(auto_now=True) def __str__(self):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

return self.product_name

Tiếp theo, chúng ta tạo app store để quản lý bảng product với lệnh startapp store. Trong file store/models.py ta tạo class Product như sau:

class ProductAdmin(admin.ModelAdmin):

list_display = (’product_name’, ’price’, ’stock’, ’category’, ’created_date’,

’modified_date’, ’is_available’)

prepopulated_fields = {’slug’: (’product_name’,)}

1 2 3 4 5

admin.site.register(Product, ProductAdmin)

Trong file store/admin.py, ta cũng thực hiện thêm app store để superuser quản lý:

Giao diện quản lý app product trong superuser được tạo ra như sau:

5.3 Phát triển các ứng dụng quản lý với Python 309

Hình 5.38: Giao diện quản lý app product trong superuser

urlpatterns = [path(’admin/’, admin.site.urls),

path(’’, views.home, name=’home’), path(’store/’, include(’store.urls’)), path(’carts/’, include(’carts.urls’)),

1 2 3 4 5

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Trong file greatkart/urls.py ta tùy chỉnh biến urlpattern như sau:

urlpatterns = [

path(’’, views.store, name=’store’), path(’/’, views.store, name=’products_by_category’), path(’//’, views.product_detail,

1 2 3 4 5

name=’product_detail’),]

Ngoài ra, ở app store ta cũng tạo 1 file urls.py với biến urlpattern:

class Cart(models.Model):

cart_id = models.CharField(max_length=250, blank=True) date_added = models.DateTimeField(auto_now_add=True) def __str__(self):

return self.cart_id

class CartItem(models.Model):

product = models.ForeignKey(Product, on_delete=models.CASCADE) cart = models.ForeignKey(Cart, on_delete=models.CASCADE) quantity = models.IntegerField() is_active = models.BooleanField(default=True) def __str__(self):

1 2 3 4 5 6 7 8 9 10 11 12 13

return self.product

Chúng ta đã thực hiện khai báo các url trong file greatkart/urls.py, biến urlpattern khai báo các cụm đường dẫn đến các app khác. Django sẽ tự động tìm các đường dẫn từ file này. Biến urlpattern trong file store/urls.py sẽ khai báo cụ thể các đường dẫn như thế nào với tiền tố kế thừa từ file url cha. Thiết kế Cart, CartItem model: Tạo 2 bảng cart và cart_item trong cùng 1 app là carts với lệnh startapp carts. Ta tùy chỉnh file carts/models.py với các class mới như sau:

1 2

admin.site.register(Cart) admin.site.register(CartItem)

Thêm đoạn code để superuser quản lý, ở file carts/admin.py:

Chương 5. Phát triển ứng dụng với Python 310

urlpatterns = [

path(’’, views.cart, name=’cart’), path(’add_cart//’, views.add_cart, name=’add_cart’), path(’remove_cart//’, views.remove_cart, name=’remove_cart’), path(’remove_cart_item//’, views.remove_cart_item,

name=’remove_cart_item’),]

1 2 3 4 5 6

Bảng Cart có các bản ghi mô tả các giỏ hàng của người dùng, bao gồm cả người dùng đã đăng nhập và người dùng vãng lai (bản ghi được tạo dựa trên cookie của máy local). Bảng CartItem với bản ghi tương ứng là các mục hàng trong giỏ hàng. Với 2 khóa ngoại là product và cart. Tùy chỉnh biến urlpartterns trong file carts/urls.py như sau:

1

’DIRS’: [’templates’]

Mở trang settings.py, tùy chỉnh biến TEMPLATES ở cặp key-value như sau:

def home(request):

products = Product.objects.all().filter(is_available=True) context = {

’products’: products, }

return render(request, ’home.html’, context=context)

1 2 3 4 5

Chúng ta tạo folder đồng cấp với manager.py là templates để Django tự động tìm folder này để load các file template. Từ file greatkart/views.py, thêm hàm home để làm chức năng điều hướng request:

Từ folder template, tạo file base.html làm file template cơ sở cho hầu hết các trang trong hệ thống và file home.html làm trang chủ. Các file template có thể tham khảo ở đây: https://greatkart.rathank.com/. Tiếp theo, ta tùy chỉnh file store/views.py để hiển thị trang store. Ngoài ra, có thể thêm các file template cho app store.

1 2

page = request.GET.get(’page’) page = page or 1 # Trường hợp url là http://127.0.0.1:8000/store thì mặc định là trang số 1

Phân trang cho danh sách sản phẩm: Django cung cấp các tác vụ liên quan đến việc phân trang rất tốt. Các trang được thể hiện thông qua các urls khác nhau, và mọi việc đều được kế thừa từ class Paginator. Chúng ta có thể tự xây dựng chức năng phân trang thông qua hướng dẫn chi tiết của Django. Trong hàm store (GreatKart/store/views.py), cần chỉnh sửa lại như sau: - Lấy đối số page truyền lên từ client trong đường dẫn (đối số page ở đây có thể tùy chỉnh):

1

paginator = Paginator(products, 3) # n = 3

- Tạo 1 đối tượng Paginator với 2 đối số, đối số đầu là danh sách tất cả phần tử chúng ta muốn phân trang, đối số thứ 2 là số phần tử trong 1 page là n:

1 2

paged_products = paginator.get_page(page) product_count = products.count()

Lấy tất cả sản phẩm và đếm chúng:

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 311

Kết quả sau khi phân trang như sau:

Hình 5.39: Giao diện quản lý phân trang

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python

5.4.1 Tổng quan về xử lý dữ liệu với Python

Xử lý dữ liệu với Python: Là quá trình áp dụng các phương pháp, thuật toán, và thư viện trong ngôn ngữ lập trình Python để biến đổi, làm sạch, phân tích, và trích xuất thông tin từ dữ liệu. Công đoạn xử lý dữ liệu là quan trọng trong quá trình chuẩn bị dữ liệu cho các tác vụ như phân tích, học máy, và trực quan hóa. Có thể sử dụng một số thư viện như: pandas, Numpy, Scikit - learn, Matplotlib và Seaborn.

Làm sạch dữ liệu với Python: Là phần quan trọng trong quy trình xử lý dữ liệu để làm cho dữ liệu trở nên chính xác và phù hợp cho phân tích. Thường sử dụng một số kỹ thuật và thư viện Python để làm sạch dữ liệu: xử lý giá trị thiếu, xử lý dữ liệu trùng lặp, xử lý ngoại lệ và giá trị không chính xác, chuẩn hóa dữ liệu, kiểm tra và xử lý dữ liệu không hợp lý.

Thống kê dữ liệu với Python: Là quá trình sử dụng các công cụ, thư viện, và kỹ thuật thống kê để mô tả, phân tích, và hiểu thông tin từ tập dữ liệu. Các công cụ và thư viện thống kê Python thường được sử dụng để tạo ra các báo cáo thống kê, biểu đồ, và tóm tắt mô tả về tính chất của dữ liệu. Thường sẽ sử dụng các thư viện bên trên về xử lý dữ liệu.

5.4.2.1 Thư viện NumPy

5.4.2 Project 1. Xử lý mảng số học hiệu năng cao trên thư viện NumPy

NumPy (Numerical Python) là thư viện nền tảng hỗ trợ xử lý mảng nhiều chiều (ndarray) và các hàm toán học vector hóa cực kỳ nhanh, thay thế cho việc dùng vòng lặp truyền thống. NumPy (Numerical Python) là một thư viện Python mã nguồn mở được sử dụng trong hầu hết các lĩnh vực khoa học và kỹ thuật. Đây là tiêu chuẩn chung để làm việc với dữ liệu số bằng Python và là tiêu chuẩn cốt lõi của hệ sinh thái Python và PyData. NumPy API được sử dụng rộng rãi trong Pandas, SciPy, Matplotlib, scikit-learning, scikit-image và hầu hết các gói Python khoa học và khoa học dữ liệu khác.

Thư viện NumPy chứa các cấu trúc dữ liệu ma trận và mảng đa chiều và thực hiện nhiều phép toán khác nhau trên mảng. Nó bổ sung các cấu trúc dữ liệu mạnh mẽ vào Python để đảm

Chương 5. Phát triển ứng dụng với Python 312

bảo tính toán hiệu quả với các mảng và ma trận, đồng thời nó cung cấp một thư viện khổng lồ các hàm toán học cấp cao hoạt động trên các mảng và ma trận này.

Hình 5.40: Thư viện mảng đa chiều, ma trận - Numpy

5.4.2.2 Cài đặt và import thư viện NumPy

Tải Numpy tại địa chỉ sau: https://pypi.org/project/numpy/

1 2

conda install numpy pip install numpy

Để cài đặt thư viện NumPy trong môi trường ảo trên terminal (MacOS/Ubuntu) hoặc Anaconda Prompt (Windows), chúng ta có thể thực hiện bằng một trong hai cách sau: • Cách 1: Cài đặt khi tạo môi trường ảo thông qua câu lệnh conda create -n hanh python=3.7 numpy • Cách 2: Cài đặt sau khi tạo xong môi trường ảo thông qua 1 trong 2 câu lệnh sau:

1 2

!conda install numpy !pip instal numpy

Ngoài ra, chúng ta cũng có thể cài đặt thư viện thẳng trong notebook bằng cách chạy một trong hai câu lệnh sau trên cell code:

1

import numpy as np

Để có thể sử dụng NumPy và các hàm của nó, ta cần chạy câu lệnh sau:

5.4.2.3 Các hàm cơ bản trong NumPy

Chúng ta rút ngắn tên thư viện thành np để thuận tiện cho việc đọc code với NumPy. Đây là một quy ước được áp dụng rộng rãi mà bạn nên tuân theo để bất kỳ ai làm việc với code có thể dễ dàng hiểu nó.

NumPy cung cấp cho bạn rất nhiều cách nhanh chóng và hiệu quả để tạo mảng (array) và thao tác dữ liệu số bên trong chúng. list có thể chứa các kiểu dữ liệu khác nhau, còn tất cả các phần tử trong array NumPy phải đồng nhất. Điều này cho phép các phép toán được thực hiện trên mảng sẽ cực kỳ kém hiệu quả nếu các mảng không đồng nhất. Cũng bởi vì thế, một array tiêu tốn ít bộ nhớ hơn, dẫn đến NumPy sử dụng ít bộ nhớ hơn nhiều để lưu trữ dữ liệu và nó cung cấp một cơ chế xác định các kiểu dữ liệu. Điều này cho phép mã được tối ưu hóa hơn nữa. NumPy có 2 tính chất chính là Vectorization và Broadcasting.

1 2 3 4 5

#Vectorization: [1, 2, 3] + [4, 5, 6] # Phép cộng 2 list là phép nối chuỗi phần tử # Kết quả: [1, 2, 3, 4, 5, 6] import numpy as np np.array([1,2,3]) + np.array([4,5,6]) # Ket qua: array([5, 7, 9])

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 313

Mảng array được gọi là ndarray (Viết tắt của N-dimensional array - mảng N-chiều). N- dimensional array chỉ đơn giản là một array với một hay nhiều chiều dữ liệu. Khi làm việc với mảng đa chiều, ta sẽ gặp những thuật ngữ sau:

• Scalar: Mảng 0 chiều (0-D array) • Vector: Mảng 1 chiều (1-D array) • Matrix: Mảng 2 chiều (2-D array) • Tensor: Mảng 3 chiều (3-D array)

Hình 5.41: Mảng đa chiều n-dimentional

arr = np.array([1,2,3]) # khởi tạo 1 array arr #array([1, 2, 3]) type(arr) # kiểm tra kiểu dữ liệu của biến arr numpy.ndarray def addition(arr1,arr2): Sum of 2 arrays. Parameters ---------- arr1 : First array. arr2 : Second array. return arr1 + arr2

1 2 3 4 5 6 7 8 9 10 11 12

addition(np.array([1,2]),np.array([2,6])) #Output: array([3, 8])

Tạo 1 mảng (Create an array): Để tạo ra một NumPy array, ta có thể tận dụng hàm np.array() và truyền một list cho nó.

Chương 5. Phát triển ứng dụng với Python 314

# list có thể chứa các phần tử thuộc các kiểu dữ liệu khác nhau li = [1,2,’H’] type(li[0]), type(li[1]), type(li[2]) #Output: (int, int, str)

1 2 3 4 5

6 7

# casting về string với kiểu dữ liệu là unicode string < 21 characters, casting int + float về float arr = np.array([1,2,’H’]) type(arr[0]), type(arr[1]), type(arr[2]) #Output: (numpy.str_, numpy.str_, numpy.str_)

Array khác list ở chỗ nào? list có thể chứa các kiểu dữ liệu khác nhau, còn tất cả các phần tử trong array NumPy phải đồng nhất. Có hai quy tắc cơ bản cho mọi mảng trong NumPy là mọi phần tử trong mảng phải có cùng kiểu và kích thước (same type and size) và nếu các phần tử của mảng cũng là mảng thì các mảng bên trong đó phải có cùng kiểu và số phần tử với nhau.

1 2 3

arr.shape # 1 chiều chứa 3 phần tử (3,) arr.ndim # 1 chiều 1 len(arr) #3

Từ ví dụ trên, có thể thấy NumPy không trả về lỗi, nhưng nó chuyển các số nguyên thành chuỗi để đáp ứng thuộc tính rằng mọi phần tử đều là cùng một loại. Loại ‘

1 2

arr_2d = np.array([[1,2,5],[2,3,4]]) arr_2d

Tạo mảng đa chiều: Chúng ta cũng có thể tạo một mảng hai chiều từ một list các list.

1

arr_2d.size #Output: 6

Kết quả từ dòng lệnh trên có thể khiến bạn ngạc nhiên khi arr_2d có 2 chứ không phải 6 phần tử. Đó là bởi vì arr_2d có thể được hiểu là một mảng chứa hai mảng bên trong nó. Nếu muốn lấy tổng số phần tử lồng nhau trong mảng ta sử dụng thuộc tính size như sau:

1

type(arr_2d), arr_2d.dtype #Output: (numpy.ndarray, dtype(’int64’))

5.4.2.4 Một số hàm có sẵn hỗ trợ tạo mảng trong NumPy

Nếu muốn biết kiểu dữ liệu trong array, ta có thể thử sử dụng hàm type() của Python, tuy nhiên câu lệnh này sẽ chỉ cho biết rằng đối tượng là một array NumPy. Nếu muốn xem mảng đang lưu trữ loại dữ liệu nào ta sử dụng thuộc tính .dtype.

Ngoài np.array(), chúng ta có thể tạo một số array đặc thù với np.zeros(), np.ones(), np.arange(), np.linspace().

1 2 3 4 5 6

np.zeros(shape = 3), np.zeros(shape = (3,2)), np.zeros(shape = (3,2,4)) (array([0., 0., 0.]), array([[0., 0.], [0., 0.], [0., 0.]]), array([[[0., 0., 0., 0.], [0., 0., 0., 0.]], [[0., 0., 0., 0.], [0., 0., 0., 0.]], [[0., 0., 0., 0.], [0., 0., 0., 0.]]]))

Ví dụ 5.4.1. Tạo mảng chứa các giá trị 0.

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 315

Bảng 5.6: Một số hàm có sẵn hỗ trợ tạo mảng trong NumPy

Hàm

Ý nghĩa

np.zeros() np.ones() np.full() np.arange() np.linspace

1 mảng chứa các giá trị 0 1 mảng chứa các giá trị 1 1 mảng chứa các giá trị được gán theo fill_value 1 mảng chứa khoảng giá trị có khoảng cách đều nhau 1 mảng các giá trị có khoảng cách tuyến tính với nhau

1 2 3 4 5 6

np.ones(shape = 3), np.ones(shape = (3,2)), np.ones(shape = (3,2,5)) (array([1., 1., 1.]), array([[1., 1.], [1., 1.], [1., 1.]]), array([[[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]], [[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]], [[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]]]))

Ví dụ 5.4.2. Tạo mảng chứa các giá trị 1.

1 2 3 4 5 6

np.full(3, fill_value=’cat’) # truyền vào một shape và fill_value vào np.full() #Output: array([’cat’, ’cat’, ’cat’], dtype=’

5.4.2.5 Tạo mảng ngẫu nhiên

Ví dụ 5.4.3. Tạo mảng với các giá trị truyền vào.

Trong NumPy, hàm np.random() lấy ngẫu nhiên các giá trị trong một phân phối có quy luật. Có một sự thật chẳng có gì là ngẫu nhiên cả, tất cả đều là những quy luật được ẩn giấu, chỉ là chúng ta có phát hiện hay hiểu được nó hay không mà thôi và trường hợp của np.random() cũng vậy. Bản thân máy tính do con người tạo ra, nên những quy tắc hoạt động của nó đều dựa trên những gì mà con người thiết kế. Về bản chất, hàm np.random() là một mô phỏng (simulation) các kịch bản có thể xảy ra do con người sử dụng thuật toán để lập trình ra. Cũng có nghĩa là, con người làm có mục đích nên không thể coi là random, mà nó là pseudo-random!

1 2 3 4

from datetime import datetime x= datetime.now().microsecond #một phần triệu giây rand = 2*x+3 rand #Output: 1748591

Ví dụ 5.4.4. Tạo ra 1 pseudo-random.

Trong hàm np.random(), có hai hàm con là np.random.random() và np.random.normal() tương ứng với hai kiểu phân phối quen thuộc khi học về xác suất thông kê, đó là:

Chương 5. Phát triển ứng dụng với Python 316

• Phân phối đồng nhất (Uniform Distribution) là dạng phân phối xác suất thống kê trong đó tất cả các kết quả đều có khả năng xảy ra như nhau, mỗi biến có cùng một xác suất để cho ra một kết quả. Ví dụ, việc tung đồng xu cũng có phân phối đồng nhất vì xác suất xuất hiện mặt ngửa hoặc mặt sấp trong một lần tung đồng xu là như nhau, với điều kiện đồng xu đó là đồng chất. • Phân phối chuẩn/Phân phối hình chuông (Normal Distribution) quyết định bởi mean và standard deviation với những đặc điểm sau:

Hình 5.42: Phân phối đồng nhất và phân phối chuẩn

1 2 3 4 5 6

np.random.random((3, 3)) #Output: array([[0.2732366 , 0.57810574, 0.66121708], [0.05618081, 0.18816189, # 0.63645469], [0.26861496, 0.85687507, 0.54761703]]) import matplotlib.pyplot as plt plt.hist(np.random.random(100), bins = 50) plt.show();

Ví dụ 5.4.5. Tạo mảng 3x3 theo phân phối đều với các giá trị nằm trong khoảng từ 0 đến 1.

Hình 5.43: (a) Phân phối đều với các giá trị nằm trong khoảng từ 0 đến 1; (b) Phân phối chuẩn với mean = 0, standard deviation = 1

Ví dụ 5.4.6. Tạo mảng 3x3 theo phân phối chuẩn với mean = 0, standard deviation = 1.

1 2 3 4 5 6

np.random.normal(0, 1, (3, 3)) #Output: array([[-0.52211353, 0.88670169, 3.13249774], # [-0.67565883,1.57298885,-0.80391285], # [-1.07727765, 0.3448225 , -0.47382779]]) plt.hist(np.random.normal(0, 1, (10000, 1))) plt.show();

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 317

1 2 3 4 5 6

np.random.seed(0) # seed for reproducibility -> trả về 1 giá trị như nhau x1 = np.random.randint(10, size=6) # mảng 1 chiều x2 = np.random.randint(10, size=(3, 4)) # mảng 2 chiều x3 = np.random.randint(10, size=(3, 4, 5)) # mảng 3 chiều np.savetxt(’test.txt’,arr_2d) #save array np.loadtxt(’test.txt’) #load array

5.4.2.6 Index, Slicing và xác xuất thông kê

Ví dụ 5.4.7. Sinh và lưu mảng.

Cắt lát và lập chỉ mục là hai khái niệm cơ bản trong Python giúp truy cập các phần tử cụ thể trong một chuỗi, chẳng hạn như danh sách, bộ hoặc chuỗi. Bằng cách sử dụng các kỹ thuật này, chúng ta có thể trích xuất chuỗi con từ chuỗi, lọc danh sách và trích xuất cột từ danh sách 2D, cùng nhiều thứ khác.

1 2 3

arr = np.linspace(1,16,16).reshape(4,4) # tạo 1 mảng arr #Output: array([[1.,2.,3.,4.], [5.,6.,7.,8.], [9.,10.,11.,12.],[13.,14.,15.,16.]])

Ví dụ 5.4.8. .

Hình 5.44: Index và Slicing

Ví dụ 5.4.9. Tính toán ma trận.

1 2 3 4 5 6 7

arr1 = np.array([[1,2], [2,3]]) arr2 = np.array([[10,10], [1,1]]) arr1 + arr2, arr1 - arr2 #Output: (array([[11, 12], [ 3, 4]]), array([[-9, -8], [ 1, 2]])) arr1 * arr2, arr1 / arr2, arr1 @ arr2 #element-wise vs matrix multiplication #Output: (array([[10, 20],[ 2, 3]]), array([[0.1, 0.2],[2. , 3. ]]), $ array([[12, 12],[23, 23]]))

Chương 5. Phát triển ứng dụng với Python 318

NumPy hỗ trợ 1 số hàm cơ bản để ta tính toán thống kê dữ liệu bao gồm: mean, median, min, max, std, count_nonzero, unique.

arr = np.linspace(1,12,12,dtype=’int’).reshape(3,4) arr #Output: array([[ 1, 2, 3, 4],[ 5, 6, 7, 8],[ 9, 10, 11, 12]]) np.mean(arr), np.median(arr) #Output: (6.5, 6.5) np.max(arr), np.min(arr), np.std(arr) #Output: (12, 1, 3.452052529534663) np.sum(arr), np.sum(arr, axis=0) #Output: (78, array([15, 18, 21, 24])) np.count_nonzero(arr) #Output: 12 np.unique(arr) #Output: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) np.unique(arr, return_counts = True) #Output: (array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]), # array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Ví dụ 5.4.10. Các hàm thống kê cơ bản.

arr = np.arange(10) np.where(arr < 5, arr, 10*arr) #Output: array([ 0, 1, 2, 3, 4, 50, 60, 70, 80, 90]) np.where(arr < 5, ’<5’, ’>=5’) #Output: array([’<5’,’<5’,’<5’,’<5’,’<5’,’>=5’,’>=5’,’>=5’,’>=5’,’>=5’], dtype=’5’)) #Output:array([’<5’,’<5’,’<5’,’<5’,’<5’,’=5’,’>5’,’>5’,’>5’,’>5’], dtype=’

1 2 3 4 5 6 7

Ví dụ 5.4.11. Hàm where() của NumPy như một phương pháp vector hóa để viết các câu lệnh if-else.

import numpy as np # Tạo mảng ngẫu nhiên có 10 phần tử từ 1 đến 100 random_array = np.random.randint(1, 101, 10) print(random_array)

1 2 3 4

Ví dụ 5.4.12. Tạo một mảng NumPy có 10 phần tử ngẫu nhiên từ 1 đến 100.

Ví dụ 5.4.13. Tính tổng, trung bình, và phương sai của mảng NumPy.

1 2 3 4 5 6 7 8 9 10 11 12 13

import numpy as np # Tạo mảng ngẫu nhiên có 10 phần tử từ 1 đến 100 random_array = np.random.randint(1, 101, 10) # Tính tổng các phần tử trong mảng total = np.sum(random_array) # Tính trung bình các phần tử trong mảng mean = np.mean(random_array) # Tính phương sai của mảng variance = np.var(random_array) print("Mảng ngẫu nhiên:", random_array) print("Tổng các phần tử trong mảng:", total) print("Trung bình các phần tử trong mảng:", mean) print("Phương sai của mảng:", variance)

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 319

1 2 3 4 5 6 7 8 9

import numpy as np # Tạo mảng ngẫu nhiên có 10 phần tử từ 1 đến 100 random_array = np.random.randint(1, 101, 10) print("Mảng ban đầu:") print(random_array) # Thay thế các giá trị lớn hơn 50 bằng 0 random_array[random_array > 50] = 0 print("Mảng sau khi thay thế:") print(random_array)

Ví dụ 5.4.14. Thay thế tất cả các giá trị lớn hơn 50 trong mảng bằng 0.

1 2 3 4

import numpy as np # Tạo mảng 2D có kích thước 3x3 với các giá trị từ 0 đến 8 matrix = np.arange(9).reshape(3, 3) print(matrix)

Ví dụ 5.4.15. Tạo một mảng 2D có kích thước 3x3 với các giá trị từ 0 đến 8.

1 2 3 4 5 6 7 8 9 10

import numpy as np # Tạo hai mảng NumPy 1D array1 = np.array([1, 2, 3]) array2 = np.array([4, 5, 6]) # Tính tích vô hướng sử dụng hàm np.dot() dot_product = np.dot(array1, array2) # Hoặc có thể sử dụng phương thức .dot(): dot_product = array1.dot(array2) print("Mảng 1:", array1) print("Mảng 2:", array2) print("Tích vô hướng của hai mảng:", dot_product)

Ví dụ 5.4.16. Tính tích vô hướng của hai mảng NumPy 1D.

5.4.3.1 Thư viện Pandas

5.4.3 Project 2. Phân tích và xử lý dữ liệu dạng bảng với thư viện Pandas

Pandas (viết tắt từ Panel Data - bảng dữ liệu) là thư viện mã nguồn mở phục vụ cho việc phân tích và xử lý dữ liệu trong Python, được phát triển bởi Wes McKinney trong năm 2008.

Chương 5. Phát triển ứng dụng với Python 320

Thư viện này được thiết kế để làm việc dễ dàng và trực quan với dữ liệu có cấu trúc (dạng bảng, đa chiều, ...) và dữ liệu chuỗi thời gian. Hiện nay, Pandas được sử dụng rộng rãi trong cả nghiên cứu lẫn phát triển các ứng dụng về khoa học dữ liệu.

5.4.3.2 Cài đặt và import thư viện Pandas

Pandas trở thành thư viện yêu thích của những nhà phân tích dữ liệu bởi vì phù hợp với nhiều loại dữ liệu khác nhau như dữ liệu dạng bảng, như trong bảng SQL hoặc bảng tính Excel; dữ liệu chuỗi thời gian theo thứ tự và không có thứ tự; dữ liệu ma trận tùy ý với nhãn hàng và cột. Dễ dàng thao tác, phân tích, xử lý và trực quan hoá dữ liệu với khả năng xử lý dữ liệu mất mát (NaN,...), nhiễu, khả năng thay đổi kích thước (chèn và xóa cột, dòng), khả năng căn chỉnh dữ liệu tự động và rõ ràng; khả năng phân tách, gộp nối, chuyển đổi, định hình các tập dữ liệu 1 cách linh hoạt giúp cho việc tổng hợp và phân tích dữ liệu nhanh gọn, dễ dàng hơn; Khả năng tải và lưu trữ dữ liệu theo nhiều format khác nhau: .csv, .txt, .excel, .pkl, .hdfs5, ...; Khả năng xử lý dữ liệu dạng chuỗi; Khả năng tích hợp tốt với các thư viện khác của Python: SciPy, Matplotlib, Seaborn, Plotly, Sklearn, ...

Cài đặt khi tạo môi trường ảo: conda create -n hanh python=3.7 pandas

5.4.3.3 Các hàm cơ bản trong Pandas

Cài đặt sau khi tạo xong môi trường ảo: conda install pandas hoặc pip install pandas Để import thư viện ta sử dụng lệnh sau: import pandas as pd

Objects trong Pandas có 2 khái niệm: • DataFrames: các bảng dữ liệu bao gồm nhiều hàng và nhiều cột, khởi tạo thông qua câu lệnh pd.DataFrame()

• Series: cột dữ liệu, khởi tạo thông qua câu lệnh pd.Series(). Bảng dữ liệu trong SQL gọi là bảng, Excel gọi là sheet, còn Python gọi đây là một DataFrame của Pandas. Hiểu đơn giản, Series là một cột của DataFrame. Ở mức máy tính thì Series là một object riêng và DataFrame là một object riêng. Tuy nhiên, có thể chuyển một Series thành DataFrame và chuyển DataFrame một cột thành Series.

Hình 5.45: Objects trong Pandas

Khởi tạo 1 DataFrame:

Ví dụ 5.4.17. Tạo ra 1 DataFrame rỗng.

1 2 3

df = pd.DataFrame() type(df) pandas.core.frame.DataFrame

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 321

dict1 = {’name’:[’Nhuong’,’Khuong’, ’Mai’, ’Minh’, ’Lam’],

1 2 3 4

’age’:[10,11,12,14,15], ’university’:[’MIT’,’Harvard’,’NYU’,’Paris13’,’MCU’]} df1 = pd.DataFrame(dict1, index=[f’student{i}’ for i in range(1,6)])

Ví dụ 5.4.18. Tạo ra 1 DataFrame có chứa dữ liệu.

li = [[’Nhuong’,10,’MIT’], [’Khuong’,11,’Havard’], [’Mai’,12,’NYU’],

[’Minh’,14,’Paris13’],[’Lam’,15,’MCU’]]

df2 = pd.DataFrame(li, columns=[’name’, ’age’, ’university’],

1 2 3 4

index=[f’student{i}’ for i in range(1,6)])

Ví dụ 5.4.19. Tạo ra 1 DataFrame từ list của list.

name = [’Nhuong’,’Khuong’, ’Mai’, ’Minh’, ’Lam’] age = [10,11,12,14,15] university = [’MIT’, ’Harvard’,’NYU’,’Paris13’,’MCU’] tuple_li = list(zip(name, age, university)) df3 = pd.DataFrame(tuple_li,columns = [’name’, ’age’,’university’],

1 2 3 4 5 6

index=[f’student{i}’ for i in range(1,6)])

Ví dụ 5.4.20. Tạo ra 1 DataFrame từ zip.

import numpy as np df1 = pd.DataFrame(np.linspace(1,16,16).reshape(4,4),

columns=[’col1’,’col2’,’col3’,’col4’])

df1 = pd.DataFrame(np.linspace(1,16,16).reshape(4,4),

1 2 3 4 5

columns=[f’col{i}’ for i in range(1,5)])

Ví dụ 5.4.21. Tạo từ 1 chuỗi numpy.

Khởi tạo 1 Series:

1 2 3

#Lấy các giá trị 1 cột trong DataFrame và truyền vào biến Series series = df2[’name’] # cách 1 series = df2.name # cách 2

Ví dụ 5.4.22. Khởi tạo 1 Series.

Đọc/lưu 1 DataFrame: Pandas hỗ trợ đọc nhiều format dữ liệu khác nhau, ví dụ như: excel, csv, sql, html, json, table, ... Ở đây, mình sẽ ví dụ với 1 kiểu dữ liệu được sử dụng phổ biến nhất, đó là .csv. csv là viết tắt của cụm từ commas seperated value, về bản chất là 1 file text lưu trữ các thông tin dạng bảng với các giá trị từng cột phân cách nhau bới dấu commas, tức là dấu phẩy. Có nhiều biến thể của file .csv, ví dụ .tsv tương ứng tab seperated value, ...

Chương 5. Phát triển ứng dụng với Python 322

1 2 3

df = pd.read_csv(’https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data’, header=None) import seaborn as sns tips_df = sns.load_dataset(’tips’) #dữ liệu từ github của seaborn.

5.4.3.4 Indexing và phân tích dữ liệu

Chúng ta có thể đọc file csv thông qua câu lệnh pd.read_csv() và lưu file tạo ra và thao tác thông qua câu lệnh pd.to_csv(). Tương tự như csv, các format dữ liệu khác cũng sẽ có cấu trúc câu lệnh trong Pandas tương tự như với csv. Dưới đây là 1 số ví dụ về đọc và lưu file với Pandas.

Để thuận tiện cho việc phân tích dữ liệu thông qua các hàm cơ bản Pandas hỗ trợ,chúng ta sử dụng dữ liệu tips trong buổi trước, có format như sau:

1 2 3

import pandas as pd # import thư viện pandas để phân tích dữ liệu import seaborn as sns # import thư viện seaborn để load dữ liệu tips_df = sns.load_dataset(’tips’)

Ví dụ 5.4.23. Dữ liệu mẫu phân tích.

Bảng 5.7: Dữ liệu mẫu phân tích với Pandas

total_bill

tip

sex

smoker

day

time

size

Female

0 1 2 3 4

16.99 10.34 21.01 23.68 24.59

1.01 1.66 Male 3.5 Male 3.31 Male 3.61

Female

No No No No No

Sun Sun Sun Sun Sun

Dinner Dinner Dinner Dinner Dinner

2 3 3 2 4

1

loc (location): df.loc[row_label,col_label], series.loc[row_label]

Indexing: Nếu muốn truy cập vào 1 phần tử cụ thể trong DataFrame hoặc Series thì Pandas có hỗ trợ [] để chọn các cột trong DataFrame và trả về 1 Series. Để chọn tất cả các dòng (slicing):

1

iloc (index location): df.iloc[row_index,col_index], series.iloc[row_index]

Khi đó, loc nhận tên của các hàng và cột và trả về 1 Series hoặc DataFrame. Có thể sử dụng loc để lấy toàn bộ hàng hoặc cột, cũng như các phần nhỏ của chúng.

Lúc này, iloc nhận các index của các hàng và cột và trả về 1 Series hoặc DataFrame. Tương tự như loc, chúng ta có thể sử dụng loc để lấy toàn bộ hàng hoặc cột, cũng như các phần nhỏ của chúng.

Để chọn 1 cell ta sử dụng at: df.at[row_label,col_label], at nhận tên của các hàng và cột, và trả về một giá trị dữ liệu duy nhất; iat: df.iat[row_index,col_index] thì iat nhận index của các hàng và cột và trả về một giá trị dữ liệu duy nhất.

Ví dụ 5.4.24. Lấy giá trị ở hàng thứ 2 cột total_bill (10.34) trong tips_df.

tips_df.loc[1,’total_bill’] #Output: 10.34 tips_df.iloc[1,0] #Output: 10.34 tips_df.at[1,’total_bill’] #Output: 10.34 tips_df.iat[1,0] #Output: 10.34

1 2 3 4

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 323

tips_df.loc[:5,:’sex’] # Gồm tên cột, hàng bắt đầu và tên cột, hàng kết thúc tips_df.iloc[:6,:3] #bao gồm index bắt đầu, không bao gồm index kết thúc

1 2

Ví dụ 5.4.25. Lấy DataFrame dưới đây từ tips_df.

tips_df.loc[0,] #tips_df.loc[0] tips_df.iloc[0,] #tips_df.iloc[0]

1 2

Ví dụ 5.4.26. Lấy hết thông tin của bảng ghi đầu tiên trong tips_df.

tips_df[’total_bill’].to_frame() # cách 1 pd.DataFrame(tips_df[’total_bill’]) # cách 2 tips_df[[’total_bill’]] # cách 3

1 2 3

Ví dụ 5.4.27. Lấy tất cả các thông tin cột total_bill trong tips_df và ép định dạng về DataFrame.

tips_df[[’sex’,’total_bill’]].head(5) # cách 1 tips_df.loc[:4,[’sex’,’total_bill’]] # cách 2 tips_df.iloc[:5,[2,0]] # cách 3

1 2 3

5.4.3.5 Masking/Filtering trong Pandas

Ví dụ 5.4.28. Lấy 5 dòng đầu của 2 cột sex và total_bill trong tips_df.

Trong thực tế, đối với một tập dữ liệu có cấu trúc, đôi khi chúng ta muốn lọc dữ liệu theo một số tiêu chí nhất định nhằm đáp ứng nhu cầu bài toán đề ra. Ví dụ, phân tích tập khách hàng nữ, phân tích tập khách hàng VIP có hoá đơn cao hơn một mức nhất định hay tổng hợp và chỉ trích xuất dữ liệu trong một khoảng thời gian cần để phân tích. Để đáp ứng nhu cầu trên, Pandas có một số cách phổ biến như sau:

• Sử dụng cấu trúc df_name.loc[conditions] • Sử dụng cấu trúc df_name[conditions] • Sử dụng hàm query().

tips_df.loc[tips_df[’sex’] == ’Female’] # cách 1 tips_df[tips_df[’sex’] == ’Female’] # cách 2 tips_df.query("sex == ’Female’") # cách 3

1 2 3

Ví dụ 5.4.29. Lọc tất cả các thông tin của những khác hàng là nữ trong tips_df.

tips_df[(tips_df[’sex’] == ’Female’) & (tips_df[’smoker’] == ’Yes’)] # cách 1 tips_df.loc[(tips_df[’sex’] == ’Female’) & (tips_df[’smoker’] == ’Yes’)] # cách 2 tips_df.query("sex == ’Female’ & smoker == ’Yes’") # cách 3

1 2 3

Ví dụ 5.4.30. Lọc tất cả các thông tin của những khác hàng là nữ có hút thuốc trong tips_df.

5.4.3.6 Tổng hợp dữ liệu (Aggregation)

Chương 5. Phát triển ứng dụng với Python 324

Trong Python, groupby() là một hàm linh hoạt trong Python cho phép chia dữ liệu thành các nhóm riêng biệt để thực hiện các phép tính nhằm phân tích tốt hơn, cũng hoàn toàn tương tự như groupby trong SQL. groupby() được xây dựng theo cơ chế 3 bước: • Split: Chia dữ liệu thành các nhóm dựa trên một số tiêu chí (ví dụ theo cột x trong ảnh mô tả ở dưới)

• Apply: Áp dụng một số phép tính toán cho từng nhóm một cách độc lập (ví dụ tính tổng các giá trị của từng nhóm trong cột x). Bước này có thể là 1 trong các thao tác dưới đây: – Tổng hợp (Aggregation/Reduction): đưa ra 1 số phân tích thống kê trong một nhóm như sum, mean, std, min, max, size, count ... của nhóm dữ liệu. – Chuyển đổi (Transformation): thực hiện một số tính toán nhóm như chuẩn hoá, lấp đầy các giá trị null ... – Lọc (Filteration): loại bỏ một số nhóm, ... • Combine: Kết hợp các kết quả vào một cấu trúc dữ liệu.

Hình 5.46: Tổng hợp dữ liệu (Aggregation)

Pandas hỗ trợ 13 chức năng tổng hợp sử dụng sau groupby() sau:

tips_df.groupby(’sex’).total_bill.mean() # riêng hoá đơn tips_df[’total_bill_tip’] = tips_df[’total_bill’] + tips_df[’tip’] #cả hoá đơn và tips tips_df.groupby(’sex’).total_bill_tip.mean()

1 2 3

Ví dụ 5.4.31. Tính trung bình số tiền mỗi giới tính trả khi ăn tại nhà hàng theo thống kê trong tips_df.

tips_df.groupby(’sex’).agg({’total_bill’:[’mean’,’min’,’max’],’tip’:[’mean’,’min’,’max’]}) # Ta có thể đổi tên cột bằng cách dưới đây tips_df.groupby(’sex’).agg(mean_total_bill=(’total_bill’,’mean’), mean_total_tip=(’tip’,’mean’))

1 2 3

Ví dụ 5.4.32. Tính số tiền lớn nhất, nhỏ nhất và trung bình hoá đơn và số tiền tips mỗi giới tính chi ra cho 1 bữa ăn tại nhà hàng theo thống kê trong tips_df.

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 325

Bảng 5.8: Các hàm tổng hợp dữ liệu (Aggregation) trong Pandas

Tên hàm

Ý nghĩa

mean() sum() size() count() std() var() sem() describe() first() last() nth() min() max():

Tính trung bình của các nhóm Tính tổng các giá trị của nhóm Tính kích thước nhóm Tính toán số lượng nhóm Độ lệch chuẩn của các nhóm Tính toán phương sai của các nhóm Sai số chuẩn của giá trị trung bình của các nhóm Tạo thống kê mô tả Tính toán giá trị đầu tiên của nhóm Tính giá trị cuối cùng của nhóm Lấy giá trị thứ n hoặc một tập hợp con nếu n là một danh sách Tính toán giá trị nhỏ nhất nhóm Tính toán giá trị lớn nhất nhóm

1

tips_df.groupby([’sex’,’smoker’])[[’total_bill’,’tip’]].mean()

Ví dụ 5.4.33. Tính số tiền trung bình trong hoá đơn và tips mỗi giới tính khi có hút thuốc và không hút thuốc chi ra cho 1 bữa ăn tại nhà hàng theo thống kê trong tips_df.

1

tips_df[tips_df[’time’] == ’Dinner’].groupby([’sex’,’smoker’])[[’total_bill’,’tip’]].mean()

Ví dụ 5.4.34. Tính số tiền trung bình trong hoá đơn và tips mỗi giới tính khi có hút thuốc và không hút thuốc chi ra cho 1 bữa ăn tối tại nhà hàng theo thống kê trong tips_df.

Pivot: Nếu như đã từng làm việc với Excel chắc hẳn không lạ gì với Pivot Table. Tương tự như Pivot Table trong Excel, Pandas hỗ trợ ta tổng hợp, trích lọc, phân tích dữ liệu dễ dàng và nhanh chóng với pivot_table(). pivot_table() khá tương đồng với groupby() bởi cùng theo nguyên lý split-apply-combine giống nhau, tuy nhiên dữ liệu sẽ được phân tích và tổng hợp dưới với pivot_table() đa chiều (mulitdimensional) chứ không phải là một chiều như groupby().

Một số tham số cần lưu ý: • data: DataFrame • values (optional): cột để tổng hợp • index: cột, group hoặc mảng. Nếu mảng truyền vào thì phải có độ dài bằng với dữ liệu. • columns: cột, Group hoặc mảng. Tương tự như index • aggfunc: (default: mean): hàm tổng hợp dữ liệu • fill_value: giá trị được điền vào các ô dữ liệu NA (sau khi đã tính toán) • margins: (bool, default: False). Thêm một cột tính tất cả các giá trị của các cột còn lại theo hàm tổng hợp

• margins_name (string, default: ’All’): Tên của cột margins • dropna: (bool, default: False). Bỏ đi các hàng có chứa NA

Chương 5. Phát triển ứng dụng với Python 326

• observed: (bool, default: False). Chỉ áp dụng nếu tất cả các nhóm dữ liệu đều là Categoricals. Nếu là True: chỉ hiển thị các giá trị quan sát được cho các nhóm phân loại. Nếu là False: hiển thị tất cả các giá trị cho các nhóm phân loại.

1

tips_df.pivot_table(values=’total_bill_tip’, index=’sex’, aggfunc=’mean’)

Ví dụ 5.4.35. Tính trung bình số tiền mỗi giới tính trả khi ăn tại nhà hàng theo thống kê trong tips_df.

1

tips_df.pivot_table(values=’total_bill’, index=’day’, columns=’time’,aggfunc=’sum’)

5.4.3.7 Hợp nhất dữ liệu (Merge, Concat)

Ví dụ 5.4.36. Tính tổng số tiền nhà hàng thu được không kể tips các ngày trong tuần theo bữa ăn được thống kê trong tips_df.

Merge: Pandas có đầy đủ tính năng, hiệu suất cao trong hoạt động in-memory join rất giống với SQL thông qua hàm merge(). Dưới đây là một số so sánh giữa phương pháp sử dụng trong Pandas và trong SQL và hình ảnh minh hoạ để có thể thấy rõ sự tương đồng này.

Bảng 5.9: So sánh giữa phương pháp sử dụng trong Pandas và trong SQL

Methods

SQL Join Name

Meaning

_merge

left right outer inner

Chỉ sử dụng keys bên trái LEFT OUTER JOIN RIGHT OUTER JOIN Chỉ sử dụng keys bên phải FULL OUTER JOIN INNER JOIN

Sử dụng keys của cả 2 dataframes Chỉ sử dụng keys giao nhau của 2 dataframes

left_only right_only both both

Hình 5.47: Hợp nhất dữ liệu trong Pandas

1 2 3 4 5 6

left = tips_df.head(6)[[’total_bill’,’tip’]].reset_index() right = tips_df.loc[4:8][[’tip’,’sex’]].reset_index() left.merge(right, on=[’index’,’tip’], how=’left’) left.merge(right, on=[’index’,’tip’], how=’right’) left.merge(right, on=[’index’,’tip’], how=’inner’) left.merge(right, on=[’index’,’tip’], how=’outer’)

Ví dụ 5.4.37. Hợp nhất dữ liệu trong Pandas.

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 327

1

pd.concat([tips_df.head(3),tips_df.tail(3),tips_df.sample(3)[[’total_bill’,’tip’,’sex’]]])

Concat: Trong thực tế, chúng ta có thể làm việc với các dữ liệu có cấu trúc cùng 1 format (bao gồm các cột tương đồng nhau) nhưng được chia nhỏ thành các file khác nhau. Để có thể thuận lợi đánh giá được dữ liệu 1 cách tổng quan nhất, ta cần nối các dữ liệu có cấu trúc này với nhau và Pandas hỗ trợ ta đắc lực thông qua hàm pd.concat(). Dưới đây là 1 ví dụ về cách thức hàm hoạt động.

5.4.4.1 Thư viện SciPy

5.4.4 Project 3. Xử lý mô hình hóa, tối ưu thống kê với SciPy

Scipy là phần mềm nguồn mở cho toán học, khoa học và kỹ thuật. Thư viện SciPy được xây dựng dựa trên thư viện NumPy, cung cấp thao tác mảng N chiều thuận tiện và nhanh chóng. SciPy gồm các gói con (submodule) cho đại số tuyến tính, tối ưu hóa, tích hợp và thống kê.

1

python-m pip install --user numpy scipy matplotlib ipython jupyter pandas sympy nos

Cài đặt thư viện SciPy thông qua các phân phối: Anaconda, Miniconda, WinPython, Pyzo. Sử dụng pip: python-m pip install --user scipy. Chúng ta có thể cài đặt cùng lúc nhiều thư viện với pip:

5.4.4.2 Các hàm cơ bản trong thư viện SciPy

Lưu ý, Numpy phải được cài đặt trước, nên cài đặt Matplotlib khi sử dụng Scipy.

1 2 3 4

from scipy import special import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt

Khai báo thư viện: Để đơn giản và thuận tiện, các gói con của thư viện Scipy và các thư viện Numpy, Matplotlib thường được khai báo dưới dạng:

Trong đó, special là một gói con của Scipy. Các gói con khác được khai báo tương tự. Các hàm cơ bản: Scipy được xây dựng trên Numpy nên bạn có thể sử dụng các hàm của Numpy để thực hiện tất cả các thao tác array cơ bản. Chi tiết về các hàm này có thể tìm ở NumPy Reference Guide hoặc sử dụng các lệnh help, info và source. Bên dưới là ví dụ về một số thao tác array cơ bản.

>>> import numpy as np # khai báo numpy >>> np.mgrid[0:5,0:4] # Hàm mrid() array([[[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]], [[0, 1, 2, 3],[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]])

1 2 3 4 5 6 7 8 9

>>> # Hàm mrid() số ảo >>> np.mgrid[0:5:4j,0:4:3j] array([[[0. , 0. , 0. ], [1.66666667, 1.66666667, 1.66666667], [3.33333333, 3.33333333, 3.33333333], [5. , 5. , 5. ]], [[0. , 2. , 4. ],[0. , 2. , 4. ],

Ví dụ 5.4.38. Thao tác array viết trong Python Shell.

[0. , 2. , 4. ], [0. , 2. , 4. ]]])

>>> from numpy import poly1d # Hàm đa thức >>> p = poly1d([2,6]) >>> print(p) 2 x + 6 >>> print(p*p) # Bình phương hàm p

2

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

4 x + 24 x + 36 >>> print(p.deriv()) # Đạo hàm của p 2 >>> # Giá trị p tại x = 1, 2, 10 >>> p([1,2,10]) array([ 8, 10, 26]) >>> # Hàm select() để lấy ra array theo điều kiện >>> x = np.arange(15) >>> dieu_kien = [x< 10, x>=5] >>> chon_ra = [x, x**3] >>> np.select(dieu_kien, chon_ra) array([ 0, 1, 8, 27, 64, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]) >>> dieu_kien = [x>12, x<3] >>> np.select(dieu_kien, chon_ra) array([ 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14]) >>>

5.4.4.3 Các gói con của Scipy

Chương 5. Phát triển ứng dụng với Python 328

Việc sử dụng thư viện SciPy yêu cầu (hoặc tùy chọn phụ thuộc vào) một số thư viện khác để hoạt động, phụ thuộc chính là Python và NumPy. Nó đòi hỏi một bộ sưu tập lớn hơn các thư viện và công cụ để xây dựng thư viện hoặc xây dựng tài liệu. Các công cụ và thư viện luôn thay đổi. SciPy nhằm mục đích tương thích với một số bản phát hành của các thư viện và công cụ phụ thuộc. Việc buộc cơ sở người dùng đến các thành phần khác để nâng cấp cho mỗi bản phát hành sẽ làm giảm đáng kể giá trị của SciPy. Tuy nhiên, việc duy trì khả năng tương thích ngược với các công cụ / thư viện cũ đặt ra những hạn chế trong đó các chức năng và khả năng mới hơn có thể được kết hợp. SciPy có một cách tiếp cận có phần bảo thủ là duy trì khả năng tương thích với một số bản phát hành chính của Python và NumPy trên các nền tảng chính. Do đó người dùng cần chú ý sự tương thích giữa phiên bản của các thư viện khác có liên quan với phiên bản của Scipy. Những thông tin được tổng hợp ở mục Toolchain Roadmap của tài liệu hướng dẫn Scipy.

Scipy có nhiều gói con và liên tục được phát triển, bổ sung tính năng mới.

Scipy sắp tới sẽ phát triển hỗ trợ BLAS và LAPACK, thêm mảng sparse bên cạnh ma trận sparse, cải tiến biến đổi Fourier, hỗ trợ cho mảng phân tán và mảng GPU, cải thiện các bản dựng nguồn (source builds) trên Windows và các cải tiến thống kê. Mỗi gói con đều được đội đóng góp (Contribute) xây dựng lộ trình phát triển riêng.

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 329

Bảng 5.10: Tổng hợp các gói con của Scipy

gói con

Miêu tả

Thuật toán phân cụm (Clustering Algorithms) Các hằng số toán học và vật lý Hàm biến đổi Fourier nhanh (Fast Fourier Transform) Giải phương trình vi phân và tích phân

cluster constants fftpack integrate interpolate Nội suy và làm mịn spline io linalg ndimage odr optimize signal sparse spatial special stats

Đầu vào và đầu ra Đại số tuyến tính Xử lý ảnh N chiều Hồi quy khoảng cách trực giao Tối ưu hóa và chương trình root-finding Xử lý tín hiệu Ma trận sparse và các đoạn chương trình liên quan Các cấu trúc dữ liệu không gian và thuật toán Các hàm toán học đặc biệt Các hàm và phân phối thống kê

5.4.4.4 Gói phân cụm (scipy.cluster)

Các thuật toán phân cụm rất hữu ích trong lý thuyết thông tin, phát hiện mục tiêu, truyền thông, nén và các lĩnh vực khác. scipy.cluster gồm scipy.cluster.vq và scipy.cluster.hierarchy. Phân cụm K-mean và lượng tử hóa vestor (scipy.cluster.vq): Thuật toán k-mean lấy đầu vào số lượng cụm để tạo k và một tập các vectơ quan sát thành cụm. Nó trả về một tập hợp các trọng tâm (centroid), một trọng tâm cho mỗi cụm k. Một vectơ quan sát được phân loại với số cụm hoặc chỉ số trọng tâm của trọng tâm gần nó nhất.

Một vectơ v thuộc cụm i nếu nó gần với trọng tâm i hơn bất kỳ trọng tâm nào khác. Nếu v thuộc về i, chúng ta nói trọng tâm i là trọng tâm thống trị của v. Thuật toán k-mean cố gắng giảm thiểu biến dạng, được định nghĩa là tổng khoảng cách bình phương giữa mỗi vectơ quan sát và trọng tâm thống trị của nó. Việc giảm thiểu đạt được bằng cách phân loại lại các quan sát thành các cụm và tính toán lại các trọng tâm cho đến khi đạt được một cấu hình trong đó các trọng tâm được ổn định. Người ta cũng có thể định nghĩa một số lần lặp tối đa. Các hàm hiện tại trong scipy.cluster.vq là whiten(), vq(), kmeans() và kmeans2(). Bên dưới là một số ví dụ cho môđun này.

>>> #hàm whiten()-Chuẩn hóa một nhóm quan sát trên cơ sở từng tính năng. >>> import numpy as np >>> from scipy.cluster.vq import whiten >>> features = np.array([[2.9, 3.3, 4.7], [7.5, 6.5, 7.2],[0.8, 0.1, 0.7,]]) >>> whiten(features) array([[1.03644899, 1.26301815, 1.75565531], [2.68047153, 2.48776302, 2.68951452], [0.28591696, 0.03827328, 0.26148058]])

1 2 3 4 5 6 7 8 9

>>> # hàm vq - Gán mã từ một cuốn sách mã cho các quan sát.

Ví dụ 5.4.39. Các hàm trong scipy.cluster.vq.

10 11 12 13 14

>>> from scipy.cluster.vq import vq >>> code_book = np.array([[1.,1.,1.,],[2.,1.,1.]]) >>> vq(features, code_book) (array([1, 1, 0]), array([4.44859528, 9.9468588 , 0.96953597])) >>> # hàm kmeans - Thực hiện k-mean trên một tập các vectơ quan sát tạo thành các cụm k >>> from scipy.cluster.vq import vq, kmeans, whiten >>> import matplotlib.pyplot as plt >>> features = np.array([[],]) >>> from numpy import random >>> features = np.array([[ 1.3,2.2],[ 2.1,2.4],[ 0.4,0.6],

[ 0.3,2.8],[ 0.1,0.2],[ 0.2,1.4], [ 2.0,0.1],[ 4.3,3.9],[ 3.0,4.0]])

>>> whitened = whiten(features) >>> book = np.array((whitened[0],whitened[1])) >>> kmeans(whitened,book) (array([[0.52090714, 0.86997969],[2.27745447, 2.45501118]]), 0.8168475927077372) >>> >>> random.seed((500,1500)) >>> codes = 4 >>> kmeans(whitened,codes) (array([[0.89644484, 1.76379444],[1.45369434, 0.07150518],[2.65299217, 2.82445461],

[0.16959767, 0.52437132]]), 0.39112017893552065)

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

>>> pts = 60 # Tạo 60 điểm dữ liệu trong 2 cụm a và b >>> a = np.random.multivariate_normal([0, 0], [[4, 1], [1, 4]], size=pts) >>> b = np.random.multivariate_normal([20, 10], [[14, 2], [2, 1]], size=pts) >>> features = np.concatenate((a, b)) >>> # Whiten dữ liệu >>> whitened = whiten(features) >>> # Tìm 2 cụm dữ liệu >>> codebook, distortion = kmeans(whitened, 2) >>> # Vẽ Whiten dữ liệu và tâm cụm (màu đỏ) >>> plt.scatter(whitened[:, 0], whitened[:, 1]) >>> plt.scatter(codebook[:, 0], codebook[:, 1], c=’r’) >>> plt.show() >>># hàm k-mean2 >>> from scipy.cluster.vq import kmeans2 >>>#Tạo mảng z có hình dạng (100,2) chứa hỗn hợp các mẫu từ 3 phân phối đa biến. >>> np.random.seed(12345678) >>> a = np.random.multivariate_normal([0, 6], [[2, 1], [1, 2.5]], size=45) >>> b = np.random.multivariate_normal([1, 0], [[1, -1], [-1, 3]], size=35) >>> c = np.random.multivariate_normal([6, 5], [[4, 0], [0, 1.]], size=25) >>> z = np.concatenate((a, b, c)) >>> np.random.shuffle(z) >>> # Tính toán 3 cụm >>> centroid, label = kmeans2(z, 3, minit=’points’) >>> centroid array([[ 6.17155178, 4.85018346],

Chương 5. Phát triển ứng dụng với Python 330

[ 0.89380981, -0.14430193], [ 0.03293515, 6.16629408]])

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

>>> # Số điểm trong mỗi cụm >>> counts = np.bincount(label) >>> counts array([24, 35, 46], dtype=int64) >>> # Vẽ các cụm >>> w0 = z[label == 0] >>> w1 = z[label == 1] >>> w2 = z[label == 2] >>> plt.plot(w0[:, 0], w0[:, 1], ’o’, alpha=0.5, label=’cụm 1’) [] >>> plt.plot(w1[:, 0], w1[:, 1], ’s’, alpha=0.5, label=’cụm 2’) [] >>> plt.plot(w2[:, 0], w2[:, 1], ’d’, alpha=0.5, label=’cụm 3’) [] >>> plt.plot(centroid[:, 0], centroid[:, 1], ’ro’, label=’tâm’) [] >>> plt.axis(’equal’) (-3.2328087766702582, 8.417272880962955, -3.9724381733346927, 10.306803368482795) >>> plt.legend(shadow=True) >>> plt.show()

5.4 Phát triển các ứng dụng xử lý dữ liệu với Python 331

5.4.4.5 Gói biến đổi Fourier (scipy.fft, scipy.fftpack)

Hình 5.48: Kết quả phân cụm (a) kmean() và (b) kmean2()

Gói scipy.fftpack là gói biến đổi Fourier được phát triển trước, nay trở thảnh di sản và được thay thế bằng gói scipy.fft. Gói scipy.fft có đa dạng các hàm giúp giải quyết dễ dàng biến đổi Fourier. Gói được phân thành các nhóm hàm:

• Biến đổi Fourier nhanh (FFTs) gồm 18 hàm như fft(), ifft(), fft2(), v.v. • Biến đổi Sin và Cosine rời rạc (DST và DCT) gồm 8 hàm như dct(), idct(), dctn(), v.v. • Các chức năng trợ giúp với 7 hàm như fftshift(), fftfreq(), rfftfreq(), v.v.

Chương 5. Phát triển ứng dụng với Python 332

• Kiểm soát backend như set_backend(), skip_backend(), set_global_backend() và register_backend().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

from matplotlib import pyplot as plt import numpy as np fre = 10 # Tạo hàm trpng miền thời gian. Tần số theo đơn vị Hz fre_samp = 100 #Tỉ lệ mẫu #Thời gian t = np.linspace(0, 2, 2 * fre_samp, endpoint = False ) # Hàm sin(f*2pi*t)+ cos(2f*2pi*t) a = np.sin(fre * 2 * np.pi * t) + np.cos(2*fre * 2 * np.pi * t) figure, axis = plt.subplots() # Vẽ hàm axis.plot(t, a) axis.set_xlabel (’Thời gian (s)’) axis.set_ylabel (’Cường độ tín hiệu’) plt.figure(1) from scipy import fft # Sử dụng hàm fft chuyển sang miền tần số A = fft.fft(a) # Thực hiện biến đổi fft frequency = fft.fftfreq(len(a)) * fre_samp figure, axis = plt.subplots() # Vẽ hàm trong miền tần số axis.stem(frequency, np.abs(A), use_line_collection=True) axis.set_xlabel(’Tần số (Hz)’) axis.set_ylabel(’Độ lớn phổ tần số’) axis.set_xlim(-fre_samp / 2, fre_samp/ 2) axis.set_ylim(-5, 120) plt.show()

Ví dụ 5.4.40. Biến đổi Fourier nhanh bằng hàm fft lên hàm a(t) = sin(10 ∗ 2πt) + cos(20 ∗ 2πt).

Hình 5.49: hàm số trong miền thời gian (a) và hàm số trong miền tần số

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 333

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python

5.5.1.1 Thư viện TensorFlow

5.5.1 Project 1. Phát triển ứng dụng với TensorFlow

TensorFlow là một trong những thư viện Machine learning và Deep learning hàng đầu hiện nay. Nó đã trở thành công cụ quan trọng không thể thiếu đối với các nhà phát triển và nhà nghiên cứu trong lĩnh vực trí tuệ nhân tạo. Với khả năng xử lý dữ liệu lớn và xây dựng mô hình dự đoán chính xác, TensorFlow đang ngày càng trở nên phổ biến, đồng thời có ảnh hưởng lớn đến nhiều lĩnh vực khác nhau.

Cách thức hoạt động của TensorFlow: TensorFlow là một thư viện tính toán số và biểu diễn dữ liệu bằng cấu trúc đồ thị (Graph) để tạo và huấn luyện các mô hình học máy. Các đồ thị này bao gồm các nút (Nodes) và các cạnh (Edges) được sử dụng để biểu diễn các phép tính và dữ liệu tương ứng trong mô hình. Một cách tổng quát, quá trình huấn luyện mô hình học máy trong TensorFlow trải qua các bước sau:

• Bước 1. Xây dựng đồ thị tính toán: Trước khi huấn luyện mô hình, việc xây dựng đồ thị tính toán là bước quan trọng đầu tiên. Đây là nơi mà các phép tính và quá trình huấn luyện được định nghĩa và tổ chức.

• Bước 2. Định nghĩa hàm mất mát: Sau khi xây dựng đồ thị, bước tiếp theo là định nghĩa hàm mất mát để đánh giá hiệu suất của mô hình. Hàm mất mát đo lường sự khác biệt giữa dự đoán của mô hình và giá trị thực tế của dữ liệu đầu vào.

• Bước 3. Tối ưu hóa mô hình: Sau khi định nghĩa hàm mất mát, quá trình tối ưu hóa mô hình bắt đầu. Mục tiêu là điều chỉnh các tham số của mô hình để giảm thiểu hàm mất mát và cải thiện hiệu suất dự đoán.

• Bước 4. Huấn luyện mô hình: Quá trình huấn luyện mô hình là giai đoạn mà mô hình học từ dữ liệu huấn luyện. Các tham số của mô hình được điều chỉnh dần dần để tối ưu hóa hiệu suất dự đoán trên dữ liệu mới.

• Bước 5. Đánh giá mô hình: Sau khi huấn luyện xong, mô hình cần được đánh giá để xác định hiệu suất và độ chính xác của nó trên dữ liệu kiểm tra. Kết quả này giúp đánh giá khả năng dự đoán của mô hình trong thực tế.

• Bước 6. Sử dụng mô hình: Sau khi mô hình đã được huấn luyện và đánh giá, nó có thể được sử dụng để dự đoán kết quả trên dữ liệu mới. Quá trình này giúp áp dụng mô hình học máy vào các vấn đề thực tế, đồng thời tối ưu hóa quá trình ra quyết định.

Chương 5. Phát triển ứng dụng với Python 334

Hình 5.50: Thư viện Machine Learning - TensorFlow

Các thuộc tính cơ bản của TensorFlow: • Tensors: TensorFlow là thư viện mã nguồn mở được phát triển bởi Google dành cho việc xây dựng và huấn luyện các mô hình máy học. Một trong những khái niệm cơ bản nhất trong TensorFlow là Tensor. Tensors là cấu trúc dữ liệu chính để lưu trữ dữ liệu trong TensorFlow. Chúng có thể được xem như các mảng nhiều chiều với số chiều tùy ý. • Operations: Thuộc tính Operations trong TensorFlow là gì? Nó là các phép toán hay có thể hiểu đơn giản là các thao tác được thực hiện trên các Tensors để tạo ra các biến thể mới. Các phép toán này có thể là các phép toán số học đơn giản như cộng, trừ, nhân, chia hoặc các phép toán phức tạp hơn như ma trận nhân, tích vô hướng hay các phép toán logic.

• Variables: Trong TensorFlow, Variables là các thực thể có thể thay đổi giá trị trong quá trình huấn luyện mô hình. Chúng được sử dụng để lưu trữ trọng số và độ lệch của mô hình máy học. Khi huấn luyện mô hình, các biến này được cập nhật liên tục để tối ưu hóa hiệu suất của mô hình.

• Graphs: Graphs hay còn gọi là đồ thị, nó là một phần quan trọng của TensorFlow. Mỗi Nodes trong đồ thị đại diện cho một phép tính hoặc biến, trong khi Edges (cạnh) đại diện cho dữ liệu được truyền qua các Nodes. Với Graphs, bạn có thể xây dựng và quản lý các mô hình máy học phức tạp.

• Sessions: Sessions trong TensorFlow là gì? Đây là môi trường thực thi cho các phép tính trong mô hình. Khi bạn muốn thực hiện tính toán trong TensorFlow, bạn cần tạo một Session và chạy các Nodes trong đồ thị tính toán. Sessions giúp bạn tối ưu hóa việc sử dụng tài nguyên tính toán và quản lý bộ nhớ hiệu quả.

• Placeholders: Placeholders trong TensorFlow là các biến mà bạn có thể truyền dữ liệu vào trong quá trình huấn luyện mô hình. Có thể hiểu các Placeholders dùng để chứa dữ liệu đầu vào và đưa dữ liệu vào mô hình một cách linh hoạt. Điều này giúp bạn dễ dàng thay đổi dữ liệu đầu vào mà không cần phải thay đổi cấu trúc của mô hình.

Ưu điểm sử dụng TensorFlow để xây dựng máy học: • Hỗ trợ nhiều nền tảng: TensorFlow hỗ trợ nhiều nền tảng khác nhau, nghĩa là bạn có thể

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 335

xây dựng và triển khai các mô hình máy học trên nhiều thiết bị khác nhau mà không gặp bất kỳ rắc rối nào. Điều này rất hữu ích khi bạn muốn triển khai ứng dụng máy học trên các thiết bị di động, máy tính cá nhân hoặc trên dữ liệu đám mây.

• Hiệu suất cao: Một trong những lý do quan trọng khiến bạn nên sử dụng TensorFlow là gì? Đó chính là hiệu suất cao. TensorFlow được thiết kế để xử lý các phép tính phức tạp một cách hiệu quả, giúp tăng tốc quá trình huấn luyện và triển khai mô hình máy học. Nó giúp cho việc phát triển ứng dụng máy học trở nên nhanh chóng và hiệu quả hơn. • Được sử dụng rộng rãi: TensorFlow là thư viện mã nguồn mở được sử dụng rộng rãi, đặc biệt là trong trong cộng đồng máy học và trí tuệ nhân tạo. Bởi vì nó mang lại lợi ích lớn cho người dùng khi có thể tìm kiếm sự hỗ trợ nhanh chóng, đồng thời cung cấp nguồn lực và tài nguyên để phát triển ứng dụng của bạn.

• Hỗ trợ mạnh mẽ cho các mô hình học sâu: Với TensorFlow ta có thể dễ dàng triển khai các mô hình học máy phức tạp, từ các mạng nơron cơ bản cho đến các mô hình học sâu sâu hơn như mạng nơron tích chập và mạng nơron hồi quy. Thư viện này cung cấp một loạt các công cụ và API linh hoạt giúp tối ưu hóa hiệu suất mô hình.

• API linh hoạt: TensorFlow cung cấp một loạt các API linh hoạt cho việc xây dựng và triển khai các mô hình học máy. Các API này cho phép dễ dàng tạo ra các biến thể của các mô hình học máy phức tạp mà không cần phải viết mã từ đầu. Ngoài ra, TensorFlow cũng hỗ trợ nhiều ngôn ngữ lập trình khác nhau như Python, C++ và Java, giúp bạn linh hoạt trong việc lựa chọn ngôn ngữ phù hợp.

5.5.1.2 Các công cụ ứng dụng TensorFlow

Tải về TensorFlow tại địa chỉ sau: https://github.com/tensorflow/tensorflow

Các công cụ đang ứng dụng TensorFlow hiện nay trong lĩnh vực trí tuệ nhân tạo có thể kể đến gồm:

• Keras: Keras là một API mã nguồn mở được tích hợp sâu vào TensorFlow, giúp đơn giản hóa quá trình xây dựng mô hình học máy. Với Keras, người dùng có thể nhanh chóng tạo ra các mô hình phức tạp mà không cần phải lo lắng về các chi tiết kỹ thuật.

• TensorBoard: TensorBoard là một công cụ hữu ích được tích hợp sẵn trong TensorFlow, giúp người dùng theo dõi và hiểu rõ hơn về quá trình huấn luyện mô hình. Với các đồ thị và biểu đồ trực quan, người dùng có thể phân tích kết quả cũng như điều chỉnh mô hình một cách dễ dàng.

• TensorFlow Hub: TensorFlow Hub cung cấp một kho lưu trữ các mô hình đã được huấn luyện sẵn, giúp người dùng tiết kiệm thời gian và công sức trong việc xây dựng mô hình mới. Nhờ các mô hình này, người dùng có thể nhanh chóng ứng dụng chúng vào mô hình của mình một cách dễ dàng.

• TensorFlow Lite: TensorFlow Lite là một phiên bản nhỏ gọn của TensorFlow, được thiết kế để chạy trên các thiết bị di động như điện thoại thông minh và máy tính bảng. Điều này giúp tối ưu hóa hiệu suất, đồng thời cho phép ứng dụng sử dụng trí tuệ nhân tạo ngay trên thiết bị của người dùng mà không cần kết nối mạng.

Chương 5. Phát triển ứng dụng với Python 336

• TensorFlow.js: TensorFlow.js là thư viện JavaScript mã nguồn mở, cho phép phát triển mô hình trí tuệ nhân tạo và huấn luyện trực tiếp trên trình duyệt web. Do đó, nó mang lại sự linh hoạt và tiện lợi cho các nhà phát triển, giúp họ tích hợp trí tuệ nhân tạo vào ứng dụng web một cách dễ dàng hơn.

5.5.1.3 Các thuật toán nổi bật được hỗ trợ bởi TensorFlow

• TensorFlow Extended (TFX): Là nền tảng giúp tự động hóa quy trình máy học từ đầu đến cuối. TFX cung cấp các công cụ và thư viện để xử lý dữ liệu, huấn luyện mô hình, triển khai và quản lý mô hình. Từ đó, giúp tăng cường hiệu suất và tiết kiệm thời gian cho các nhà phát triển và nhà nghiên cứu.

Các thuật toán nổi bật được hỗ trợ bởi TensorFlow trong lĩnh vực trí tuệ nhân tạo có thể kể đến gồm:

• Linear Regression: Là thuật toán đơn giản, giúp người dùng nhanh chóng tiếp cận và hiểu rõ về cách hoạt động của mô hình. Ngoài ra, Linear Regression cũng phù hợp với các bài toán có dữ liệu liên quan đến các mối quan hệ tuyến tính, giúp dự đoán chính xác giá trị đầu ra.

• Classification: TensorFlow cung cấp nhiều Classification (thuật toán phân loại) như Support Vector Machine, Random Forest và Neural Networks. Sử dụng TensorFlow, người dùng có thể xây dựng các mô hình phân loại chính xác và linh hoạt cho các bài toán phức tạp.

• Deep Learning Classification: Sử dụng các mạng nơ-ron sâu để học và dự đoán dữ liệu, giúp cải thiện độ chính xác và hiệu suất của mô hình. Đồng thời, Deep Learning có khả năng xử lý các dữ liệu lớn và phức tạp, từ đó giúp người dùng áp dụng mô hình cho các bài toán thực tế.

• Deep Learning Wipe and Deep: TensorFlow cung cấp rất nhiều thuật toán nổi bật. Một số thuật toán Deep Learning phổ biến như Neural Networks, Convolutional Neural Networks (CNN), Recurrent Neural Networks (RNN) đều được TensorFlow hỗ trợ. • Booster Tree Regression: Thuật toán Booster Tree Regression là một trong những phương pháp quan trọng trong Machine Learning để dự đoán giá trị của một biến liên tục. TensorFlow cung cấp một số công cụ để xây dựng và tinh chỉnh các mô hình Booster Tree Regression, giúp tối ưu hoá hiệu suất cũng như độ chính xác của mô hình.

5.5.1.4 Tạo và huấn luyện một mạng neural với TensorFlow

• Boosted Tree Classification: Trong bài toán phân loại, Boosted Tree Classification là phương pháp hiệu quả để phân loại dữ liệu vào các nhóm khác nhau. TensorFlow cung cấp các thuật toán tiên tiến như Gradient Boosting, XGBoost để hỗ trợ việc xây dựng các mô hình phân loại chất lượng cao và chính xác.

1 2

import tensorflow as tf import numpy as np

- Bước 1. Nhập TensorFlow và các thư viện liên quan:

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 337

1 2 3

# Tạo dữ liệu giả định X_train = np.array([[1.0, 2.0], [2.0, 3.0], [3.0, 4.0]]) y_train = np.array([0, 1, 1])

- Bước 2. Chuẩn bị dữ liệu huấn luyện: Trước hết, chúng ta cần chuẩn bị dữ liệu huấn luyện và dữ liệu kiểm tra. Trong ví dụ này, chúng ta sẽ tạo dữ liệu giả định để minh họa:

1 2 3 4 5 6

# Tạo một Sequential model model = tf.keras.Sequential() # Thêm một lớp Dense với 2 đầu ra (units) và hàm kích hoạt sigmoid model.add(tf.keras.layers.Dense(units=2, activation=’sigmoid’, input_dim=2)) # Thêm lớp đầu ra với hàm kích hoạt softmax (vì đây là bài toán phân loại) model.add(tf.keras.layers.Dense(units=2, activation=’softmax’))

- Bước 3. Xây dựng mô hình mạng nơron:

1 2

# Biên dịch mô hình với hàm loss và optimizer model.compile(loss=’sparse_categorical_crossentropy’,optimizer=’adam’,metrics=[’accuracy’])

- Bước 4. Biên dịch mô hình:

1 2

# Huấn luyện mô hình với dữ liệu huấn luyện model.fit(X_train, y_train, epochs=100)

- Bước 5. Huấn luyện mô hình

1 2 3 4 5

# Đánh giá mô hình với dữ liệu kiểm tra (nếu có) # X_test và y_test là dữ liệu kiểm tra thực tế loss, accuracy = model.evaluate(X_test, y_test) print("Loss =", loss) print("Accuracy =", accuracy

- Bước 6. Đánh giá mô hình (tùy chọn).

5.5.2.1 Thư viện Deep Learnin - Keras

5.5.2 Project 2. Phát triển ứng dụng với Keras

Keras được ra mắt vào năm 2015 và tác giả là Franc¸ois Chollet, nhà nghiên cứu và kỹ sư nổi tiếng trong lĩnh vực trí tuệ nhân tạo. Keras đã nhanh chóng trở thành một trong những công cụ phổ biến nhất trong cộng đồng Deep Learning nhờ vào giao diện thân thiện với người dùng và khả năng tích hợp với các framework mạnh mẽ như TensorFlow. Các đặc tính nổi bật của Keras:

• API cấp cao dễ sử dụng: Keras cung cấp các API cấp cao cho phép người dùng định nghĩa mô hình học sâu một cách trực quan và dễ hiểu. Thay vì phải viết code chi tiết cho từng lớp và kết nối trong mạng neural, Keras cho phép bạn xây dựng mô hình chỉ với vài dòng mã.

• Tập trung vào phần quan trọng: Thay vì phải lo về các chi tiết kỹ thuật phức tạp, Keras giúp người dùng tập trung vào việc thiết kế mô hình, chọn hàm mất mát và các thuật toán tối ưu, làm cho quá trình xây dựng mô hình trở nên nhẹ nhàng hơn.

Chương 5. Phát triển ứng dụng với Python 338

• Tích hợp hoàn hảo với TensorFlow: Từ TensorFlow 2.0, Keras đã được tích hợp sẵn vào TensorFlow, giúp khai thác sức mạnh của TensorFlow một cách dễ dàng thông qua Keras.

Hình 5.51: Thư viện Deep Learning - Keras

5.5.2.2 Linear regression với Keras

Tải về Keras tại địa chỉ sau: https://pypi.org/project/Keras/ Việc huấn luyện một mô hình deep learning hay neural network nói chung bao gồm các bước: Chuẩn bị dữ liệu, xây dựng network, chọn thuật toán cập nhật nghiệm, xây dựng loss và phương pháp đánh giá mô hình, huấn luyện mô hình và đánh giá mô hình.

import numpy as np from keras.models import Sequential from keras.layers.core import Dense, Activation from keras import optimizers

# 1. create pseudo data y = 2*x0 + 3*x1 + 4 X = np.random.rand(100, 2) y = 2* X[:,0] + 3 * X[:,1] + 4 + .2*np.random.randn(100) # noise added

# 2. Build model model = Sequential([Dense(1, input_shape = (2,), activation=’linear’)])

# 3. gradient descent optimizer and loss function sgd = optimizers.SGD(lr=0.1) model.compile(loss=’mse’, optimizer=sgd)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

# 4. Train the model model.fit(X, y, epochs=100, batch_size=2)

Chúng ta cùng làm một ví dụ đơn giản. Dữ liệu đầu X vào có số chiều là 2, đầu ra y = 2 ∗ X[0] + 3 ∗ X[1] + 4 + e với e là nhiễu tuân theo một phân phối chuẩn có kỳ vọng bằng 0, phương sai bằng 0.2. Dưới đây là đoạn code huấn luyện mô hình linear regression bằng Keras:

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 339

1 2 3 4 5 6 7 8 9 10 11 12

Epoch 1/100 100/100 [==============================] - 0s 5ms/step - loss: 1.7199 Epoch 2/100 100/100 [==============================] - 0s 709us/step - loss: 0.0388 Epoch 3/100 100/100 [==============================] - 0s 675us/step - loss: 0.0415 Epoch 4/100 100/100 [==============================] - 0s 774us/step - loss: 0.0392 Epoch 5/100 ..... Epoch 100/100 100/100 [==============================] - 0s 823us/step - loss: 0.0393

Kết quả thu được:

Chúng ta nhận thấy rằng thuật toán hội tụ khá nhanh và MSE loss khá nhỏ sau khi huấn luyện xong. Chúng ta cùng xem xét từng bước. Tại bước 2 xây dựng mô hình:

• Sequantial([]) là thể hiện việc các layer được xây dựng theo đúng thứ tự trong []. Phần tử đầu tiên của list thể hiện kết nối giưa input layer và layer tiếp theo, các phần tử tiếp theo của list thể hiện kết nối của các layer tiếp theo.

model = Sequential() model.add(Dense(1, input_shape=(2,), activation=’linear’))

1 2

• Dense thể hiện một fully connected layer, tức toàn bộ các unit của layer trước đó được nối với toàn bộ các unit của layer hiện tại. Giá trị đầu tiên trong Dense bằng 1 thể hiện việc chỉ có 1 unit ở layer này (đầu ra của linear regression trong trường hợp này bằng 1). input_shape = (2,) chính là kích thước của dữ liệu đầu vào. Kích thước này là một tuple nên ta cần viết dưới dạng (2,). Về sau, khi làm việc với dữ liệu nhiều chiều, ta sẽ có các tuple nhiều chiều. Ví dụ, nếu input là ảnh RGB với kích thước 224x224x3 pixel thì input_shape = (224, 224, 3). Các layer cũng có thể được thêm lần lượt vào model bằng cách sử dụng hàm .add(). Đoạn code phía trên và đoạn code ngay dưới đây là tương đương.

1 2 3 4

# 2. Build model model = Sequential() model.add(Dense(1, input_shape=(2,))) model.add(Activation(’linear’))

Activation cũng có thể được tách ra thành riêng một layer như sau:

1 2 3

# 3. gradient descent optimizer and loss function sgd = optimizers.SGD(lr=0.1) model.compile(loss=’mse’, optimizer=sgd)

Bước 3: Thể hiện việc chọn phương pháp cập nhật nghiệm, ở đâu ta sử dụng Stochastic Gradient Descent (SGD) với learning rate lr=0.1. Các phương pháp cập nhật nghiệm khác có thể được tìm thấy tại Keras-Usage of optimizers. loss=’mse’ chính là mean squared error, là hàm mất mát của linear regression.

Chương 5. Phát triển ứng dụng với Python 340

1

model.fit(X, y, epochs=100, batch_size=2)

Sau khi xây dựng được mô hình và chỉ ra phương pháp cập nhật cũng như hàm mất mát, ta huấn luyện mô hình bằng:

1

model.get_weights()

Keras khá giống với scikit-learn ở chỗ cùng huấn luyện các mô hình bằng phương thức .fit()). Ở đây, epochs chính là số lượng epoch và batch_size chính là kích thước của một mini-batch. Để xem hệ số tìm được của linear regression, ta sử dụng:

1

[array([[1.996118 ], [3.0239758]], dtype=float32), array([3.963116], dtype=float32)]

Kết quả:

5.5.2.3 Logistic regression với Keras

Trong đó, phần tử thứ nhất của list này chính là hệ số tìm được, phẩn tử thứ hai chính là bias. Kết quả này gần với nghiệm mong đợi của bài toán (y = 2 ∗ X[0] + 3 ∗ X[1] + 4).

import numpy as np from keras.models import Sequential from keras.layers.core import Dense, Activation from keras import losses from keras import optimizers

# 1. Prepare data X = np.array([0.50, 0.75, 1.00, 1.25, 1.50, 1.75, 1.75, 2.00, 2.25, 2.50, 2.75, 3.00, 3.25, 3.50, 4.00, 4.25, 4.50, 4.75, 5.00, 5.50])

y = np.array([0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1])

# 2. Build model model = Sequential() model.add(Dense(1, input_shape=(1,))) model.add(Activation(’sigmoid’))

# 3. gradient descent optimizer and loss function sgd = optimizers.SGD(lr=0.05) model.compile(loss=losses.binary_crossentropy, optimizer=sgd)

# 4. Train the model model.fit(X, y, epochs=3000, batch_size=1)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

Quay lại ví dụ về mối liên hệ giữa số giờ ôn tập và kết quả thi trong bài logistic regression, bài toán có thể được giải quyết bằng keras như sau:

1 2

model.get_weights() [array([[1.5141923]], dtype=float32), array([-4.1248693], dtype=float32)]

Có hai sự khác biệt ở Activation và loss vì logistic regression sử dụng hàm activation là sigmoid, hàm mất mát là trường hợp đặc biệt của cross entropy với hai class. Kết quả tìm được tương đối giống với kết quả tìm được trước đó với numpy và ta có y 1.51 ∗ x − 4.12.

5.5.2.4 Keras cho multi-layer perceptron

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 341

Chúng ta cùng xây dựng một mạng MLP đơn giản với Keras để giải quyết một bài toán phân loại ảnh. Cơ sở dữ liệu ảnh được dùng là Fashion-MNIST. Chúng ta đã quá quen với việc sử dụng MNIST, là cơ sở dữ liệu về chữ số viết tay, được sử dụng rất rộng rãi trong cồng đồng AI/ML. MNIST thường được thử đầu tiên khi có một thuật toán phân loại ảnh mới. Một số người nói “If it doesn’t work on MNIST, it won’t work at all”. Nhưng đồng thời, “Well, if it does work on MNIST, it may still fail on others.”

Fashion-MNIST được tạo ra gần đây với kích thước tương tự như MNIST nhưng các ảnh là các ảnh xám của trang phục với các nhãn: (0) T-shirt/top, (1) Trouser, (2) Pullover, (3) Dress, (4) Coat, (5) Sandal, (6) Shirt, (7) Sneaker, (8) Bag, (9) Ankle boot. Fashion-MNIST cũng có 10 class, 60000 ảnh cho training, 10000 ảnh cho test, mỗi ảnh có kích thước 28x28 pixel và là các ảnh xám với chỉ một channel. Dưới đây là một ví dụ về ảnh của class (2) Pullover.

Hình 5.52: Một mẫu dữ liệu đầu vào với kích thước 28x28, tương ứng với nhãn "pullover" - áo len chui đầu

# 1. prepare data from __future__ import print_function from keras.datasets import fashion_mnist (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data() print(’x_train shape:\t’, x_train.shape) print(’x_test shape:\t’, x_test.shape) print(’y_train shape:\t’, y_train.shape) print(’y_test shape:\t’, y_test.shape)

1 2 3 4 5 6 7 8

Tác giả của Fashion-MNIST cho rằng cần phải thay thế MNIST vì: MNIST đã trở nên quá dễ, rất nhiều thuật toán deep learning đã đạt được độ chính xác lên tới 99.7%, ngay cả KNN cũng đạt được trên 96%. Rất khó để đánh bại con số 99.7%, và nếu mô hình của bạn đạt được con số này, chúng ta vẫn khó có thể kết luận ngay đó là một mô hình tốt. MNIST được sử dụng quá nhiều đến mức nhàm chán, không đại diện cho các bài toán computer vision hiện đại. Cơ sở dữ liệu Fashion-MNIST có thể được tải về thông qua keras.datasets.

x_train shape: (60000, 28, 28) x_test shape: (10000, 28, 28) y_train shape: (60000,) y_test shape: (10000,)

1 2 3 4

Kết quả ở đây, x_train, x_test mang các giá trị nguyên từ 0 đến 255, y_train, y_test chứa các số nguyên từ 0 đến 9 thể hiện class của x tương ứng.

Chương 5. Phát triển ứng dụng với Python 342

1 2 3 4 5 6 7

# data normalization x_train = x_train/255. x_test = x_test/255. num_classes = 10 # convert class vectors to binary class matrices y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes)

Nếu sử dụng một neural network với softmax layer ở cuối, ta cần chuẩn hoá dữ liệu đầu vào x_train, x_test về đoạn [0, 1] và chuyển y_train, y_test về dạng one-hot coding. Việc này có thể được thực hiện như sau:

Chúng ta đã thực hiện bước đầu tiên trong bài toán xây dựng mô hình neural network cho bài toán classification ở bước chuẩn bị dữ liệu. Xây dựng một multi-layer perceptron để giải quyết bài toán: Ta sẽ xây dựng một MLP (multi-layer perceptron) với 3 hidden layers. Các layer cụ thể như sau: • Input layer với số units là 28 × 28 = 784. Mỗi input là một bức ảnh của Fashion-MNIST được kéo dài ra thành một vector.

• Hidden layer thứ nhất với 128 units, activation là ReLU. • Hidden layer thứ hai với 256 units, activation là ReLU. • Hidden layer thứ ba với 512 units, activation là ReLU. • Output layer là một softmax layer với 10 units.

from keras.layers import Dense, Flatten from keras.models import Sequential from keras import metrics # 2. buid model model = Sequential() model.add(Flatten(input_shape=(28, 28))) model.add(Dense(128, activation=’relu’)) model.add(Dense(256, activation=’relu’)) model.add(Dense(512, activation=’relu’)) model.add(Dense(num_classes, activation=’softmax’))

# 3. loss, metrics model.compile(loss=keras.losses.categorical_crossentropy,

1 2 3 4 5 6 7 8 9 10 11 12 13 14

optimizer=keras.optimizers.SGD(lr=0.1), metrics=[’accuracy’])

Hàm mất mát là cross entropy, ta tạm thời chưa quan tâm đến regularization (ở đây là weight decay). Phương pháp đánh giá hệ thống phân lớp này là ’accuracy’, tức số lượng điểm được phân loại đúng trong toàn bộ số điểm. Network đơn giản này được thực hiện trên Keras như sau:

Ở đây có một hàm mới là Flatten(), hàm này biến mỗi điểm dữ liểu ở dạng một mảng nhiều chiều thành một mảng một chiều. Vì ta đang sử dụng MLP nên ta cần làm công việc này. Về sau, khi sử dụng CNN việc giữ nguyên mảng hai chiều sẽ cho kết quả tốt hơn. Kết quả sau khi thực hiện đoạn code trên như sau:

Epoch 1/20 60000/60000 [=======================] - 3s 47us/step - loss: 0.6784 - acc: 0.7582 .... Epoch 20/20 60000/60000 [=======================] - 3s 54us/step - loss: 0.2140 - acc: 0.9192

1 2 3 4 5

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 343

from keras import metrics score = model.evaluate(x_test, y_test, verbose=0) print(’Test loss: %.4f’% score[0]) print(’Test accuracy %.4f’% score[1])

1 2 3 4

Sau 20 epochs, mô hình cho độ chính xác trên tập huấn luyện x_train khá cao là 0.9192. Nếu muốn đánh giá mô hình trên tập x_test, ta có thể thực hiện như sau:

Test loss: 0.3312 Test accuracy 0.8840

1 2

Kết quả thu độ chính xác của mô hình trên tập kiểm thử đạt 88.4%.

Như vậy, với dữ liệu đầu vào chỉ là 784 chiều và đặc trưng cho dữ liệu thời trang cũng không quá phức tạp trên nền là một màu đen và ảnh đã được căn chỉnh đúng tâm, đúng kích thước. MLP mặc dù cho kết quả tương đối tốt trong bài toán này, nó không phải là một mô hình tối ưu cho dữ liệu dạng ảnh vì ít nhất, dữ liệu ảnh hai chiều ban đầu đã được dàn phẳng ra thành dữ liệu một chiều, làm mất đi những thông tin về không gian trong ảnh (spatial information). Convolutional neural network thông thường sẽ cho kết quả tốt hơn. Tôi sẽ sớm giới thiệu với bạn đọc về kiến trúc này. Mạng MLP đơn giản này chưa dùng nhiều kỹ thuật của deep learning giúp tăng độ chính xác và giảm thời gian huấn luyện mô hình.

5.5.3 Project 3. Tạo Neural Network huấn luyện dữ liệu mẫu với TensoFlow, Kera

Phân loại đa lớp là một kiểu học máy có thể phân dữ liệu thành nhiều danh mục khác nhau. Neural network dùng trình phân loại softmax để phân phối xác suất hay tỉ lệ trên các class có thể. Chúng ta xét phân loại đa lớp cho ảnh từ dataset MNIST thành 10 danh mục khác nhau tương ứng với các con số từ 0 tới 9.

Datset MNIST: Là một dataset benchmark phổ biến cho học máy và các thuật toán thị giác máy tính. Nó chứa 70.000 ảnh chữ viết tay ở kích thước 28x28 pixel. Các con số viết tay nằm trong phạm vi từ 0 tới 9. Trước khi xây dựng bất kỳ mẫu học máy, chúng ta cần hiểu dataset chứa những gì. Hiểu dataset sẽ cho ta cách xử lý dữ liệu tốt hơn.

1

!pip install numpy matplotlib tensorflow opencv-python

Chuẩn bị môi trường phát triển: Để triển khai, chúng ta cần có kiến thức nền tảng về học máy, cách sử dụng Jupyter Notebook hoặc Google Colab. Để tạo mới Jupyter Notebook hoặc đăng ký Google Colab. Chạy lệnh này để cài đặt gói cần thiết:

Trong ví dụ này, chúng ta sử dụng Matplotlib để trực quan hóa dữ liệu, NumPy để thao tác với mảng, TensorFlow để tạo và đào tạo mô hình và OpenCV để cung cấp cho mô hình các chữ số viết tay.

Chương 5. Phát triển ứng dụng với Python 344

1 2 3 4 5 6

import tensorflow as tf from tensorflow import keras import matplotlib.pyplot as plt %matplotlib inline import numpy as np import cv2

Nhập mô đun cần thiết: Nhập các gói đã cài đặt trong môi trường. Điều này cho phép gọi và dùng các hàm và mô đun của chúng trong code sau này. Chúng ta nhập môđun Keras từ thư viện Google TensorFlow, dùng Keras để huấn luyện neural network chuyên sâu với TensorFlow làm backend.

1

(X_train, y_train) , (X_test, y_test) = keras.datasets.mnist.load_data()

Dataset MNIST được tích hợp vào Keras, để tải dataset MNIST và tách nó thành phần training và test. Chúng ta sẽ dùng phần train để định hướng model và test để đánh giá độ chính xác của mẫu trong phân loại ảnh mới chưa nhìn thấy.

1 2

len(X_train) len(X_test)

Kiểm tra độ dài của tập train và test. Dataset MNIST có 60.000 ảnh phục vụ cho việc huấn luyện và 10.000 ảnh cho việc kiểm tra.

1 2 3 4

X_train[0].shape X_train[0] plt.matshow(X_train[0]) y_train[0]

Kiểm tra hình dạng của ảnh đầu tiên trong dataset MNIST ở kích thước 28x28 pixel. Sau đó, in các giá trị pixel và minh họa nó bằng Matplotlib.

Kết quả như sau:

Hình 5.53: Kết quả phân lớp sử dụng thư viện Deep Learning - Keras

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 345

5.5.4.1 Thư viện PyTorch

5.5.4 Project 4. Phát triển ứng dụng với thư viện PyTorch

Pytorch là framework được phát triển bởi Facebook. Đây là một ông lớn về công nghệ đầu tư rất nhiều nguồn lực cho việc phát triển Trí tuệ nhân tạo. Pytorch được phát triển với giấy phép mã nguồn mở do đó nó tạo được cho mình một cộng đồng rất lớn.Một cộng đồng lớn đồng nghĩa với nhiều tài nguyên để học và các vấn đề của bạn có thể đã có ai đó giải quyết và chia sẻ với cộng đồng. Pytorch cùng với Tensorflow và Keras là một trong những framework phổ biến được sử dụng trong các bài toán về Deep Learning hiện nay. Đặc biệt, trong các lĩnh vực nghiên cứu, hầu như các tác giả đều sử dụng pytorch để triển khai bài toán của mình. Pytorch cho thấy lợi thế của nó trong lĩnh vực nghiên cứu bởi việc rất dễ dàng để bạn debug và visuallize, ngoài ra nó theo cơ chế Dynamic Graphs cho phép giảm thời gian huấn luyện mô hình.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#Tạo một Tensor từ list cho trước sử dụng torch.Tensor t = torch.Tensor([[1,2,3],[3,4,5]]) # Tạo Tensor với kích thước (2,3) cho trước và có giá trị ngẫu nhiên tuân theo # phân phối chuẩn với trung vị bằng 0 và phương sai bằng 1 t = torch.randn(2, 3) # Tạo Tensor với kích thước (2,3) cho trước và tất cả phần tử có giá trị đều bằng 1 t = torch.ones(2, 3) # Tạo Tensor với kích thước (2,3) cho trước và tất cả phần tử có giá trị đều bằng 0 t = torch.zeros(2, 3) #Tạo tensor có kích thước (2,3) với giá trị nằm trong khoảng từ 0->10 t = torch.randint(low = 0,high = 10,size = (2,3)) #Sử dụng torch.from_numpy để chuyển đổi từ Numpy array sang Tensor a = np.array([[1,2,3],[3,4,5]]) t = torch.from_numpy(a) #Sử dụng .numpy() để chuyển đổi từ Tensor sang Numpy array t = t.numpy()

Tensor trong pytorch: Tensor cũng giống như Numpy array nhưng được chuyển sang tensor để sử dụng tính toán trên GPU. Các phép toán, biến đổi và các hoạt động cơ bản của Numpy đều có thể thực hiện được trên Tensor. Create Tensor: Có rất nhiều cách tạo một Tensor, bao gồm việc chuyển đổi từ List, Numpy sang Tensor. Dưới đây là một số cú pháp cơ bản hay được sử dụng để tạo một Tensor:

1 2 3 4 5 6 7

A = torch.randn(2,4) W = torch.randn(4,3) t = A.mm(W) #Nhân 2 ma trận sử dụng .mm print(t) t = t.t() #Ma trận chuyển vị print(t.shape) t = t**2 #Bình phương mỗi giá trị trong Tensor

Tensor operations: Tensor và Variables đã từng khác nhau và cung cấp chức năng khác nhau, nhưng bây giờ API Variables không được dùng nữa và tất cả các phương thức cho Variables đều hoạt động với Tensors.

print(t) t_size = t.size() #Trả về size của Tensor print(t_size) t = t.flatten() #Duỗi Tensor có kích thước (a,b) thành (1,a*b) print(t)

#Thêm 1 chiều với dim bằng 0 cho Tensor t = t.unsqueeze(0) print(t.shape) #Giảm 1 chiều với dim bằng 0 cho Tensor t = t.squeeze(0) print(t.shape) #hàm transpose có tác dụng đổi chiều dữ liệu ví dụ dữ liệu đang có shape=(224,224,3), #sau khi thực hiện câu lệnh dưới sẽ thành (3,224,224) t = t.transpose(2,0,1) #hàm view có tác dụng giảm chiều dữ liệu ví dụ dữ liệu đang có shape = (3,224,224), #sau khi thực hiện câu lệnh dưới sẽ thành (3,224*224) t = t.view(t.size(0),-1)

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

Chương 5. Phát triển ứng dụng với Python 346

Tạo model bằng pytorch: Để tạo một mô hình là một lớp bằng cách kế thừa nn.Module, điều này cho phép tạo một mô hình học sâu dưới dạng một lớp. Lớp này có 2 hàm bắt buộc phải có đó là init và forward:

class MySimpleModel(nn.Module):

def __init__(self):

super().__init__() #Định nghĩa các layer self.lin1 = nn.Linear(256, 128) self.lin2 = nn.Linear(128, 10)

def forward(self, x):

# Kết nối các layer lại với nhau x = self.lin1(x) x = self.lin2(x) return x

1 2 3 4 5 6 7 8 9 10 11

• init: Là một hàm khởi tạo nhận vào các biến,tham số giúp bạn có thể khởi tạo các biến, hàm của đối tượng được khởi tạo. Vì Class này kế thừa nn.Module nên khi khởi tạo một đối tượng mới của Class thì phải khởi tạo lớp kế thừa nên trong hàm init luôn phải có super().__init__(). Ngoài ra hàm khởi tạo này chúng ta có thể khởi tạo các layer custom sử dụng trong mô hình, tạo backbone bằng cách load mô hình pretrained, khởi tạo và thực thi một số hàm khác. • forward: Là hàm nhận vào là dữ liệu input ban đầu. Dữ liệu sẽ đi lần lượt qua từng layer của model và trả về output của model. Một mô hình đơn giản có thể được triển khai như sau:

Trên đây là một model đơn giản với 2 lớp Fully Connected với đầu vào là một tensor có độ dài là 256 và đầu ra có độ dài là 10. Nhưng điều đáng nói ở đây là với mô hình chuyển tiếp này sẽ giúp chúng ta có thể dễ dàng thiết kế mô hình tính toán theo từng layer, cho thấy khả năng

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 347

class MySkipCModel(nn.Module):

def __init__(self):

super().__init__() # Định nghĩa các layers self.layer1 = nn.Linear(256, 128) self.layer2 = nn.Linear(128, 256) self.layer3 = nn.Linear(128, 10)

def forward(self, x):

1 2 3 4 5 6 7 8 9 10 11 12 13 14

#Kết nối các layer lại với nhau x_out1 = self.layer1(x) x_out2 = x + self.layer2(x_out1) x_out2 = self.layer1(x_out2) x = self.layer3(x_out2) return x

customize mô hình trong Pytorch là rất thuận tiện cho việc nghiên cứu và thiết kế mô hình trong việc Research. Ví dụ về customize model trong Pytorch được thực hiện dễ dàng như sau:

import torch.nn as nn import torchvision.models as models class MyModel(nn.Module):

def __init__(self,num_cls):

super().__init__() self.num_cls = num_cls backbone = models.resnet50(pretrained=True) self.model_backbone = nn.Sequential(*list(backbone.children())[:-1]) self.clf = nn.Sequential(

nn.Linear(2048,512), nn.ReLU(), nn.BatchNorm1d(512), nn.Dropout(0.5), nn.Linear(512,self.num_cls))

def forward(self,input):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

output = self.model_backbone(input) output = output.view(output.size(0),-1 ) output = self.clf(output) return output

Mô hình trên được gọi là mô hình Skip Connection được sử dụng trong các mô hình hiện đại hiện nay. Mô hình này giúp cho việc tính toán trở nên nhanh hơn. Qua ví dụ trên, chúng ta có thể thấy được để định nghĩa một mô hình trong Pytorch khá dễ dàng. Tiếp theo, chúng ta sẽ code mẫu một model classification đơn giản sử dụng phương pháp transfer learning của mô hình Resnet50:

1 2

# load a model; pre-trained on COCO model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)

Cú pháp nn.Sequential(*list(backbone.children())[:-1]) cho phép bạn cus- tom model backbone, cắt bỏ các layer không cần dùng đến. Ngoài mô hình Resnet ra chúng ta có thể sử dụng các mô hình trích xuất thông tin khác trong thư viện của Pytorch như: VGG, Inception, Googlenet, Mobilenet,... Chúng ta có thể sử dụng thư viện torchvision.models để import FasterRCNN:

Chương 5. Phát triển ứng dụng với Python 348

num_classes = 2 # 1 class (wheat) + background # get number of input features for the classifier in_features = model.roi_heads.box_predictor.cls_score.in_features # replace the pre-trained head with a new one model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)

1 2 3 4 5

Sau đó tùy theo bài toán để định nghĩa số lớp đầu ra của mô hình, vì COCO có 80 lớp sẽ không phù hợp nếu bài toán của bạn có mục tiêu khác. Xét ví dụ có 2 lớp:

torch.nn.Conv2d(in_channels: int, out_channels: int, kernel_size: Union[T, Tuple[T, T]], stride: Union[T, Tuple[T, T]] = 1, padding: Union[T, Tuple[T, T]] = 0, dilation: Union[T, Tuple[T, T]] = 1, groups: int = 1, bias: bool = True, padding_mode: str = ’zeros’)

1 2 3 4

Bây giờ chúng ta có thể sử dụng model này cho bài toán object detection. Ngoài ra còn có thư viện Detecto trong Pytorch và Detectron2 cho các bài toán về Object Detection và Segmentation. Một phần quan trọng để giúp Pytorch được sử dụng rộng rãi nếu không cung cấp nhiều layers có sẵn được sử dụng thường xuyên. Một số layers như: nn.Linear, nn.Conv2d, nn.MaxPool2d, nn.ReLU, nn.BatchNorm2d, nn.Dropout, nn.Embedding, nn.GRU/nn.LSTM, nn.Softmax, nn.LogSoftmax, nn.MultiheadAttention, nn.TransformerEncoder, nn.TransformerDecoder. Ví dụ cách sử dụng của layer Conv2D như sau:

import torch.nn as nn import torch #Tạo lớp Conv2d đầu vào channals 3, đầu ra 256, kernel kích thước (3,3) và stride=2 layers = nn.Conv2d(3,256,(3,3),2) #Tạo ngẫu nhiên Tensor có chiều (3,256,256) để xem thay đổi khi đi qua lớp Conv2d, #kết quả sẽ được một Tensor có chiều (256,127,127) print(layers(torch.randn(1,3,256,256)).shape)

1 2 3 4 5 6 7

Ví dụ về một layer đơn giản:

Data

Train

Image_train1 Image_train2 ... Image_train1000

Val

Image_val1 ...

Test

Image_test1 ...

1 2 3 4 5 6 7 8 9 10 11 12

Tạo dataset theo batch size trong pytorch: Sau khi tạo được mô hình thì bước tiếp theo để có thể huấn luyện mô hình đó là cách tạo dữ liệu chia thành tập train, val, test và cho qua mô hình theo từng batch size theo format sau:

Chúng ta có thể sử dụng thư viện torchvision.datasets.ImageFolder để tạo dataset:

from torchvision import transforms from torchvision.datasets import ImageFolder traindir = "data/train/" t = transforms.Compose([

transforms.Resize(size=256), transforms.CenterCrop(size=224), transforms.ToTensor()])

train_dataset = ImageFolder(root=traindir,transform=t) print("Num Images in Dataset:", len(train_dataset)) print("Example Image and Label:", train_dataset[2])

1 2 3 4 5 6 7 8 9 10

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 349

Kết quả như sau:

Vì trong thực tế sẽ không có data để theo format như thế nên việc hiểu và biết customize dataset là rất quan trọng và nó được sử dụng rất phổ biến. Chúng ta sẽ tạo Dataset thành một lớp giống như model trên kia. Lớp này kế thừa torch.utils.data.Dataset và cũng có 3 lớp bắt buộc có đó là :

• init : Là hàm khởi tạo, nhận vào các tham số và khởi tạo các tham số tương ứng • len : Hàm trả về độ dài của dữ liệu • getitem: nhận vào là index, chỉ số này nằm trong độ dài của dữ liệu. Hàm này mục tiêu để đọc dữ liệu, xử lí dữ liệu, nhãn và trả về dữ liệu chuẩn để đưa vào model. Các phương pháp Augmentation được thực hiện tại đây.

class myDataset(Dataset):

def __init__(self,data_dict,trans = None):

super().__init__() self.data_dict = data_dict self.trans = trans

def __len__(self):

return len(self.data_dict)

def __getitem__(self,idx):

image_path = self.data_dict[idx][’data_link’]

1 2 3 4 5 6 7 8 9

Xét bài toán classification, tùy vào từng format dữ liệu để tạo được data truyền vào. Ví dụ sau đã tiền xử lí và lấy được data dưới dạng dict mà mỗi example là một cặp link ảnh và nhãn của ảnh. Augmentation ảnh có thể sử dụng thư viện torchvision.transforms.

label= self.data_dict[idx][’label’] try:

image = cv2.imread(image_path) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

except Exception as e:

print(e) if self.trans:

transformed = self.trans(image=image) image = transformed["image"]

return image.float(), label

10 11 12 13 14 15 16 17 18 19

Chương 5. Phát triển ứng dụng với Python 350

1 2 3

torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None)

Sau khi tạo đối tượng Dataset, Class này chỉ generate ra từng example và để dữ liệu tạo thành batch thì ta phải sử dụng hàm torch.utils.data.Dataloader của Pytorch

trans = A.Compose([A.RandomCrop(width=256, height=256), A.HorizontalFlip(p=0.5),

A.RandomBrightnessContrast(p=0.2), ToTensorV2(),])

train_dataset = myDataset(data_dict=data_dict,trans=trans) train_dataloader=DataLoader(train_dataset,batch_size=64,shuffle=True,num_workers=10)

1 2 3 4

Một số tham số thường dùng gồm: dataset nhận vào class Dataset đã khởi tạo ở trên; batch_size: thể hiện bạn muốn dữ liệu cua bạn được generate theo batch bao nhiêu; num_workers khi muốn chạy nhiều tiến trình cùng một lúc tùy vào phần cứng; collate_fn để định nghĩa cách sắp xếp và kết nối dữ liệu và nhãn tương ứng theo từng lô dữ liệu. Ví dụ sử dụng Dataloader như sau:

x_batch,y_batch = next(iter(train_dataloader)) print(x_batch.shape)

1 2

Để kiểm tra dữ liệu đã được gen đúng hay chưa, chúng ta thực hiện câu lệnh sau:

5.5.4.2 Cách huấn luyện mô hình

Hàm next(iter(train_dataloader)) sẽ trả về dữ liệu theo từng batch_size.

num_epochs = 10 for epoch in range(num_epochs):

model.train() #Thiết lập trạng thái huấn luyện cho mô hình for x_batch,y_batch in train_dataloader: optimizer.zero_grad() #xóa gradients # Cho dữ liệu qua model và trả về output cần tìm pred = model(x_batch) # Tính toán giá trị lỗi và backpropagation loss = loss_criterion(pred, y_batch) loss.backward() optimizer.step() # Cập nhật trọng số

1 2 3 4 5 6 7 8 9 10 11

Sau khi đã tạo được model và dữ liệu, bước tiếp theo là làm sao để có thể chạy mô hình thông qua quá trình huấn luyện. Xét ví dụ sau:

#Thiết lập trạng thái đánh giá cho mô hình, ở bước này thì mô hình không backward

#và cập nhật trọng số

model.eval() for x_batch,y_batch in valid_dataloader:

pred = model(x_batch) val_loss = loss_criterion(pred, y_batch)

12 13 14 15 16 17

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 351

Trong ví dụ trên, mô hình chạy 5 epochs và ở mỗi epoch: • Sử dụng model.train() để thiết lập trạng thái huấn luyện cho mô hình • Sử dụng vòng for để lấy từng cặp dữ liệu theo từng batch size • Ở mỗi vòng lặp, chúng ta forward dữ liệu bằng cách sủ dụng model(x_batch), trả về output tương ứng.

• Thực hiện tính toán hàm mất mát đã được định nghĩa trước đó, về hàm loss thì mình sẽ nói ở phần dưới đây, thực hiện bằng cách truyền vào hàm đó hàm mục tiêu và hàm dự đoán, hàm này trả về giá trị mất mát và mình cần tối ưu nó về nhỏ nhất có thể.

5.5.4.3 Các hàm loss và custom hàm loss trong PyTorch

• Thực hiện Back-propagation bằng cách sử dụng loss.backward(). • Cập nhật trọng số bằng cách sử dụng optimizer.step() Sau khi chạy xong vòng lặp dữ liệu huấn luyện thì sẽ đến với việc đánh giá mô hình bằng cách sử dụng dữ liệu val: • Trước tiên thực hiện model.eval() để chuyển trạng thái mô hình sang đánh giá chạy vòng lặp dữ liệu đánh giá • Ở mỗi vòng lặp ta chỉ forward dữ liệu qua model và tính giá trị loss tại mỗi vòng lặp.

def dice_loss(pred, target, smooth = 1.):

pred = pred.contiguous() target = target.contiguous() intersection = (pred * target).sum() loss = (1-((2. *intersection + smooth)/(pred.sum()+target.sum()+smooth))) return loss.mean()

1 2 3 4 5 6

Pytorch hỗ trợ rất nhiều các hàm loss như các bài toán hồi quy, phân loại,... Một số hàm loss phổ biến như là nn.MSE(), nn.CrossEntropyLoss(), nn.KLDivLoss(), nn.BCELoss, nn.NLLLoss(). Ngoài các hàm phổ biến ra thì còn một số hàm loss khác chưa được pytorch hỗ trợ nhưng việc triển khai nó là rất dễ dàng, bạn chỉ việc tạo một hàm nhận đầu vào là giá trị mục tiêu và giá trị dữ đoán do mô hình đưa ra và trả về giá trị lỗi là xong. Sau đây, mình sẽ ví dụ code hàm loss dice_loss được sử dụng nhiều trong bài toán segmentation để giải quyết việc imballanced data:

def calc_loss(pred, target, metrics, bce_weight=0.5) bce = F.binary_cross_entropy( pred, target) dice = dice_loss(pred, target) loss = bce * bce_weight + dice * (1 - bce_weight) metrics[’bce’] += bce.data.cpu().numpy() * target.size(0) metrics[’dice’] += dice.data.cpu().numpy() * target.size(0)

1 2 3 4 5 6

Ngoài ra còn có thể kết hợp các hàm loss lại với nhau như sau:

7 8

metrics[’loss’] += loss.data.cpu().numpy() * target.size(0) return loss

5.5.4.4 Các hàm tối ưu trong PyTorch

Chương 5. Phát triển ứng dụng với Python 352

1 2 3

model.cuda() x_batch.cuda() y_batch.cuda()

Tương tự như các hàm loss, Pytorch cũng hỗ trợ rất nhiều các hàm tối ưu để bạn sử dụng như là torch.optim.Adadelta , torch.optim.Adagrad, torch.optim.RMSprop và hàm loss hay sử dụng đó là torch.optim.Adam. Nếu có gpu, ta sử dụng cú pháp sau để giúp việc huấn luyện trở nên nhanh chóng hơn:

5.5.5.1 Thư viện Scikit-learn

5.5.5 Project 5. Phát triển ứng dụng với thư viện Scikit-learn

Scikit-learn là một thư viện học máy phổ biến và mạnh mẽ, hỗ trợ nhiều loại thuật toán cũng như các công cụ để trực quan hóa Machine Learning, tiền xử lý, điều chỉnh, lựa chọn và đánh giá mô hình. Dựa trên NumPy, SciPy và Matplotlib, Scikit-learn có một số thuật toán hiệu quả để phân loại, phân tích hồi quy và phân cụm. Bao gồm các vector machines, rain forests, gradient boosting, k-means, và DBSCAN.

Scikit-learn được biết đến với tính dễ phát triển tương đối nhờ các API được thiết kế nhất quán và hiệu quả, tài liệu mở rộng cho hầu hết các thuật toán và nhiều hướng dẫn online. Hiện tại các phiên bản cho các nền tảng phổ biến bao gồm Linux, MacOS và Windows đang được phát hành. API Scikit-learn đã trở thành tiêu chuẩn thực tế cho việc triển khai học máy nhờ tính dễ sử dụng, thiết kế chỉnh chu và sự hỗ trợ đông đảo trong cộng đồng Scikit-learn.

Scikit-learn cung cấp các mô-đun để xây dựng, điều chỉnh và đánh giá mô hình ML: • Preprocessing đề cập đến các công cụ Scikit-learn hữu ích trong việc trích xuất và chuẩn hóa features trong quá trình phân tích dữ liệu.

• Classification đề cập đến một bộ công cụ xác định danh mục liên kết với dữ liệu trong mô hình học máy. Ví dụ: những công cụ này được sử dụng để phân loại email hợp lệ hoặc thư rác. Về cơ bản, Classification xác định đối tượng thuộc về loại nào.

• Regression (Phân tích hồi quy) đề cập đến việc tạo ra một mô hình học máy để tìm hiểu mối quan hệ giữa dữ liệu đầu vào và đầu ra, chẳng hạn như hành vi hoặc giá cổ phiếu. Hồi quy dự đoán một thuộc tính có giá trị liên tục được liên kết với một đối tượng. • Các công cụ Clustering trong Scikit-learn tự động nhóm dữ liệu có đặc điểm tương tự thành các bộ (sets), chẳng hạn như dữ liệu khách hàng được sắp xếp theo bộ dựa trên vị trí thực tế. • Dimensionality Reduction làm giảm số lượng biến ngẫu nhiên để phân tích. Ví dụ: để tăng hiệu quả trực quan hóa, dữ liệu bên ngoài có thể bị loại bỏ.

• Model selection đề cập đến các thuật toán và khả năng cung cấp các công cụ so sánh, xác thực và chọn tham số tối ưu để sử dụng trong các dự án học máy khoa học dữ liệu.

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 353

5.5.5.2 Cơ chế hoạt động của Scikit-learn

• Pipeline đề cập đến các tiện ích để xây dựng quy trình làm việc mô hình. • Visualization cho học máy cho phép vẽ đồ thị và điều chỉnh trực quan nhanh chóng.

Scikit-learn được viết chủ yếu bằng Python và sử dụng NumPy cho đại số tuyến tính hiệu suất cao cũng như cho các phép tính array. Một số thuật toán Scikit-learn cốt lõi được viết bằng Cython để tăng hiệu suất tổng thể.

Là một thư viện cấp cao bao gồm một số triển khai các thuật toán học máy khác nhau, Scikit-learn cho phép người dùng xây dựng, đào tạo và đánh giá mô hình bằng một vài dòng mã. Scikit-learn cung cấp một bộ API cấp cao thống nhất để xây dựng quy trình hoặc quy trình học máy.

Hình 5.54: Cơ chế hoạt động của Scikit-learn

Người dùng sử dụng ML Scikit-learn Pipeline để truyền dữ liệu qua các transformers nhằm trích xuất các đặc điểm và công cụ ước tính để tạo ra mô hình, sau đó đánh giá các dự đoán để đo lường độ chính xác của mô hình.

5.5.5.3 Sử dụng GPU để tăng tốc Scikit-learn APIs

• Transformer: Đây là thuật toán biến đổi hoặc nhập vào dữ liệu để xử lý. • Estimator: Đây là thuật toán học máy đào tạo hoặc điều chỉnh dữ liệu để xây dựng mô hình, mô hình này có thể được sử dụng để dự đoán. • Pipeline: Một đường dẫn kết nối các Transformer và Estimator lại với nhau để chỉ định quy trình làm việc ML.

Về mặt kiến trúc, CPU bao gồm một vài cores với nhiều bộ nhớ đệm có thể xử lý một số threads phần mềm cùng một lúc. Ngược lại, GPU bao gồm hàng trăm cores có thể xử lý hàng nghìn threads cùng một lúc. Bộ thư viện phần mềm nguồn mở NVIDIA RAPIDS, được xây dựng trên CUDA-X AI, cung cấp khả năng thực thi các quy trình phân tích và khoa học dữ liệu từ đầu đến cuối hoàn toàn trên GPU. Dựa trên các nguyên hàm NVIDIA CUDA để tối ưu hóa điện toán ở mức độ thấp, nhưng thể hiện tính song song của GPU và tốc độ bộ nhớ băng thông cao thông qua giao diện Python thân thiện với người dùng.

Chương 5. Phát triển ứng dụng với Python 354

Các thuật toán học máy cuML và các phép toán nguyên thủy của RAPIDS tuân theo API tương tự như Scikit-learn quen thuộc. Các thuật toán phổ biến như XGBoost, Random Forest và nhiều thuật toán khác được hỗ trợ cho cả triển khai GPU đơn và trung tâm dữ liệu lớn. Đối với các tập dữ liệu lớn, việc triển khai dựa trên GPU này có thể hoàn thành nhanh hơn 10-50 lần so với CPU tương đương.

Hình 5.55: Sử dụng GPU để tăng tốc Scikit-learn APIs

5.5.5.4 Cây phân loại và hồi quy (Classification and Regression Trees)

Với RAPIDS GPU DataFrame, dữ liệu có thể được tải lên GPU bằng giao diện như Pandas, sau đó được sử dụng cho các thuật toán phân tích biểu đồ và học máy được kết nối khác nhau mà không cần tách khỏi GPU. Mức độ tương tác này có thể thực hiện được thông qua các thư viện như Apache Arrow và cho phép tăng tốc quy trình từ đầu đến cuối từ khâu chuẩn bị dữ liệu, học máy đến học sâu. RAPIDS hỗ trợ chia sẻ bộ nhớ thiết bị giữa nhiều thư viện khoa học dữ liệu phổ biến. Điều này giúp lưu trữ dữ liệu trên GPU và tránh việc sao chép qua lại vào bộ nhớ máy chủ.

Trong ví dụ này, chúng ta sử dụng cây quyết định Decision tree phân loại để mô hình hóa bộ dữ liệu hoa Iris. Bộ dữ liệu này được cung cấp dưới dạng tập dữ liệu mẫu với thư viện và được tải về máy tính. Trình phân loại phù hợp với dữ liệu và sau đó dự đoán được thực hiện trên dữ liệu đào tạo.

1 2 3 4 5 6 7 8

# Sample Decision Tree Classifier from sklearn import datasets from sklearn import metrics from sklearn.tree import DecisionTreeClassifier # load the iris datasets dataset = datasets.load_iris() # fit a CART model to the data model = DecisionTreeClassifier()

Bộ dữ liệu này được cung cấp dưới dạng tập dữ liệu mẫu ngay trong thư viện sau đó được tải xuống. Thuật toán phân loại bắt đầu huấn luyện mô hình với bộ dữ liệu Iris ban đầu sau đó dự đoán lại các dữ liệu huấn luyện. Cuối cùng, chúng ta đánh giá độ tốt của mô hình bằng quan sát accuracy và confusion matrix của 2 tập nhãn thực tế và nhãn dự đoán của mô hình.

model.fit(dataset.data, dataset.target) print(model) # make predictions expected = dataset.target predicted = model.predict(dataset.data) # summarize the fit of the model print(metrics.classification_report(expected, predicted)) print(metrics.confusion_matrix(expected, predicted))

9 10 11 12 13 14 15 16

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 355

DecisionTreeClassifier(class_weight=None, criterion=’gini’, max_depth=None,

max_features=None, max_leaf_nodes=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, presort=False, random_state=None, splitter=’best’) precision recall f1-score support

0 1.00 1.00 1.00 50 1 1.00 1.00 1.00 50 2 1.00 1.00 1.00 50

avg / total 1.00 1.00 1.00 150 [[50 0 0] [ 0 50 0] [ 0 0 50]]

1 2 3 4 5 6 7 8 9 10 11 12

Chạy ví dụ trên được kết quả như sau.

Chúng ta có thể thấy chi tiết mô hình cây phân loại được huấn luyện với các tham số chi tiết như thế nào, mỗi tham số ảnh hưởng rất lớn tới việc mô hình có tốt hay không. Phía dưới là classification report và confusion matrix của mô hình.

5.5.6.1 Thư viện NLTK

5.5.6 Project 6. Phát triển ứng dụng xử lý ngôn ngữ tự nhiên (NTLK)

Thư viện NLTK (Natural Language Toolkit) là một trong những thư viện open-source xử lí ngôn ngữ tự nhiên. Được viết bằng Python và với ưu điểm là dễ dàng sử dụng nên thư viện này ngày càng trở nên phổ biến và có được một cộng đồng lớn mạnh. Thư viện cung cấp hơn 50 kho dữ liệu văn bản khác nhau (corpora) và nhiều chức năng để xử lí dữ liệu văn bản để phục vụ cho nhiều mục đích khác nhau. Cài thư viện NLTK với pip install nltk.

Hình 5.56: Thư viện xử lý ngôn ngữ tự nhiên - Natural Language Toolkit

5.5.6.2 Tiền xử lí dữ liệu văn bản với NLTK

Chương 5. Phát triển ứng dụng với Python 356

wget https://www.gutenberg.org/files/36/36-0.txt with open("/content/36-0.txt", encoding=’utf-8-sig’) as f:

raw_text = f.read()

1 2 3

Tiền xử lí dữ liệu là giai đoạn rất quan trọng, hay nói cách khác đây là công đoạn làm sạch văn bản. Việc văn bản được làm sạch giúp cách thuật toán có thể trích xuất được những đặc trưng tốt nhất từ đó nâng cao hiệu quả, chất lượng của các mô hình, thuật toán. Để trực quan, chúng ta sẽ tiền xử lí nội dung của quyển The War of the Worlds của tác giả H. G. Wells được tải từ trang Gutenberg. Tải sách và đọc nội dung quyển sách như sau:

1

raw_text = raw_text.replace("\n", " ")

Sau khi quan sát nội dung quyển sách thì trước tiên ta cần loại bỏ các kí tự xuống dòng \n:

1

raw_text = raw_text.lower()

Biến đổi về chữ thường: Chuyển tất cả các chữ in hoa về chữ thường. Đây là cách đơn giản nhưng cũng rất hiệu quả trong việc tiền xử lí dữ liệu văn bản, đặc biệt là đối với những bộ dữ liệu nhỏ.

sentence_list = nltk.sent_tokenize(raw_text) # Print some sentences for i in range(100, 110): print(sentence_list[i]) print("-----")

print("---------------------------------------") print(f"Number of sentences: {len(sentence_list)}")

1 2 3 4 5 6 7

Tách các câu: Từ một đoạn văn bản gồm nhiều câu thì thông qua bước này ta thu được các câu thành phần. Để nhận biết một câu đơn giản nhất là khi gặp dấu "." kết thúc câu, chúng ta hoàn toàn có thể sử dụng hàm split() trong python và tách câu mỗi khi gặp dấu ".". Tuy nhiên, không phải lúc nào dấu "." cũng là kết thúc câu, ví dụ trong tiếng anh, từ "Mr. Smith" thì nếu ta dùng cách trên để bóc tách các câu thì sẽ sai. Để có thể tách các câu chính xác thì việc sử dụng các thư viện hỗ trợ là biện pháp đơn giản nhất cụ thể là sử dụng hàm nltk.sent_tokenize. Bên cạnh hàm để tách các câu thì thư viện NLTK cũng cung cấp hàm để tách các từ nltk.word_tokenize.

import string print("Punctuations: " + string.punctuation + "\n") sentence_list = [sentence.translate(str.maketrans(’’, ’’, string.punctuation))

for sentence in sentence_list]

for i in range(100, 110): print(sentence_list[i])

1 2 3 4 5 6

Loại bỏ các kí tự đặc biệt (dấu câu): Trong các câu trong văn bản sẽ tồn tại nhiều dấu câu như ?, !, ", ;, ... trước khi xây dựng bộ từ vựng thì các kí tự này cũng cần được loại bỏ. Python đã định nghĩa các dấu câu trong string.punctuation tuy vào bài toán ta có thể thêm hoặc bớt các dấu này cho phù hợp.

7

print("-----")

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 357

Không chỉ dấu "," và "." trong câu đã được loại bỏ thì các dấu được định nghĩa trong string.punctuation cũng được bỏ đi. Ngoài ra ta có thể thêm bớt các dấu tùy theo mục đích.

nltk.download(’stopwords’) from nltk.corpus import stopwords stop_word_list = set(stopwords.words(’english’)) print(stop_word_list, "\n") for i in range(len(sentence_list)):

sentence_list[i] = " ".join([word for word in sentence_list[i].split()

if word not in stop_word_list])

for i in range(100, 110): print(sentence_list[i]) print("-----")

1 2 3 4 5 6 7 8 9 10

Loại bỏ stop-word: Stop words thường là các từ xuất hiện nhiều lần và không đóng góp nhiều vào ý nghĩa của câu, chúng sẽ đóng vai trò như nhiễu, trong tiếng Anh các từ này có thể kể đến như the, is, at, on, which, in, some, many hay trong tiếng Việt là các từ cái, các, cả,.... Các từ này thường sẽ được loại bỏ để giảm kích thước của bộ từ vựng. Trong thư viện NLTK có định nghĩa các stop words phổ biến trong tiếng Anh, tuy nhiên tùy thuộc vào mục đích, bài toàn mà ta sẽ thêm bớt các stop word cho phù hợp. Để sử dụng stop words của NLTK, trước tiên ta cần download bộ stop words nltk.download(’stopwords’).

from collections import Counter # get word list word_list =list() for sentence in sentence_list: for word in sentence.split():

word_list.append(word)

word_counter = Counter(word_list) # for example, remove 10 rare words rare_word_list=set([word for(word, word_count) in word_counter.most_common()[:-10-1:-1]]) print(rare_word_list) for i in range(len(sentence_list)):

sentence_list[i] = " ".join([word for word in sentence_list[i].split()

if word not in rare_word_list])

1 2 3 4 5 6 7 8 9 10 11 12 13

5.5.6.3 Stemming và Lemmatization

Loại bỏ các từ hiếm gặp: Bên cạnh stop words thì trong nhiều bài toán ta cũng cần phải loại bỏ các từ hiếm gặp, đặc biệt khi bộ dữ liệu lớn. Đây cũng là kĩ thuật mà ta cần cân nhắc trước khi sử dụng bởi loại bỏ các từ này có thể gây ra sự mất mát về ngữ nghĩa của câu, đặc biệt là với các bộ dữ liệu trung bình, nhỏ. Để loại bỏ các từ hiếm ta sẽ dùng Counter để đếm số lần xuất hiện của các từ và tìm ra các từ ít xuất hiện nhất, sau đó loại bỏ các từ này trong câu như đối với stop words.

Stemming là quá trình biến đổi các từ về dạng gốc của nó (ví dụ: connected, connection khi stemming thu được connect hay moved, move khi stemming thu được mov), lưu ý là stemming

Chương 5. Phát triển ứng dụng với Python 358

from nltk.stem.porter import PorterStemmer stemmer = PorterStemmer() stemmed_sentence_list = [] for i in range(len(sentence_list)):

stemmed_sentence_list.append(" ".join([stemmer.stem(word)

for word in sentence_list[i].split()]))

for i in range(100, 110):

print(stemmed_sentence_list[i]) print("-----")

1 2 3 4 5 6 7 8 9

đơn giản là loại bỏ phần cuối của từ tuy nhiên dạng của từ thu được chưa chắc đã tồn tại trong tiếng Anh (như từ mov). Thông thường kĩ thuật này được sử dụng để chuẩn hóa bộ từ vựng và ta cũng cần cân nhắc sử dụng theo bài toán đặt ra. Trong thư viện NLTK cũng có hỗ trợ thuật toán Porter để thực hiện nhiệm vụ này.

from nltk.stem import WordNetLemmatizer from nltk.corpus import wordnet

wordnet_map = {"N":wordnet.NOUN, "V":wordnet.VERB, "J":wordnet.ADJ, "R":wordnet.ADV} lemmatizer = WordNetLemmatizer() lemmatized_sentence_list = [] for i in range(len(sentence_list)):

pos_tagged_sentence = nltk.pos_tag(sentence_list[i].split()) lemmatized_sentence_list.append(" ".join([lemmatizer.lemmatize(word, wordnet_map.get(pos[0], wordnet.NOUN)) for word, pos in pos_tagged_sentence]))

for i in range(100, 110):

print(lemmatized_sentence_list[i]) print("-----")

1 2 3 4 5 6 7 8 9 10 11 12

Khi quan sát output, ta thấy một số từ như eruption -> erupt, astronomer -> astronom.... Lemmatization về cơ bản là giống với stemming khi nó loại bỏ phần đuôi của từ để thu được gốc từ, tuy nhiên các gốc từ ở đây đều thực sự tốn tại chứ không như stemming (như ví dụ trên thì từ moved sau khi lemmatize sẽ thu được move). Trong thư viện NLTK sẽ sử dụng từ điển Wordnet để map theo các quy tắc (theo tính chất của từ, từ là danh từ, động từ, trạng từ hay tính từ). Sử dụng part-of-speech tagging (nltk.pos_tag) để thu được các tính chất của từ.

5.5.6.4 Loại bỏ các emoji, URL

Có thể thấy từ excited -> excite và invited -> invite. Tuy nhiên, hai kĩ thuật này thường được sử dụng trong tiếng Anh (hoặc ngôn ngữ nào mà một gốc từ có thể biến đổi thành nhiều dạng khác nhau), còn trong tiếng Việt thì ta không dùng vì một từ không có các biến thể khác nhau.

emoji_pattern = re.compile("["

u"\U0001F600-\U0001F64F" # emoticons

1 2

Đối với một số bài toán sử dụng dữ liệu là các văn bản từ những trang mạng xã hội như Twitter, Facebook,... thì việc loại bỏ các biểu tượng cảm xúc - emoji là vô cùng cần thiết. Để loại bỏ emoji ta sẽ sử dụng regex, pattern lấy từ repo này khá đầy đủ và hoạt động tốt.

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

u"\U0001F300-\U0001F5FF" # symbols & pictographs u"\U0001F680-\U0001F6FF" # transport & map symbols u"\U0001F1E0-\U0001F1FF" # flags (iOS) u"\U00002500-\U00002BEF" # chinese char u"\U00002702-\U000027B0" u"\U00002702-\U000027B0" u"\U000024C2-\U0001F251" u"\U0001f926-\U0001f937" u"\U00010000-\U0010ffff" u"\u2640-\u2642" u"\u2600-\u2B55" u"\u200d" u"\u23cf" u"\u23e9" u"\u231a" u"\ufe0f" # dingbats u"\u3030" "]+", flags=re.UNICODE)

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 359

1 2 3

url_example = "You can read more about AI at https://viblo.asia/" url_pattern = re.compile(r’http\S+’) print(url_pattern.sub(r’’, url_example))

Loại bỏ URL: Khi crawl dữ liệu từ nhiều nguồn thì không thể tránh khỏi việc các dữ liệu này sẽ dính các đường dẫn URL khác nhau. Sử dụng regex để loại bỏ các URL đơn giản như sau.

5.5.7.1 Thư viện OpenCV

5.5.7 Project 7. Phát triển ứng dụng với thư viện OpenCV

OpenCV là dự án bắt đầu tại hãng Intel vào năm 1999 bởi Gary Bradsky và ra mắt lần đầu tiên vào năm 2000. Sau đó Vadim Pisarevsky gia nhập và quản lý nhóm. Vào năm 2005, OpenCV được sử dụng trên xe tự lái Stanley và chiếc này đã vô địch giải đấu 2005 DARPA Grand. Tiếp theo nó tiếp tục được cải tiến và phát triển dưới sự hỗ trợ của Willow Garage bên cạnh với Gary Bradsky và Vadim Pisarevsky. Hiện tại OpenCV hỗ trợ vô số các thuật toán liên quan để lĩnh vực thị giác máy tính (computer vision) và lĩnh vực học máy (machine learning).

OpenCV có thể sử dụng được ở hầu hết các ngôn ngữ như C++, Python, Java . . . và các hệ điều hành khác nhau như Windows, Linux, OS X, Android, iOS. Ngoài ra nó thể sử dụng card đồ họa GPU để xử lý nhằm tốc độ xử lý.

Tải OpenCV tại địa chỉ sau: https://pypi.org/project/opencv-python/ Ở đây để đơn giản cho việc cài đặt thì chúng ta sử dụng một thư viện có sẵn trên kho quản lý gói của python là opencv-python. Đây là một thư viện không phải của tổ chức OpenCV tuy nhiên nó có tính năng y hệt và được cập nhật thường xuyên theo sự thay đổi của OpenCV. Hay nói cách khác đây là một đóng gói cho OpenCV trên kho thư viện của python. Nếu bạn muốn sử dụng opencv phiên bản gốc thì lên trang sourceforge.net chọn phiên bản rồi tải xuống. Tiếp

Chương 5. Phát triển ứng dụng với Python 360

Hình 5.57: Thư viện Xử lý hình ảnh OpenCV

1 2

import cv2 print(cv2.__version__)

5.5.7.2 Các thao tác cơ bản với OpenCV

theo là giải nén và cài đặt bằng tay theo hướng dẫn. Vì cách cài đặt này để cái đặt cho nhiều ngôn ngữ khác nhau nên cách này không khuyến khích cho người vừa bắt đầu sử dụng opencv. Sử dụng đoạn lênh sau để cài đặt gói từ kho thư viện pip: pip install opencv-python. Để kiểm tra cài đặt thành công hay không ta thực hiện đoạn lênh sau để kiểm tra phiên bản của opencv-python. Tùy từng thời điểm thì phiên bản của gói sẽ khác nhau. Các phiên bản mới là cập nhật cho opencv mới hơn.

img = cv2.imread(’digital-neon.jpg’) cv2.imshow(’Display Image’, img) cv2.waitKey(0)

1 2 3

Hiển thị hình ảnh: Đầu tiên ta tạo một đối tượng chứa thông tin ảnh được tải lên từ file. Sau đó hiện thị hình ảnh lên cửa sổ giao diện.

img = cv2.imread(’digital-neon.jpg’) (h, w, d) = img.shape print("width={}, height={}, depth={}".format(w, h, d)) Output: width=580, height=326, depth=3

1 2 3 4

Ở đây digital-neon.jpg là file hình ảnh để test, hàm waitKey(0) là hàm chờ không cho thoát cửa sổ lập tức mà phải người dùng nhấn phím bất kỳ để thoát. Lấy kích thước của ảnh:

Ở đây biến img là một đối tượng của Numpy array chứa giá trị màu của từng điểm ảnh trên các không gian màu khác nhau. Lệnh img.shape để lấy ra kích thước của mảng này với h, w, d

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 361

lần lượt là chiều cao, chiều rộng, độ sâu của bước ảnh. Với ảnh có màu thì độ sau thường là 3, ảnh đen trắng là 1.

(B, G, R) = img[50, 50] print("R={}, G={}, B={}".format(R, G, B)) output: R=96, G=100, B=111

1 2 3

Lấy giá trị màu ở một điểm ảnh: Đoạn lệnh sau lấy ra giá trị màu ở điểm ảnh tại vi trí 50, 50 với gốc tọa độ là điểm trên cùng bên trái hình ảnh. Giá trị các thành phần màu có giá trị từ 0 đên 255.

img = cv2.imread(’digital-neon.jpg’) (h, w, d) = img.shape r = 300.0 / w dim = (300, int(h * r)) resized = cv2.resize(img, dim)

1 2 3 4

Thay đổi kích thước ảnh: Để thay đổi kích thước của ảnh trong opencv thì chúng ta sẽ dùng hàm resize. Hàm này cần xác định rõ chiều cao, chiều rộng ảnh sau khi biến đổi. Tuy nhiên ảnh sau khi thay đổi thường cùng tỷ lệ chiều cao, chiều rộng với ảnh gốc. Đoạn lệnh sau biến đối ảnh gốc có chiều rộng 580 pixel sang ảnh có chiều rộng là 300 pixel.

1 2 3 4 5

img = cv2.imread(’digital-neon.jpg’) (h, w, d) = img.shape center = (w // 2, h // 2) M = cv2.getRotationMatrix2D(center, 45, 1.0) rotated = cv2.warpAffine(img, M, (w, h))

5.5.7.3 Các thuật toán chính và ứng dụng của OpenCV

Xoay ảnh: Để xoay được ảnh đầu tiên ta cần xác định gốc xoay và hướng xoay. Sau khi xác định xong tiếp theo ta tính ma trận xoay bằng hàm getRotationMatrix2D trong opencv. Cuối cùng ta nhân ma trận này với ma trận ảnh gốc ta được ảnh sau khi xoay. Đoạn lệnh dưới đây xoay ảnh một góc 45 theo chiều ngược kim đồng hồ với gốc xoay là điểm chính giữa hình ảnh.

OpenCV có khả năng thực hiện nhiều tác vụ như phân loại hình ảnh, phát hiện và phân đoạn đối tượng, trích xuất đặc điểm và thậm chí nhận dạng chữ viết tay của con người,.... nhờ một bộ hơn 2500 thuật toán đã được tối ưu. Trong đó các thuật toán phổ biến nhất có thể kể đến như:

• Thuật toán Support Vector Machines (SVM) và K-Nearest Neighbors (KNN): Đây là hai thuật toán phổ biến trong việc phân loại và nhận dạng mẫu, được áp dụng trong các nhiệm vụ như: nhận diện chữ viết tay, phân loại khuôn mặt và các bài toán xử lý ảnh khác.

• Cây Quyết Định (Decision Trees): Thuật toán này có thể kết hợp với các phương pháp học máy khác như Random Forest hoặc Gradient Boosting để tăng hiệu quả, đặc biệt trong các bài toán như phát hiện đối tượng và phân đoạn ảnh.

• Deep Learning: OpenCV hỗ trợ triển khai các mô hình học sâu từ các framework như TensorFlow và PyTorch, giúp thực hiện các tác vụ như nhận diện đối tượng, phân loại và phân đoạn ảnh.

Chương 5. Phát triển ứng dụng với Python 362

• YOLO: Thuật toán phát hiện đối tượng nổi bật, cho phép nhận diện nhiều đối tượng trong một lần quét ảnh duy nhất.

Ứng dụng của OpenCV trong thực tế gồm:

• Phân tích đặc trưng 2D và 3D: OpenCV cung cấp các công cụ phân tích các đặc trưng 2D và 3D trong hình ảnh và video như so khớp hình ảnh, theo dõi đối tượng và ứng dụng thực tế ảo (AR). Ví dụ, OpenCV có thể phát hiện và so khớp các đặc điểm chính trong hình ảnh để tạo ra ảnh toàn cảnh (panorama) từ nhiều hình ảnh khác nhau. Hoặc kết hợp với các công cụ như OpenMVG, COLMAP hoặc thư viện Structure from Motion (SfM) để có thể tạo ảnh 3D.

• Nhận diện khuôn mặt và mở khóa thiết bị: Thêm một ứng dụng phổ biến của OpenCV là nhận diện khuôn mặt đã được sử dụng trong nhiều hệ thống bảo mật. OpenCV có thể nhận diện khuôn mặt và giúp mở khóa điện thoại thông minh hoặc cấp quyền truy cập vào các khu vực bảo mật bằng cách nhận diện khuôn mặt người dùng.

• Nhận diện cử chỉ và tương tác giữa người và máy tính: OpenCV giúp phát triển các hệ thống nhận diện cử chỉ, cho phép người dùng tương tác với máy tính hoặc các thiết bị thông qua các cử chỉ và chuyển động tay. Công nghệ này rất phổ biến trong các trò chơi, thực tế ảo (VR),... Ví dụ webcam có thể theo dõi chuyển động tay của người dùng, cho phép điều khiển các hành động trên màn hình như điều hướng menu hay chơi game mà không cần sử dụng bộ điều khiển vật lý.

• Hiểu chuyển động và phát hiện đối tượng: Các thuật toán của OpenCV thường được tích hợp trong các hệ thống giám sát, xe tự lái (nhận diện vạch đường, vật thể) và robot nhờ khả năng hiểu chuyển động và phát hiện đối tượng. Chẳng hạn như kỹ thuật "Background Subtraction" giúp nhận diện chuyển động khi phát hiện một vật thể đã xuất hiện trong khung hình. Hoặc Optical Flow và Deep Learning cũng là hai nhóm thuật toán thường được sử dụng để theo dõi đối tượng trong thời gian thực.

• Tạo hiệu ứng 3D và độ sâu: OpenCV hỗ trợ một số kỹ thuật xử lý ảnh và video liên quan đến hiệu ứng 3D như ước lượng độ sâu từ ảnh stereo (với các thuật toán như StereoBM và StereoSGBM) và theo dõi chuyển động (Optical Flow). Tuy nhiên, để tạo ra đồ họa 3D hoàn chỉnh hoặc các hiệu ứng thị giác phức tạp thường cần kết hợp OpenCV với các công cụ chuyên biệt như OpenGL, Unreal Engine hoặc các phần mềm dựng hình 3D.

Những thách thức khi sử dụng OpenCV:

• Độ phức tạp: Với nhiều tính năng và chức năng, OpenCV có thể khiến người mới bắt đầu cảm thấy choáng ngợp và mất thời gian để làm quen.

• Thiếu tính năng nâng cao: OpenCV phù hợp với các tác vụ cơ bản và trung cấp nhưng thiếu các tính năng tiên tiến như các thư viện chuyên dụng cho học sâu như TensorFlow hay PyTorch.

• C++ là ngôn ngữ chính: Nền tảng OpenCV chủ yếu được viết bằng C++, điều này có thể gây khó khăn cho những lập trình viên quen thuộc với các ngôn ngữ cấp cao như Python hay Java.

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 363

5.5.7.4 Ứng dụng nhận điện khuôn mặt với OpenCV

• Quản lý phụ thuộc: Việc tích hợp OpenCV với các thư viện khác trong dự án phức tạp có thể gặp phải vấn đề tương thích và quản lý phụ thuộc. • Hiệu suất: OpenCV có thể không tối ưu cho các tác vụ đặc thù yêu cầu hiệu suất cao, so với việc viết mã tùy chỉnh. • Tài liệu hạn chế: Một số tài liệu của OpenCV có thể không đầy đủ hoặc đã lỗi thời, gây khó khăn trong việc tìm kiếm thông tin. • Hạn chế trong học máy: OpenCV không phải là thư viện chuyên dụng cho học máy nên không thể đáp ứng đầy đủ các yêu cầu phức tạp như các thư viện học sâu.

Nhận dạng mặt người (Face recognition) là một lĩnh vực nghiên cứu của ngành Computer Vision, và cũng được xem là một lĩnh vực nghiên cứu của ngành Biometrics (tương tự như nhận dạng vân tay – Fingerprint recognition, hay nhận dạng mống mắt – Iris recognition). Xét về nguyên tắc chung, nhận dạng mặt có sự tương đồng rất lớn với nhận dạng vân tay và nhận dạng mống mắt, tuy nhiên sự khác biệt nằm ở bước trích chọn đặt trưng (feature extraction) của mỗi lĩnh vực.

Trong khi nhận dạng vân tay và mống mắt đã đạt tới độ chín, tức là có thể áp dụng trên thực tế một cách rộng rãi thì nhận dạng mặt người vẫn còn nhiều thách thức và vẫn là một lĩnh vực nghiên cứu thú vị với nhiều người. So với nhận dạng vân tay và mống mắt, nhận dạng mặt có nguồn dữ liệu phong phú hơn (bạn có thể nhìn thấy mặt người ở bất cứ tấm ảnh, video clip nào liên quan tới con người trên mạng) và ít đòi hỏi sự tương tác có kiểm soát hơn (để thực hiện nhận dạng vân tay hay mống mắt, dữ liệu input lấy từ con người đòi hỏi có sự hợp tác trong môi trường có kiểm soát).

Hiện nay các phương pháp nhận dạng mặt được chia thành nhiều hướng theo các tiêu chí khác nhau: nhận dạng với dữ liệu đầu vào là ảnh tĩnh 2D (still image based FR) là phổ biến nhất, tuy nhiên tương lai có lẽ sẽ là 3D FR (vì việc bố trí nhiều camera 2D sẽ cho dữ liệu 3D và đem lại kết quả tốt hơn, đáng tin cậy hơn), cũng có thể chia thành 2 hướng là: làm với dữ liệu ảnh và làm với dữ liệu video.

Trên thực tế người ta hay chia các phương pháp nhận dạng mặt ra làm 3 loại: phương pháp tiếp cận toàn cục (global, như Eigenfaces-PCA, Fisherfaces-LDA), phương pháp tiếp cận dựa trên các đặc điểm cục bộ (local feature based, như LBP, Gabor wavelets) và phương pháp lai (hybrid, là sự kết hợp của hai phương pháp toàn cục và local feature). Phương pháp dựa trên các đặc điểm cục bộ đã được chứng minh là ưu việt hơn khi làm việc trong các điều kiện không có kiểm soát và có thể nói rằng lịch sử phát triển của nhận dạng mặt (A never ending story) là sự phát triển của các phương pháp trích chọn đặc trưng (feature extractrion methods) được sử dụng trong các hệ thống dựa trên feature based.

Các ứng dụng cụ thể của nhận dạng mặt dựa trên 2 mô hình nhận dạng: identification (xác định danh tính, bài toán 1-N), và verification (xác thực danh tính, bài toán 1-1). Trong bài toán identification, ta cần xác định danh tính của ảnh kiểm tra, còn trong bài toán verification ta cần xác định 2 ảnh có cùng thuộc về một người hay không.

Chương 5. Phát triển ứng dụng với Python 364

- Bước 1. Cài đặt OpenCV, copy file cv2.pyd từ thư mục \face detection\opencv\build\python\3.12

1 2

pip install numpy pip install pillow

vào thư mục \Python3.12\Lib\site-packages. Cài đặt numpy vào thư mục \Python27\Scripts chạy lệnh

Chúng ta sử dụng phương pháp nhận diện khuôn mặt đơn giản Haar-cascade Detection. Sử dụng haarcascade_frontalface_default.xml từ \opencv\sources\data\haarcascades, copy vào thư mục của dự án.

Cài đặt sqlite, tạo CSDL FaceBase với bảng People. - Bước 2. Viết mã nguồn. Với ứng dụng này, chúng ta sẽ tạo phần mềm nhận diện khuôn mặt bằng giai đoạn

def insertOrUpdate(Id,Name):

conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(Id) cursor=conn.execute(cmd) isRecordExist=0 for row in cursor: isRecordExist=1 if(isRecordExist==1):

cmd="UPDATE People SET Name="+str(Name)+"WHERE ID="+str(Id)

else:

cmd="INSERT INTO People(Id,Name) Values("+str(Id)+","+str(Name)+")"

conn.execute(cmd) conn.commit() conn.close()

1 2 3 4 5 6 7 8 9 10 11 12 13 14

• Giai đoạn 1. Tạo dataSet dùng để nhận diện. • Giai đoạn 2. Tạo dataTraning sử dụng để traning dữ liệu. • Giai đoạn 3. Tạo lớp detector dể nhận diện. Kết nối sqlite để tạo/cập nhật record

id=raw_input(’enter your id’) name=raw_input(’enter your name’) insertOrUpdate(id,name) sampleNum=0 while(True):

ret, img = cam.read() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = detector.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) #incrementing sample number sampleNum=sampleNum+1 #saving the captured face in the dataset folder cv2.imwrite("dataSet/User."+id +’.’+ str(sampleNum) + ".jpg", gray[y:y+h,x:x+w])

Mã nguồn dùng camera để chụp hình dữ liệu:

cv2.imshow(’frame’,img)

#wait for 100 miliseconds if cv2.waitKey(100) & 0xFF == ord(’q’):

break

# break if the sample number is morethan 20 elif sampleNum>20:

15 16 17 18 19 20 21 22 23

break cam.release() cv2.destroyAllWindows()

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 365

import cv2 import sqlite3 cam = cv2.VideoCapture(0) detector=cv2.CascadeClassifier(’haarcascade_frontalface_default.xml’) #insert/update data to sqlite def insertOrUpdate(Id,Name):

conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(Id) cursor=conn.execute(cmd) isRecordExist=0 for row in cursor: isRecordExist=1 if(isRecordExist==1):

cmd="UPDATE People SET Name="+str(Name)+"WHERE ID="+str(Id)

else:

cmd="INSERT INTO People(Id,Name) Values("+str(Id)+","+str(Name)+")"

conn.execute(cmd) conn.commit() conn.close()

id=raw_input(’enter your id’) name=raw_input(’enter your name’) insertOrUpdate(id,name) sampleNum=0 while(True):

#camera read ret, img = cam.read() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = detector.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces:

cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) #incrementing sample number sampleNum=sampleNum+1 #saving the captured face in the dataset folder cv2.imwrite("dataSet/User."+id+’.’+str(sampleNum)+".jpg",gray[y:y+h,x:x+w]) cv2.imshow(’frame’,img)

#wait for 100 miliseconds if cv2.waitKey(100) & 0xFF == ord(’q’):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

break

Dữ liệu lưu vào sqlite, dataSetCreator đầy đủ:

# break if the sample number is morethan 20 elif sampleNum>20:

40 41 42 43 44

break cam.release() cv2.destroyAllWindows()

Chương 5. Phát triển ứng dụng với Python 366

1 2

path=’dataSet’ imagePaths=[os.path.join(path,f) for f in os.listdir(path)]

Tạo lớp traning dữ liệu:

1

ID=int(os.path.split(imagePath)[-1].split(’.’)[1])

Tách ID từ tên file ảnh:

faceImg=Image.open(imagePath).convert(’L’); faceNp=np.array(faceImg,’uint8’) faces.append(faceNp)

1 2 3

Convert ảnh và thêm vào mảng faces cùng với ID, đối với bàn toán phân lớp (classfication) thì Feature là ảnh còn Label chính là ID người dùng.

recognizer.train(faces,np.array(Ids)) recognizer.save(’recognizer/trainningData.yml’)

1 2

Traning và lưu vào file:

import cv2,os import numpy as np from PIL import Image

recognizer = cv2.face.LBPHFaceRecognizer_create() path=’dataSet’

def getImagesAndLabels(path):

#get the path of all the files in the folder imagePaths=[os.path.join(path,f) for f in os.listdir(path)] faces=[] IDs=[] for imagePath in imagePaths:

faceImg=Image.open(imagePath).convert(’L’); faceNp=np.array(faceImg,’uint8’) #split to get ID of the image ID=int(os.path.split(imagePath)[-1].split(’.’)[1]) faces.append(faceNp) print ID IDs.append(ID) cv2.imshow("traning",faceNp) cv2.waitKey(10)

return IDs, faces

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

Code Traning đầy đủ:

Ids,faces=getImagesAndLabels(path) #trainning recognizer.train(faces,np.array(Ids)) recognizer.save(’recognizer/trainningData.yml’) cv2.destroyAllWindows()

25 26 27 28 29

5.5 Phát triển ứng dụng trí tuệ nhân tạo với Python 367

#get data from sqlite by ID def getProfile(id):

conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(id) cursor=conn.execute(cmd) profile=None for row in cursor: profile=row

conn.close() return profile

1 2 3 4 5 6 7 8 9 10

Lớp detector nhận diện khuôn mặt đã traning. Lấy thông tin user từ Database:

ret,img=cam.read(); gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) faces=faceDetect.detectMultiScale(gray,1.3,5);

1 2 3

Sử dụng camera để nhận diện :

for(x,y,w,h) in faces:

cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) id,conf=rec.predict(gray[y:y+h,x:x+w]) profile=getProfile(id) if(profile!=None):

1 2 3 4 5 6 7 8

cv2.putText(img,"Name:"+ str(profile[1]),(x,y+h+30),fontface,fontscale,fontcolor,2) cv2.putText(img,"Age:"+str(profile[2]),(x,y+h+60),fontface,fontscale,fontcolor,2) cv2.putText(img,"Gender:"+str(profile[3]),(x,y+h+90),fontface,fontscale,fontcolor,2)

Hiển thị thông tin User bằng text

import cv2 import numpy as np from PIL import Image import pickle import sqlite3

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

faceDetect=cv2.CascadeClassifier(’haarcascade_frontalface_default.xml’); cam=cv2.VideoCapture(0); rec=cv2.face.LBPHFaceRecognizer_create(); rec.read("recognizer\\trainningData.yml") id=0 #set text style fontface = cv2.FONT_HERSHEY_SIMPLEX fontscale = 1 fontcolor = (203,23,252)

Code detector:

#get data from sqlite by ID def getProfile(id):

conn=sqlite3.connect("FaceBase.db") cmd="SELECT * FROM People WHERE ID="+str(id) cursor=conn.execute(cmd) profile=None for row in cursor: profile=row

conn.close( return profile

while(True):

#camera read ret,img=cam.read(); gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) faces=faceDetect.detectMultiScale(gray,1.3,5); for(x,y,w,h) in faces:

cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) id,conf=rec.predict(gray[y:y+h,x:x+w]) profile=getProfile(id) #set text to window if(profile!=None):

#cv2.PutText(cv2.fromarray(img),str(id),(x+y+h),font,(0,0,255),2); cv2.putText(img, "Name: " + str(profile[1]), (x,y+h+30), fontface, fontscale, fontcolor ,2) cv2.putText(img, "Age: " + str(profile[2]), (x,y+h+60), fontface, fontscale, fontcolor ,2) cv2.putText(img, "Gender: " + str(profile[3]), (x,y+h+90), fontface, fontscale, fontcolor ,2)

cv2.imshow(’Face’,img) if cv2.waitKey(1)==ord(’q’):

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

break; cam.release() cv2.destroyAllWindows()

Chương 5. Phát triển ứng dụng với Python 368

6. Phụ lục A. Môi trường thực hành

6.1 Môi trường lập trình Notepad++

Hiện nay có rất nhiều phần mềm hỗ trợ cho việc lập trình tuy nhiên Notepad gần như là phần mềm mà các coder không dùng cũng thường có trong máy tính của mình. Nếu chúng ta mới bắt đầu học lập trình thì có thể sử dụng Notepad++ để lập trình trước khi sử dụng những phần mềm khác.

Nếu máy tính chưa có Notepad++, sinh viên có thể tải về phiên bản mới nhất tại: https://notepad-plus-plus.org/downloads/. Sinh viên lựa chọn phiên bản mới nhất là Notepad++ v8.5.4 hoặc chọn phiên bản phù hợp với máy tính của mình (xem Hình 6.1).

Hình 6.1: Download Notepad++

Chương 6. Phụ lục A. Môi trường thực hành 370

Sau khi tải về, chúng ta cài đặt file npp.8.5.4.Installer.x64.exe dưới quyền Administrator. Chọn OK, chọn Next, chọn I Agree

Hình 6.2: Các bước cài đặt Notepad++ v8.5.4

Chọn các thành phần sẽ cài đặt, nhấn Next. Tích vào Create Shortcut on Desktop và chọn Install, cuối cùng chọn Finish.

Hình 6.3: Tùy chọn các thành phần cài đặt Notepad++ v8.5.4

Đến đây chúng ta đã có thể lập trình được Python trên Notepad ++. Tuy nhiên khi chạy chương trình chúng ta phải mở cửa sổ cmd hoặc powershell trên Windows ra để chạy. Để thuận tiện cho việc lập trình, chúng ta nên mở cửa sổ console bên dưới phần code để thuận tiện cho việc chạy chương trình.

Đầu tiên, chúng ta vào menu Plugins chọn Plugins Admin. Sau đó chọn cài đặt plugin NppExec bằng cách tích vào ô vuông và chọn Install ở góc bên phải cửa sổ, chọn Install. Chọn Yes khi đó Notepad++ sẽ cài đặt plugin và khởi động lại. Sau khi cài đặt xong để hiện cửa sổ console để làm việc như Hình 6.4.

371

Hình 6.4: Cài đặt cửa sổ console làm việc với Notepad++ v8.5.4

Để soạn và chạy được chương trình Python, chúng ta phải chạy câu lệnh cmd để bắt đầu sử dụng. Chúng ta bắt đầy với ví dụ đơn giản tạo chương trình in dòng chữ xin chào các bạn lưu thành file hello.py như sau:

Hình 6.5: Soạn thảo và thực thi chương trình Python qua cmd với Notepad++ v8.5.4

Sau đó, chúng ta gõ tên file python đã lập trình sẵn và chạy chương trình. Thay vì gõ lệnh cmd, chúng ta cũng có thể sử dụng PowerShell của windows. Khi chạy chương trình nếu chỉ đánh tên file sẽ xảy ra lỗi vì thế chúng ya phải thêm ./ vào trước tên file, ví dụ: ./hello.py. Chú ý, để hiện thị được tiếng việt ở cửa sổ console thì phải thiết lập ở plugin như sau:

Chương 6. Phụ lục A. Môi trường thực hành 372

Hình 6.6: Soạn thảo và thực thi chương trình Python qua PowerShell với Notepad++ v8.5.4

6.2 Môi trường lập trình Eclipse

Để lập trình trên môi trường Eclipse ta cài đặt PyDev cho lập trình Python. PyDev là một Plugin cho phép chúng ta cài đặt vào Eclipse, và chúng ta có thể lập trình Python trên Eclipse IDE. Eclipse là một IDE sử dụng để phát triển Java. Tuy nhiên nó cho phép cài đặt thêm các plugin để trở thành công cụ lập trình các ngôn ngữ khác như C/C++, Ruby, Python, PHP, ...

Cài đặt PyDev: Trên Eclipse chọn Help\Eclipse Marketplace, nhập vào "PyDev" để tìm kiếm:

Hình 6.7: Tìm kiếm cài đặt pydev trên Eclipse Marketplace

373

Sau khi lựa chọn các bước để cài đặt thành công, chúng ta cần khởi động lại Eclipse

Hình 6.8: Các bước cài đặt pydev trên Eclipse và khởi động lại

Để kiểm tra lại Eclipse sau khi cài đặt, trên Eclipse chọn File\New\Other. Nếu nhìn thấy PyDev trên cửa sổ Wizard có nghĩa là PyDev đã được cài đặt thành công vào Eclipse.

Tiếp theo, chúng ta cần cấu hình Interpreter với Eclipse. Đây là bộ thông dịch sử dụng để

thông dịch mã Python sang mã máy tính. Trên Eclipse chọn: Window\Preferences\PyDev\Interpreters\Python Interpreter di chuyển đến thư mục cài đặt Python và chọn python.exe, nhấn OK.

Hình 6.9: Cấu hình Interpreter với Eclipse

Chương 6. Phụ lục A. Môi trường thực hành 374

Thết lập đường dẫn đến SYSTEM, chọn Apply và đóng lại để hoàn tất việc tích hợp Python với Eclipse.

Hình 6.10: Cấu hình Interpreter với Eclipse

6.3 Môi trường lập trình Sublime Text

Sublime text hay còn biết đến là trình soạn thảo mã nguồn đa nền tảng độc quyền với giao diện của ngôn ngữ lập trình Python. Công cụ này được nhiều developer sử dụng rộng rãi vì vừa miễn phí vừa đầy đủ các tính năng hỗ trợ cần thiết. Sublime text hỗ trợ cả ngôn ngữ lập trình và ngôn ngữ đánh dấu cho phép người dùng thêm các chức năng vào plugin theo ý muốn.

Khả năng tùy biến là một trong những ưu điểm nổi bật đầu tiên khi nhắc đến trình soạn thảo Sublime text khi lập trình viên thiết kế website có thể hoàn toàn tùy chỉnh như ý muốn thông qua các plugin. Lập trình viên được cho phép cài đặt, nâng cao, hoặc gỡ bỏ các plugin trực tiếp từ bên trong trình chỉnh sửa mà không cần phải thao tác lại từ đầu (khởi động). Github, BitBucket và PackageControl.io là cộng đồng mà người dùng có thể tải xuống các gói của Sublime text rồi cho vào kho lưu trữ riêng. Những cộng đồng trên đều sử dụng trình soạn thảo này với nhiều plugin. Sublime text có chức năng Goto và Command Palette có thể tìm kiếm các biểu thức thông thường, phân biệt chữ thường với chữ hoa hoặc tìm toàn bộ từ khóa. Không những thế, Sublime còn cho phép người dùng các kết quả tìm kiếm vào bộ đệm để có thể sử dụng lại cho lượt search tiếp theo. Sublime text còn có khả năng hiển thị nhiều tập tin văn bản trên các cách khác nhau. Người dùng có thể có một số tập tin đang mở sẵn được sắp xếp trong các tab. Đấy chính là cách mà lập trình viên có thể di chuyển và sắp xếp lại chúng theo ý muốn. Cách này được xem là khá tiêu chuẩn, tuy nhiên vẫn còn nhiều cách khác. Ngoài ra, công cụ này còn cho người dùng chỉnh sửa các bố cục khác như hàng và cột, chỉnh sửa toàn màn hình (Distraction Free).

Trình soạn thảo mã nguồn Sublime text được xây dựng trên Python và C/C++ nên trình chỉnh sửa rất nhẹ. Nó rất nhanh, khi bạn mở Sublime text từ Menu Start của Windows ngay lập tức sẽ tải xuống và chỉ mất vài giây để nó xuất hiện trên màn hình của bạn. Hơn nữa,

375

công cụ được đánh giá là ổn định nhất so với các trình soạn thảo mã khác. Tình trạng treo và crash rất hiếm khi xảy ra. Trình soạn thảo mã Sublime text được cài sẵn trên các nền tảng Mac, Windows và Linux. Vì thế, người dùng dễ dàng sử dụng trên mọi máy tính. Nó có sử dụng bộ công cụ UI tùy chỉnh nên giao diện được tối ưu hóa rất tốt cả về mặt tốc độ lẫn thẩm mỹ. Không những thế, nó còn tận dụng mọi chức năng gốc trên mỗi nền tảng. Mọi thứ trong Sublime text đều có thể tùy chỉnh với các tệp JSON dễ dàng. Sử dụng trình soạn thảo này giúp người dùng linh hoạt trong việc cài đặt có thể chỉ định trên từng loại tệp, từng project.

Để tải xuống Sublime Text: Chúng ta truy cập trang web chính thức của Sublime Text và tải xuống phiên bản phù hợp cho hệ điều hành của mình.

Cấu hình Sublime Text cho Python

• Bước 1. Mở Command Palette: Đi đến menu Tools trên thanh công cụ, chọn Command Palette hoặc nhấn tổ hợp phím Ctrl + Shift + P (Windows/Linux) hoặc Cmd + Shift + P (Mac).

• Bước 2. Cài đặt Package Control: Trong Command Palette, gõ Install Package Control và chọn tùy chọn này từ danh sách thả xuống. Điều này sẽ cài đặt Package Control trên trình soạn thảo Sublime Text.

{

"target": "terminus_exec", "cancel": "terminus_cancel_build", "focus": true, "timeit": true,

"cmd": ["python3", "-u", "$file"], "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)", "selector": "source.python",

"env": {"PYTHONIOENCODING": "utf-8"},

"windows": {

"cmd": ["python", "-u", "$file"],

},

"variants": [

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

{

• Bước 3. Cài đặt Terminus: Sau khi cài đặt Package Control, mở lại Command Palette và bắt đầu gõ Package Control. Chọn Package Control và Install Package từ danh sách thả xuống, trong danh sách các gói, gõ và chọn Terminus. Sau khi tải xuống và cài đặt Terminus hoàn tất, nó sẽ xuất hiện dưới Preferences > Package Settings > Terminus. • Bước 4. Tạo New Build System với Sublime Text cho Python: Trên thanh công cụ của Sublime Text, chọn Tools, chọn Build System và sau đó chọn New Build System. Một tệp tin mới sẽ mở ra với nội dung mặc định. Thay thế nội dung này bằng đoạn mã sau để cấu hình Build System cho Python:

"name": "Syntax Check", "cmd": ["python3", "-m", "py_compile", "$file"],

"windows": {

"cmd": ["py", "-m", "py_compile", "$file"],

}

}

]

20 21 22 23 24 25 26 27 28

}

Chương 6. Phụ lục A. Môi trường thực hành 376

Lưu tệp tin này với tên như Python-Termius.sublime-build. – Trên Windows, tệp sẽ được lưu trong thư mục: C:\Users\ \AppData\Roaming\Sublime Text 3\Packages\User

– Trên macOS: ˜/Library/Application Support/Sublime Text 3/Packages/User – Trên Linux: ˜/.config/sublime-text-3/Packages/User

• Bước 5. Sử dụng Build System mới: Sau khi lưu tệp Build System, quay lại Sublime Text. Di chuyển đến Tools\Build System và chọn Python-Termius (tên đã đặt cho Build System). Chạy mã Python trong Sublime Text: Mở tệp tin Python mà bạn muốn chạy, nhấn Ctrl + B (Windows/Linux) hoặc Cmd + B (Mac) để chạy mã Python bằng Build System mới.

6.4 Môi trường lập trình Spyder

Spyder (trước đây là Pydee) là một nguồn mở đa nền tảng và môi trường phát triển tích hợp (IDE) để lập trình khoa học bằng ngôn ngữ Python. IDE này được phát hành theo giấy phép MIT. Spyder là có thể mở rộng với các plugin. Nó bao gồm hỗ trợ cho các công cụ tương tác để kiểm tra dữ liệu và kết hợp các kiểm soát chất lượng dành riêng cho Python và các công cụ như Pyflakes, Pylint và Rope.

Spyder là một môi trường khoa học mã nguồn mở miễn phí được viết bằng Python, dành cho Python, được thiết kế bởi và dành cho các nhà khoa học, kỹ sư và nhà phân tích dữ liệu. Nó có sự kết hợp độc đáo giữa chức năng chỉnh sửa, phân tích, gỡ lỗi và lập hồ sơ nâng cao của một công cụ phát triển toàn diện với khả năng khám phá dữ liệu, thực thi tương tác, kiểm tra sâu và khả năng trực quan hóa của một gói khoa học.

Các tính năng chung của Spyder: • Trình chỉnh sửa tích hợp IDE này là đa ngôn ngữ. Tôi đã có một trình duyệt chức năng / lớp, các chức năng phân tích cú pháp mã (pyflakes và pylint hiện đang được hỗ trợ), tùy chọn hoàn thành mã, phân tách theo chiều ngang và dọc và định nghĩa goto.

• Bảng điều khiển tương tác. Bảng điều khiển Python hoặc IPython là một không gian làm việc và hỗ trợ gỡ lỗi để đánh giá ngay lập tức mã được viết trong Trình chỉnh sửa. Nó cũng đi kèm với Tích hợp hình Matplotlib.

• Tôi đã đặt ra một người xem tài liệu. Chương trình sẽ có thể hiển thị cho chúng tôi tài liệu về bất kỳ lệnh gọi lớp hoặc hàm nào được thực hiện trong Trình chỉnh sửa hoặc

377

trong bảng điều khiển.

• Chúng tôi sẽ có thể khám phá các biến được tạo trong quá trình thực thi tệp. Có thể chỉnh sửa chúng bằng các trình soạn thảo dựa trên GUI khác nhau, chẳng hạn như từ điển và ma trận Numpy. • Chúng tôi sẽ có khả năng tìm kiếm trong kho lưu trữ. Nó cũng sẽ cung cấp cho chúng tôi hỗ trợ biểu thức chính quy.

• Chúng ta có thể có một Trình duyệt tệp để thoải mái hơn. Chúng tôi cũng sẽ có thể truy cập vào hồ sơ lịch sử. Spyder cũng có thể được sử dụng như một thư viện mở rộng PyQt5 / PyQt4 (trình gián điệp mô-đun). Tiện ích trình bao tương tác Python được sử dụng trong Spyder có thể được tích hợp vào ứng dụng PyQt5 / PyQt4 của riêng bạn. Đối với những ai cần nó, bạn có thể tham khảo mã nguồn của dự án và các đặc điểm của nó trên trang GitHub của dự án.

Hình 6.11: Môi trường lập trình Spyder

Cài đặt Spyder: Chúng ta có thể cài đặt IDE này trên các hệ thống Gnu/Linux khác nhau. Trong phần này, quá trình cài đặt sẽ được thực hiện trên Ubuntu 17.10. Để hoạt động chính xác chúng ta cần đáp ứng các yêu cầu nhất định cần thiết về những gói nào khác được yêu cầu để cài đặt thành công. Khi các gói phụ thuộc được hoàn thành, chúng ta sẽ có thể thực hiện cài đặt bằng cách mở terminal (Ctrl + Alt + T) và viết vào đó: sudo apt install spyder. Chúng ta cũng có thể cài đặt chương trình này bằng pip. Để thực hiện việc này từ terminal (Ctrl + Alt + T), viết: sudo pip install spyder.

Gỡ cài đặt Spyder: Để gỡ cài đặt IDE này khỏi Ubuntu, chúng ta mở thiết bị đầu cuối (Ctrl + Alt + T) và viết nội dung sau: sudo apt remove spyder && sudo apt autoremove Nếu chọn cài đặt bằng pip, chúng ta có thể gỡ cài đặt chương trình bằng cách nhập vào terminal: sudo pip uninstall spyder

6.5 Môi trường lập trình PyCharm

PyCharm là một phần mềm được phát triển bởi JetBrains, cung cấp các công cụ cần thiết

Chương 6. Phụ lục A. Môi trường thực hành 378

giúp các lập trình viên Python tăng năng suất làm việc. Ngoài ra, PyCharm còn được tích hợp nhiều yếu tố mở rộng khác như: biên dịch mã, tô sáng cú pháp, điều hướng project nhanh chóng, công cụ cơ sở dữ liệu và trình soạn thảo văn bản có tích hợp lập trình nhằm mục đích thúc đẩy quá trình phát triển Website.

PyCharm cũng tương tự như Python, là một trong những IDE được nhiều người dùng ưa chuộng và sử dụng rộng rãi trong giới lập trình. Nhờ sự tiện lợi và hiệu quả cao, PyCharm đã được nhiều doanh nghiệp có tầm ảnh hưởng lớn sử dụng làm IDE Python như: Symantec, Twitter, Pinterest,...

Một trong những điểm mạnh của việc sử dụng PyCharm là khả năng cung cấp API cho các nhà phát triển, đồng thời cho phép họ viết các plugin riêng để mở rộng tính năng. Hơn nữa, phần mềm này còn tương thích với đa dạng các hệ điều hành như Linux, Windows và macOS. Điều này, giúp các lập trình viên Python tiết kiệm thời gian đáng kể trong quá trình phát triển một ứng dụng hay website nào đó.

Sau đây là các bước hướng dẫn chi tiết về cách tải và cài đặt phần mềm PyCharm:

- Bước 1: Trước tiên, truy cập vào website PyCharm theo đường link: https://www.jetbrains.com/pycharm/ và nhấn chọn “Tải xuống” để tài phần mềm về máy.

Hình 6.12: Tải phần mềm từ website PyCharm

- Bước 2: Trên màn hình sẽ hiển thị hai lựa chọn tải phần mềm PyCharm, trong đó:

• Professional: Là phiên bản chuyên nghiệp, được sử dụng để phát triển Web Python và khoa học. Với phiên bản này được hỗ trợ nhiều ngôn ngữ lập trình khác nhau như: HTML, JS và SQL. Đồng thời, cho phép người dùng thử nghiệm miễn phí trước khi mua bản quyền. • Community: Là phiên bản miễn phí nên chỉ có thể sử dụng để phát triển Python thuần túy.

379

Hình 6.13: Lựa chọn phiên bản tải phần mềm PyCharm

Chúng ta có thể lựa chọn một trong hai phiên bản trên và nhấn “Download” để tải xuống.

- Bước 3: Sau khi tải về thành công, bạn click vào file vừa tải về để tiến hành cài đặt.

Hình 6.14: Lựa chọn phiên bản tải phần mềm PyCharm

- Bước 4: Tiếp theo, nhấn chọn “Next” để tiếp tục.

Hình 6.15: Cài đặt phần mềm PyCharm

- Bước 5: Sau đó click chuột vào “Browse” để lựa chọn thư mục muốn lưu trữ và nhấn “Next” để sang bước tiếp theo.

Chương 6. Phụ lục A. Môi trường thực hành 380

Hình 6.16: Cài đặt phần mềm PyCharm

- Bước 6: Khi màn hình xuất hiện như hình bên dưới, bạn tích vào các ô PyCharm, Add “Open Folder as Project”, py và Add “bin” folder to the PATH. Sau đó nhấn chọn “Next” để chuyển sang bước tiếp theo.

Hình 6.17: Cài đặt phần mềm PyCharm

- Bước 7: Tiếp theo, bạn nhấn chọn “Install” để tiếp tục.

Hình 6.18: Cài đặt phần mềm PyCharm

- Bước 8: Chờ khoảng 1 phút khi quá trình cài đặt đạt 100%, bắt đầu nhấn “Next” để hoàn tất quá trình cài đặt.

381

Hình 6.19: Cài đặt phần mềm PyCharm

- Bước 9: Nếu muốn khởi động lại ngay có thể tích vào ô “Reboot now” hoặc nếu muốn khởi động sau có tích vào ô “I want to manually reboot later”. Cuối cùng, chỉ cần nhấn chọn “Finish” là đã hoàn tất quá trình cài đặt phần mềm PyCharm.

Hình 6.20: Cài đặt phần mềm PyCharm

7. Phụ lục B. Đáp án câu hỏi trắc nghiệm

7.1 Đáp án câu hỏi trắc nghiệm Chương 1

Câu hỏi Đáp án

1 C

2 B

3 A

4 B

5 B

6 D

7 A

8 B

9 C

10 C

11 D

12 C

13 B

14 C

15 A

Câu hỏi Đáp án

16 B

17 B

18 A

19 C

20 A

21 B

22 B

23 B

24 A

25 D

26 D

27 A

28 B

29 A

30 D

Câu hỏi Đáp án

31 A

32 C

33 B

34 D

35 C

36 A

37 B

38 A

39 B

40 A

41 D

42 A

43 C

44 B

45 B

Câu hỏi Đáp án

46 A

47 A

48 B

49 D

50 B

7.2 Đáp án câu hỏi trắc nghiệm Chương 2

Câu hỏi Đáp án

1 B

2 D

3 A

4 B

5 C

6 C

7 C

8 D

9 B

10 B

11 D

12 B

13 D

14 B

15 B

Câu hỏi Đáp án

16 A

17 A

18 C

19 A

20 B

21 B

22 C

23 C

24 A

25 C

26 C

27 C

28 C

29 C

30 B

Câu hỏi Đáp án

31 D

32 C

33 C

34 B

35 A

36 B

37 A

38 C

39 A

40 B

41 B

42 D

43 A

44 C

45 C

Câu hỏi Đáp án

46 B

47 B

48 A

49 A

50 B

Chương 7. Phụ lục B. Đáp án câu hỏi trắc nghiệm 384

7.3 Đáp án câu hỏi trắc nghiệm Chương 3

Câu hỏi Đáp án

1 C

2 C

3 A

4 C

5 A

6 D

7 B

8 C

9 A

10 C

11 C

12 C

13 C

14 C

15 B

Câu hỏi Đáp án

16 B

17 B

18 B

19 B

20 B

21 A

22 C

23 B

24 D

25 A

26 A

27 B

28 B

29 C

30 C

Câu hỏi Đáp án

31 A

32 C

33 C

34 A

35 A

36 A

37 B

38 C

39 A

40 A

41 B

42 A

43 D

44 D

45 B

Câu hỏi Đáp án

46 B

47 A

48 A

49 C

50 C

51 C

52 B

53 C

54 A

55 B

56 A

57 D

58 D

59 A

60 A

Câu hỏi Đáp án

61 D

62 A

63 A

64 C

65 A

66 A

67 D

68 C

69 D

70 C

71 A

72 A

73 A

74 A

75 C

Câu hỏi Đáp án

76 A

77 C

78 B

79 A

80 B

81 C

82 B

83 B

84 A

85 A

86 A

87 D

88 D

89 B

90 B

Câu hỏi Đáp án

91 B

92 B

93 C

94 B

95 D

96 D

97 B

98 B

99 C

100 C

7.4 Đáp án câu hỏi trắc nghiệm Chương 4

Câu hỏi Đáp án

1 B

2 D

3 B

4 C

5 C

6 A

7 A

8 B

9 B

10 C

11 A

12 A

13 B

14 C

15 C

Câu hỏi Đáp án

16 A

17 A

18 B

19 C

20 D

21 B

22 C

23 C

24 D

25 A

26 A

27 D

28 B

29 C

30 D

Câu hỏi Đáp án

31 A

32 A

33 B

34 A

35 D

36 A

37 B

38 C

39 A

40 D

41 D

42 B

43 A

44 A

45 B

Câu hỏi Đáp án

46 B

47 A

48 A

49 A

50 C

8. Phụ lục C. Hướng dẫn giải bài tập

Hướng dẫn giải bài tập các chương được chia sẻ trên đường link, vui lòng quét mã QR để download các bài tập.

Tài liệu tham khảo

Tiếng Việt:

1. Bùi Việt Hà (2020), Python cơ bản, Nxb Đại học Quốc gia Hà Nội. 2. Bùi Việt Hà (2022), Python lập trình thuật toán, Nxb Đại học Quốc gia Hà Nội. 3. Bùi Việt Hà (2023), Python nâng cao, Nxb Đại học Quốc gia Hà Nội. 4. Nguyễn Xuân Hậu, Nguyễn Duy Tân, Nguyễn Thị Hải Năng, Nguyễn Hoàng Điệp (2021), Python cơ bản, Nxb Đại học Quốc gia Hà Nội. 5. Trần Thông Quế (2020), Bài tập lập trình cơ bản với ngôn ngữ Python, Nxb Đại học Quốc gia Hà Nội. 6. Nguyễn Ngọc Giang, Phan Xuân Vọng, Nguyễn Quốc Anh (2021), Đường vào lập trình Python, Nxb Đại học Quốc gia Hà Nội.

Tiếng Anh: 1. Ivan Marin, Ankit Shukla, Sarang VK (2019), Big Data Analysis with Python, Packt, ISBN-13: 978-1789955286 2. AMZ Press (2022), Python Programming for Beginners: The Ultimate Guide for Begin- ners to Learn Python Programming. ISBN-13: 979-8367162387

3. Mark Reed (2022), Python Programming for Beginners: 2 Books in 1 - The Ultimate Step-by-Step Guide To Learn Python Programming Quickly with Practical Exercises (Computer Programming), ISBN-13: 979-8841846581.