Chuyển đến nội dung chính

30 Mẹo Python Hay Giúp Viết Code Tốt Hơn (Kèm Ví Dụ)

Chúng tôi đã tuyển chọn 30 mẹo Python hay bạn có thể dùng để cải thiện code và phát triển kỹ năng Python của mình.
Đã cập nhật 22 thg 7, 2026  · 15 phút đọc

Khám phá với AI

Mở trong ChatGPTMở trong ClaudeMở trong Perplexity

Kỹ năng lập trình Python ngày càng được săn đón trong những năm gần đây. Để giúp bạn rèn luyện kỹ năng lập trình Python, chúng tôi đã tuyển chọn 30 mẹo Python hay mà bạn có thể dùng để cải thiện code. Hãy thử học mỗi ngày một mẹo trong 30 ngày tới, và xem bài viết về các thực hành tốt nhất trong Python để đảm bảo code của bạn đạt chuẩn hàng đầu. 

Nếu kỹ năng Python của bạn chưa vững, bạn cũng có thể mài giũa với lộ trình kỹ năng Lập trình Python của chúng tôi.

Mẹo về Dãy & Cấu trúc Dữ liệu

#1 Cắt lát (Slicing)

a = "Hello World!"
print(a[::-1])

"""
!dlroW olleH
"""

Slicing (cắt lát) là một tính năng trong Python dựa trên chỉ số (indexing) cho phép bạn truy cập một tập con của một dãy (sequence). Chỉ số đơn giản là vị trí của phần tử trong dãy. Nếu kiểu dãy là mutable (có thể thay đổi), bạn có thể dùng slicing để trích xuất và chỉnh sửa dữ liệu. 

Lưu ý: Ta cũng có thể dùng slicing trên dãy immutable (bất biến), nhưng cố gắng sửa phần được cắt sẽ phát sinh TypeError. 

Dạng cú pháp của slice là: sequence[start:stop:step]. Nếu không chỉ định giá trị cho tham số start, stopstep, dãy sẽ dùng giá trị mặc định. Các mặc định là: 

  • "start" mặc định là 0 
  • "stop" mặc định là độ dài của dãy
  • "step" mặc định là 1 nếu không chỉ định. 

Khi dùng sequence[start:stop], các phần tử trả về sẽ từ chỉ số bắt đầu đến stop - 1 (chỉ số dừng không được bao gồm). 

Ta cũng có thể truyền chỉ số âm để đảo ngược dãy. Ví dụ, trong một danh sách 4 phần tử, chỉ số 0 cũng là chỉ số -4, và chỉ số cuối cùng cũng là -1. Trong ví dụ trên, hiểu biết này được áp dụng cho tham số step của dãy. Kết quả là chuỗi được in ngược lại, bắt đầu từ cuối dãy về đến chỉ số 0.   

#2 Hoán đổi tại chỗ / gán đồng thời

a = 10
b = 5
print(f"First: {a, b}")

"""
First: (10, 5)
"""

a, b = b, a + 2
print(f"Second: {a, b}")

"""
Second: (5, 12)
"""

Nếu ấn tượng đầu tiên của bạn là giá trị của b sẽ là 7 thay vì 12, bạn đã rơi vào bẫy hoán đổi tại chỗ. 

Trong Python, chúng ta có thể giải nén (unpack) các iterable vào biến trong một phép gán duy nhất bằng cơ chế giải nén tự động. Ví dụ: 

a, b, c = [1, 2, 3]
print(a)
print(b)
print(c)

"""
1
2
3
"""

Ta cũng có thể gom nhiều giá trị vào một biến bằng * – mẹo Python này gọi là packing (đóng gói). Dưới đây là ví dụ về packing.  

a, *b = 1, 2, 3
print(a, b)
"""
1 [2, 3]
"""

Kết hợp packing và unpacking tự động tạo ra kỹ thuật gọi là gán đồng thời. Ta có thể dùng gán đồng thời để gán một loạt giá trị cho một loạt biến.

#3 List và tuple 

import sys

a = [1, 2, 3, 4, 5]
b = (1, 2, 3, 4, 5)

print(f"List size: {sys.getsizeof(a)} bytes")
print(f"Tuple size: {sys.getsizeof(b)} bytes")

"""
List size: 52 bytes
Tuple size: 40 bytes
"""

Hầu hết lập trình viên Python đều quen thuộc với cấu trúc dữ liệu list. Điều tương tự không hẳn đúng với tuple. Cả hai đều là iterable, cho phép đánh chỉ số, và lưu được dữ liệu hỗn hợp kiểu. Nhưng có những tình huống nên ưu tiên dùng tuple thay vì list. 

Trước hết, list là mutable, nghĩa là ta có thể sửa đổi tùy ý: 

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

"""
[1,2,8,4,5]
"""

Ngược lại, tuple là immutable, nghĩa là cố gắng sửa chúng sẽ phát sinh TypeError

Vì lý do này, tuple tiết kiệm bộ nhớ hơn vì Python có thể cấp phát đúng khối bộ nhớ cần thiết cho dữ liệu. Trái lại, với list, phải cấp phát thêm bộ nhớ phòng khi ta mở rộng nó – điều này gọi là cấp phát bộ nhớ động. 

Tóm lại: Trong các tình huống bạn không muốn dữ liệu bị thay đổi, nên ưu tiên dùng tuple thay vì list vì lý do bộ nhớ. Tuple cũng nhanh hơn list. 

Tìm hiểu thêm về Cấu trúc dữ liệu trong Python trong hướng dẫn này. 

#4 Generator

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

print(a)
print(b)

"""
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
<generator object <genexpr> at 0x7f61f8808b50>
"""

List comprehension là cách “pythonic” để tạo một list từ một iterable khác – nhanh hơn nhiều so với dùng vòng lặp for. Nhưng nếu bạn vô tình đổi ngoặc vuông [] thành ngoặc tròn () thì sao? Bạn sẽ nhận được một generator object.

Trong Python, ngoặc tròn với logic list comprehension sẽ tạo ra thứ gọi là generator object. Generator là một loại iterable đặc biệt. Không như list, chúng không lưu các phần tử. Thay vào đó, chúng lưu hướng dẫn để tạo từng phần tử theo thứ tự và trạng thái hiện tại của vòng lặp.

Mỗi phần tử chỉ được tạo khi có yêu cầu, dùng kỹ thuật gọi là đánh giá lười biếng. Lợi ích chính của mẹo này với generator là dùng ít bộ nhớ hơn vì không xây toàn bộ dãy cùng lúc. 

#5 Aliasing 

a = [1, 2, 3, 4 ,5]
b = a

# Change the 4th index in b
b[4] = 7

print(id(a))
print(id(b))
print(a) # Remember we did not explicitly make changes to a.

"""
15136008
15136008
[1, 2, 3, 4, 7]
"""

Python là ngôn ngữ lập trình hướng đối tượng – mọi thứ đều là đối tượng. Vì vậy, gán một đối tượng cho một định danh là tạo một tham chiếu đến đối tượng đó. 

Khi ta gán một định danh cho một định danh khác, ta có hai định danh cùng tham chiếu đến một đối tượng. Khái niệm này gọi là aliasing (bí danh). Thay đổi ở một alias sẽ ảnh hưởng đến alias kia. Đôi khi hành vi này là mong muốn, nhưng thường thì khiến ta bất ngờ. 

Một cách tránh là hạn chế aliasing khi dùng đối tượng mutable. Giải pháp khác là tạo một bản sao (clone) của đối tượng gốc thay vì tham chiếu. 

Cách đơn giản nhất để tạo bản sao là tận dụng slicing: 

b = a[:] 

Điều này sẽ tạo một tham chiếu mới đến một đối tượng list trong định danh b. 

Bạn có thể dùng nhiều cách khác, như gọi list(a) khi gán dữ liệu cho định danh khác hoặc dùng phương thức copy()

#6 Toán tử ‘not’

a = []
print(not a)

"""
True
"""

Mẹo Python tiếp theo là cách dễ nhất để kiểm tra cấu trúc dữ liệu rỗng bằng toán tử not. Toán tử logic tích hợp not của Python trả về True nếu biểu thức không đúng, ngược lại trả về False – nó đảo ngược giá trị chân lý của biểu thức Boolean và đối tượng.  

Một cách dùng khác bạn có thể thấy là trong câu lệnh if: 

if not a:
    # do something... 

Khi aTrue thì toán tử not sẽ trả về False, và ngược lại. 

Khá dễ gây rối não, nên hãy thử thực hành.

Mẹo về Chuỗi & Xuất

#7 F-string

first_name = "John"
age = 19

print(f"Hi, I'm {first_name} and I'm {age} years old!")

"""
Hi, I'm John and I'm 19 years old!
"""

Đôi khi ta cần định dạng một chuỗi; Python 3.6 giới thiệu một tính năng hay gọi là f-string để đơn giản hóa quá trình này. Để thấy rõ ưu điểm, cũng hữu ích khi hiểu cách định dạng chuỗi trước bản phát hành mới. 

Trước đây chuỗi được định dạng như sau: 

first_name = "John"
age  = 19

print("Hi, I'm {} and I'm {} years old!".format(first_name, age))

"""
Hi, I'm John and I'm 19 years old!
"""

Về bản chất, cách mới nhanh hơn, dễ đọc hơn, gọn hơn và khó sai hơn.

Một cách dùng khác của f-string là in tên định danh cùng với giá trị. Tính năng này được giới thiệu ở Python 3.8.

x = 10
y = 20
print(f"{x = }, {y = }")

"""
x = 10, y = 20
"""

Xem thêm hướng dẫn về Định dạng F-string trong Python để tìm hiểu thêm. 

#8 Tham số ‘end’ của hàm print()

languages = ["english", "french", "spanish", "german", "twi"]
print(' '.join(languages))

"""
english french spanish german twi
"""

Rất thường gặp việc dùng câu lệnh print mà không định nghĩa các tham số tùy chọn. Vì vậy, nhiều Pythonista không biết rằng bạn có thể kiểm soát phần nào đầu ra.

Một tham số tùy chọn ta có thể thay đổi là end. Tham số end chỉ định điều gì sẽ xuất hiện ở cuối mỗi lần gọi print

Giá trị mặc định của end"\n", báo Python xuống dòng mới. Trong đoạn code trên, ta thay bằng khoảng trắng. Do đó, đầu ra in tất cả phần tử của danh sách trên cùng một dòng.

#9 Thêm phần tử vào tuple

a = (1, 2, [1, 2, 3])
a[2].append(4)
print(a)

"""
(1, 2, [1, 2, 3, 4])
"""

Ta đã biết tuple là bất biến – xem mẹo #3 List vs. Tuple. Cố gắng thay đổi trạng thái của tuple sẽ ném TypeError. Nhưng nếu bạn coi đối tượng tuple như một dãy các tên được ràng buộc đến các đối tượng không thể thay đổi ràng buộc đó, bạn có thể sẽ nhìn khác đi.

Hai phần tử đầu của tuple là số nguyên – chúng bất biến. Phần tử cuối là một list, một đối tượng mutable trong Python.

Nếu ta coi list này chỉ là một tên khác trong dãy được ràng buộc tới một đối tượng không thể thay đổi ràng buộc, thì ta sẽ nhận ra list vẫn có thể được sửa từ bên trong tuple.

Chúng tôi có khuyên bạn làm vậy trong thực tế không? Có lẽ là không, nhưng đây là một điều hay để biết!

#10 Gộp dictionary

a = {"a": 1, "b": 2}
b = {"c": 3, "d": 4}

a_and_b = a | b
print(a_and_b)

"""
{"a": 1, "b": 2, "c": 3, "d": 4}
"""

Trong Python 3.9 trở lên, có thể gộp các dictionary bằng | (OR theo bit). Không có gì nhiều để nói ngoài việc đây là giải pháp dễ đọc hơn rất nhiều! 

Mẹo về Phong cách Code & Cú pháp

#11 Toán tử ba ngôi / biểu thức điều kiện 

condition = True
name = "John" if condition else "Doe"

print(name)

"""
John
"""

Trong đoạn code trên, bạn thấy thứ được biết đến là toán tử ba ngôi – còn gọi là biểu thức điều kiện. Ta dùng toán tử ba ngôi để đánh giá dựa trên việc điều kiện là True hay False.

Một cách khác để viết đoạn code trên như sau:

condition = True
if condition:
    name = "John"
else:
    name = "Doe"

print(name)
"""
John
"""

Dù cả hai cho cùng đầu ra, hãy để ý toán tử điều kiện ba ngôi cho phép viết code ngắn gọn và rõ ràng hơn. Đây là cách được Pythonista gọi là “Pythonic” hơn. 

#12 Loại bỏ trùng lặp khỏi list

a = [1, 1, 2, 3, 4, 5, 5, 5, 6, 7, 2, 2]
print(list(set(a)))

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

Cách đơn giản nhất để loại bỏ phần tử trùng lặp khỏi list là chuyển list thành set (rồi chuyển lại list nếu muốn).

Xét về tính có thể thay đổi, set và list khá giống nhau trong Python. Ta có thể thêm và xóa phần tử ở cả hai, nhưng chúng vẫn rất khác biệt.

List có thứ tự, đánh chỉ số từ 0 và mutable. Set không có thứ tự và không đánh chỉ số. Các phần tử trong set phải là kiểu bất biến, dù bản thân set là mutable – cố lấy phần tử theo chỉ số hoặc sửa phần tử sẽ gây lỗi.

Một khác biệt quan trọng nữa là set không chứa phần tử trùng lặp. Chính điều này giúp ta loại bỏ trùng lặp khỏi list.

#13 Dấu gạch dưới đứng một mình 

>>> print(_)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

>>> 1 + 2
3

>>> print(_)
3

Dấu gạch dưới (_) là một định danh hợp lệ trong Python, vì vậy có thể dùng để tham chiếu đối tượng. Nhưng nó còn có nhiệm vụ khác: lưu kết quả của phép đánh giá cuối cùng.

Tài liệu nêu rằng "bộ thông dịch tương tác cung cấp kết quả của lần đánh giá cuối cùng trong biến _. (Nó được lưu trong mô-đun builtins, cùng với các hàm dựng sẵn như print)."

Vì ta chưa gán đối tượng cho dấu gạch dưới trước khi gọi ở dòng đầu, nên nhận lỗi. Tuy nhiên, khi tính 1 + 2, bộ thông dịch tương tác đã lưu kết quả vào định danh _ giúp chúng ta. 

#14 Dùng gạch dưới để bỏ qua giá trị

for _ in range(100):
    print("The index doesn't matter")

"""
The index doesn't matter
The index doesn't matter
...
"""

Ở mẹo #13, ta thấy bộ thông dịch tương tác cung cấp kết quả cuối cùng trong định danh (_), nhưng đó không phải trường hợp dùng duy nhất.

Ta cũng có thể dùng nó để biểu thị các đối tượng mà ta không quan tâm hoặc sẽ không dùng ở bước sau trong chương trình. Điều này quan trọng vì dùng một định danh thay cho dấu gạch dưới (_) sẽ gây lỗi F841 khi linting chương trình. Lỗi F841 đơn giản là nói rằng một biến cục bộ đã được gán nhưng không được sử dụng, vốn là thực hành không tốt.

#15 Gạch dưới ở cuối

list_ = [0, 1, 2, 3, 4]
global_ = "Hi there" 

Tiếp nối hai mẹo trước về dấu gạch dưới (_), một mục đích khác của nó là tránh xung đột với từ khóa Python. 

PEP 8 đề cập rằng gạch dưới ở cuối nên được "dùng theo quy ước để tránh xung đột với từ khóa Python." Đồng thời nêu rằng "nói chung tốt hơn là thêm một gạch dưới ở cuối hơn là dùng viết tắt hoặc làm sai chính tả. Vì vậy list_ tốt hơn lst."

#16 Gạch dưới ở đầu

class Example:
    def __init__(self):
        self._internal = 2
        self.external = 20

Bạn sẽ thường thấy lập trình viên Python giàu kinh nghiệm hay thêm gạch dưới trước tên định danh hoặc phương thức – và có lý do.

Gạch dưới đứng trước một định danh hoặc phương thức có ý nghĩa ngầm: biến hoặc phương thức này chỉ dành cho dùng nội bộ. Về bản chất, đây là lời cảnh báo với lập trình viên khác được quy định trong PEP 8 nhưng không được Python cưỡng chế. Do đó, gạch dưới ở đầu chỉ là chỉ dấu yếu.

Khác với Java, Python không có phân biệt mạnh giữa biến private và public. Nói cách khác, nó chỉ có ý nghĩa vì cộng đồng Python đã đồng thuận như vậy. Việc thêm gạch dưới không ảnh hưởng hành vi chương trình của bạn.

#17 Gạch dưới cho mục đích hiển thị

Đây là mẹo cuối cùng về dấu gạch dưới; đến giờ ta đã đề cập ba trường hợp dùng, nhưng bạn có thể xem hướng dẫn về Vai trò của Dấu gạch dưới (_) trong Python để biết thêm. 

number = 1_500_000
print(number)

"""
15000000
"""

Một cách khác để dùng dấu gạch dưới là như dấu phân tách trực quan cho nhóm chữ số trong số nguyên, số thực và số phức – được giới thiệu ở Python 3.6. 

Ý tưởng là giúp dễ đọc các literal dài, hoặc literal có giá trị nên được tách rõ thành các phần – bạn có thể đọc thêm trong PEP 515.

Mẹo về Phong cách Code & Cú pháp

#18 __name__ == “__main__” 

if __name__ == "__main__":
    print("Read on to understand what is going on when you do this.")

"""
print("Read on to understand what is going on when you do this.")
"""

Rất có khả năng bạn đã thấy cú pháp này trong nhiều chương trình Python; Python dùng một tên đặc biệt "__main__" và gán nó cho định danh __name__ nếu tệp Python đang chạy là chương trình chính.

Nếu ta nhập (import) mô-đun hiển thị trong ảnh vào một mô-đun khác (tệp Python) và chạy tệp đó, biểu thức trong code của ta sẽ có giá trị sai. Bởi vì khi import từ mô-đun khác, định danh __name__ được gán bằng tên của mô-đun (tệp Python). 

#19 Phương thức ‘setdefault’ 

import pprint

text = "It's the first of April. It's still cold in the UK. But I'm going to the museum so it should be a wonderful day"

counts = {}
for word in text.split():
    counts.setdefault(word, 0)
    counts[word] += 1

pprint.pprint(counts)

"""
{'April.': 1,
'But': 1,
"I'm": 1,
"It's": 2,
'UK.': 1,
'a': 1,
'be': 1,
'cold': 1,
'day': 1,
'first': 1,
'going': 1,
'in': 1,
'it': 1,
'museum': 1,
'of': 1,
'should': 1,
'so': 1,
'still': 1,
'the': 3,
'to': 1,
'wonderful': 1}
"""

Bạn có thể muốn đặt giá trị cho nhiều khóa trong dictionary. Ví dụ, khi theo dõi số lần xuất hiện của từ trong một corpus. Cách thông thường là: 

  1. Kiểm tra khóa có tồn tại trong dictionary không
  2. Nếu có, tăng giá trị lên 1.
  3. Nếu không, thêm khóa và đặt giá trị là 1.

Code sẽ trông như sau:

counts = {}
for word in text.split():
    if word in counts:
        counts[word] += 1
    else:
      counts[word] = 1

Một cách gọn hơn là dùng phương thức setdefault() trên đối tượng dictionary của bạn.

Đối số thứ nhất là khóa cần kiểm tra. Đối số thứ hai là giá trị sẽ đặt cho khóa nếu nó chưa tồn tại trong dictionary – nếu khóa đã tồn tại, phương thức sẽ trả về giá trị hiện tại của khóa. Do đó, nó sẽ không bị thay đổi.

Mẹo về Cấu trúc Chương trình

#20 Khớp regex

import re

number = re.compile(r"(0)?(\+44)?\d{10}")
num_1 = number.search("My number is +447999999999")
num_2 = number.search("My number is 07999999999")

print(num_1.group())
print(num_2.group())

"""
'+447999999999'
'07999999999'
"""

Biểu thức chính quy cho phép bạn chỉ định một mẫu văn bản để tìm kiếm; đa số mọi người biết ta có thể tìm bằng CTRL + F (Windows), nhưng nếu bạn không biết chính xác mình tìm gì, làm sao tìm được? Câu trả lời là tìm theo mẫu.  

Ví dụ, số điện thoại UK theo mẫu tương tự: sẽ có số 0 ở đầu cộng với mười chữ số, hoặc +44 thay cho số 0 và mười chữ số – trường hợp thứ hai là dạng quốc tế. 

Regex tiết kiệm thời gian đáng kể. Nếu phải viết code quy tắc để bắt các trường hợp trong ảnh thay vì regex, có thể mất hơn 10 dòng code. 

Học cách regex hoạt động là rất quan trọng kể cả khi bạn không viết code. Hầu hết trình soạn thảo văn bản và trình xử lý văn bản hiện đại cho phép dùng regex trong tính năng tìm kiếm và thay thế.

#21 Dấu ống trong regex

import re

heros = re.compile(r"Super(man|woman|human)")

h1 = heros.search("This will find Superman")
h2 =  heros.search("This will find Superwoman")
h3 = heros.search("This will find Superhuman")

print(h1.group())
print(h2.group())
print(h3.group())

"""
Superman
Superwoman
Superhuman
"""

Regex có ký tự đặc biệt gọi là dấu ống (|) cho phép bạn khớp một trong nhiều biểu thức, và có thể dùng ở bất cứ đâu. Rất hữu ích khi bạn có nhiều mẫu tương tự nhau.

Ví dụ, 'Superman', 'Superwoman' và 'Superhuman' đều có tiền tố giống nhau. Do đó, bạn có thể tận dụng dấu ống để giữ phần mẫu lặp lại và thay đổi phần cần khác. Một lần nữa, tiết kiệm thời gian quý báu.

Lưu ý điểm dễ nhầm: nếu tất cả biểu thức bạn muốn khớp cùng xuất hiện trong một văn bản, lần xuất hiện đầu tiên sẽ được trả về – ví dụ, "An example text containing Superwoman, Superman, Superhuman" sẽ trả về Superwoman.

#22 Tham số ‘sep’ của hàm print()

day = "04"
month = "10"
year = "2022"

print(day, month, year)
print(day, month, year, sep = "")
print(day, month, year, sep = ".")

"""
04 10 2022
04/10/2022
04.10.2022
"""

Số lượng lập trình viên Python không biết đầy đủ khả năng của hàm print() là đáng ngại; nếu “Hello World” là chương trình đầu tiên của bạn, print() có lẽ là một trong những hàm dựng sẵn đầu tiên bạn học. Ta dùng print() để hiển thị thông điệp định dạng lên màn hình, nhưng còn nhiều hơn thế nữa. 

Trong đoạn code trên, chúng tôi minh họa các cách hiển thị thông điệp định dạng khác nhau. Tham số sep là đối số tùy chọn cho phép chỉ định cách phân tách các đối tượng nếu in nhiều hơn một. 

Mặc định là phân tách bằng khoảng trắng, nhưng chúng tôi đã thay đổi trong các câu lệnh print – một chỗ đặt sep thành "" và một chỗ đặt thành ".".

#23 Hàm lambda 

def square(num:int) -> int:
    return num ** 2

print(f"Function call: {square(4)}")
"""
Function call: 16
"""

square_lambda = lambda x: x**2
print(f"Lambda function: {square_lambda(4)}")
"""
Lambda functional: 16
"""

Hàm lambda đưa bạn đến những điều ở mức trung cấp–nâng cao bạn có thể làm với Python – học Python Trung cấp với khóa học này. Nhìn qua thì có vẻ phức tạp, nhưng thực ra khá đơn giản.

Trong ví dụ, chúng tôi chỉ dùng một đối số, nhưng bạn có thể dùng nhiều hơn nếu muốn:

square = lambda a, b: a ** b
print(f"Lambda function: {square(4, 2)}")
"""
16
"""

Về bản chất, từ khóa lambda cho phép tạo các hàm nhỏ, hạn chế, ẩn danh trong một dòng. Chúng hoạt động như hàm thông thường được khai báo bằng def, chỉ khác là không có tên.

#24 Phương thức ‘swapcase’

string = "SoMe RaNDoM sTriNg"
print(string.swapcase())

"""
sOmE rAndOm StRInG
"""

Phương thức swapcase() áp dụng cho đối tượng chuỗi để đổi chữ hoa thành chữ thường và ngược lại trong một dòng. Không có quá nhiều trường hợp dùng swapcase(), nhưng biết cũng hữu ích.

#25 Phương thức ‘isalnum’

password = "ABCabc123"
print(password.isalnum())

"""
True
"""

Giả sử chúng ta tạo chương trình yêu cầu người dùng nhập mật khẩu, nhưng phải gồm cả số và chữ. Ta có thể làm điều này trong một dòng bằng cách gọi isalnum() trên chuỗi.

Phương thức kiểm tra xem tất cả ký tự có thuộc bảng chữ cái (A-Za-z) và số (0-9) hay không. Khoảng trắng hoặc ký hiệu (!#%$&? v.v.) sẽ trả về False.

#26 Xử lý ngoại lệ

def get_ration(x:int, y:int) -> int:
    try:
        ratio = x/y
    except ZeroDivisionError:
        y = y + 1
        ratio = x/y
    return ratio

print(get_ration(x=400, y=0))

"""
400.0
"""

Chương trình Python sẽ kết thúc khi gặp lỗi.

Đôi khi ta không muốn hành vi này, như khi người dùng cuối tương tác với code. Sẽ tệ thế nào nếu code của ta dừng đột ngột trong tình huống như vậy?

Có vài trường phái về cách xử lý tình huống ngoại lệ. Nhiều lập trình viên Python thường theo quan điểm “dễ xin tha thứ hơn xin phép”. Nghĩa là họ thích bắt lỗi phát sinh bằng cách cung cấp ngữ cảnh xung quanh có thể xử lý ngoại lệ. Ý tưởng là không cần tốn thời gian bảo vệ trước mọi trường hợp ngoại lệ có thể xảy ra.

Nhưng điều này chỉ đúng khi có cơ chế đối phó sau khi vấn đề xảy ra.

#27 Xác định khác biệt giữa các list

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

solution_1 = list(set(list_2) - set(list_1))
solution_2 = list(set(list_1) ^ set(list_2))
solution_3 = list(set(list_1).symmetric_difference(set(list_2)))

print(f"Solution 1: {solution_1}")
print(f"Solution 2: {solution_2}")
print(f"Solution 3: {solution_3}")

"""
Solution 1: [9, 2, 4, 6]
Solution 2: [2, 4, 6, 9]
Solution 3: [2, 4, 6, 9]
"""

Dưới đây là ba cách khác nhau để so sánh sự khác biệt giữa hai list trong Python. 

Lưu ý: Trừ khi bạn biết chắc list_1 là tập con của list_2, thì giải pháp 1 không giống hai giải pháp còn lại.

#28 Args & kwargs

def some_function(*args, **kwargs):
    print(f"Args: {args}")
    print(f"Kwargs: {kwargs}")

some_function(1, 2, 3,  a=4, b=5, c=6)

"""
Args: (1, 2, 3)
Kwargs: {'a': 4, 'b': 5, 'c': 6}
"""

Ta dùng *args**kwargs làm tham số cho hàm khi không biết trước số lượng biến mà hàm sẽ nhận. 

Tham số *args cho phép truyền số lượng tham số biến đổi vào hàm khi là không có tên (tức là các tham số không yêu cầu tên đi kèm). Trong khi đó, **kwargs cho phép truyền số lượng tùy ý các tham số có tên vào hàm.

Thực ra, từ args và kwargs không có gì kỳ diệu: điều kỳ diệu nằm ở dấu hoa thị (*). Tức là ta có thể dùng bất kỳ từ nào sau dấu hoa thị, nhưng việc dùng argskwargs là thông lệ, và được tuân thủ trong cộng đồng Python. 

#29 Ellipsis

print(...)

"""
Ellipsis
"""

def some_function():
    ...

# Alternative solution
def another_function():
    pass

Ellipsis là một đối tượng Python có thể được gọi bằng ba dấu chấm (...) hoặc gọi trực tiếp đối tượng (Ellipsis).

Cách dùng nổi bật nhất của nó là để truy cập và cắt lát mảng đa chiều trong NumPy, ví dụ:

import numpy as np

arr = np.array([[2,3], [1,2], [9,8]])

print(arr[...,0])
"""
[2 1 9]
"""
print(arr[...])

"""
[[2 3]
[1 2]
[9 8]]
"""

Nhưng một cách dùng khác của Ellipsis là như trình giữ chỗ (placeholder) trong hàm chưa triển khai. 

Tức là bạn có thể dùng Ellipsis, ..., hoặc pass, và tất cả đều hợp lệ.

#30 List comprehension

even_numbers = [x for x in range(10) if x % 2 == 0 and x != 0]
print(even_numbers)

"""
[2, 4, 6, 8]
"""

Mẹo cuối cùng là list comprehension, một cách thanh nhã để tạo list từ một dãy khác. Chúng cho phép bạn thực hiện logic và lọc phức tạp như trong đoạn code trên.

Có những cách khác để đạt cùng mục tiêu; ví dụ, ta có thể dùng hàm lambda như sau:

even_numbers = list(filter(lambda x: x % 2 ==0 and x != 0, range(10)))
print(even_numbers)
"""
[0, 2, 4, 6, 8]
"""

Nhưng nhiều Pythonista sẽ cho rằng giải pháp này kém dễ đọc hơn list comprehension.

Câu hỏi thường gặp

Mẹo Python nào hữu ích nhất cho người mới bắt đầu?

F-string có lẽ là hữu ích nhất ngay lập tức. Chúng giúp định dạng chuỗi nhanh hơn, dễ đọc hơn và khó mắc lỗi hơn so với cách cũ như .format().

Cách nhanh nhất để hoán đổi hai biến trong Python là gì?

Dùng gán đồng thời: a, b = b, a. Không cần biến tạm — Python đánh giá hoàn toàn vế phải trước khi gán.

Làm sao gộp hai dictionary trong một dòng?

Trong Python 3.9+, dùng toán tử |: merged = dict_a | dict_b. Với các phiên bản cũ hơn, dùng {**dict_a, **dict_b}.

Sự khác nhau giữa *args và **kwargs là gì?

*args gom các đối số vị trí thừa vào một tuple. **kwargs gom các đối số có tên thừa vào một dictionary. Điều “ma thuật” nằm ở toán tử ***, không phải ở bản thân các từ — bạn có thể đặt tên khác.

Làm sao kiểm tra một list có rỗng trong Python?

Dùng toán tử not: if not my_list:. Cách này “Pythonic” hơn so với kiểm tra len(my_list) == 0.

Khác biệt giữa list comprehension và generator là gì?

Một list comprehension (ngoặc vuông) xây cả list trong bộ nhớ cùng lúc. Một generator (ngoặc tròn) tạo giá trị từng cái khi cần, dùng ít bộ nhớ hơn nhiều cho các dãy lớn.

Khi nào nên dùng toán tử ba ngôi?

Dùng cho các điều kiện một dòng đơn giản, nơi cả hai nhánh đều ngắn và rõ ràng: name = "John" if condition else "Doe". Với những gì phức tạp hơn, một khối if/else thông thường sẽ dễ đọc hơn.

Cách dễ nhất để loại bỏ phần tử trùng lặp khỏi list là gì?

Bọc trong set() rồi chuyển lại: list(set(my_list)). Lưu ý set không có thứ tự, nên thứ tự gốc sẽ không được giữ.

Chủ đề

Các khóa học Python hàng đầu

Courses

Python nâng cao

4 giờ
1.4M
Nâng cao kỹ năng Khoa học dữ liệu của bạn bằng cách tạo trực quan hóa với Matplotlib và thao tác DataFrame bằng pandas.
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow
Có liên quan

blogs

Claude Opus 4.6: Tính năng, điểm chuẩn, các bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu bảng xếp hạng về mã hóa theo hướng tác nhân và suy luận phức tạp. Thêm nữa, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem ThêmXem Thêm