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

30 mẹo Python hay để viết code tốt hơn kèm ví dụ

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 và phát triển kỹ năng Python của mình.
Đã cập nhật 29 thg 5, 2026  · 15 phút đọc

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 thêm bài viết về thực hành tốt trong Python để đảm bảo code của bạn đạt chuẩn tốt nhất. 

Nếu kỹ năng Python của bạn chưa vững, bạn cũng có thể cải thiện với Lộ trình Kỹ năng 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 là một tính năng trong Python dựa trên đánh chỉ mục để cho phép truy cập một phần con của một dãy. Chỉ mục đơn giản là vị trí của phần tử trong dãy. Nếu kiểu dãy là có thể thay đổi (mutable), bạn có thể dùng slicing để trích xuất và chỉnh sửa dữ liệu. 

Lưu ý: Chúng ta cũng có thể dùng slicing trên dãy bất biến (immutable), nhưng cố gắng chỉnh sửa phần cắt sẽ gây ra TypeError. 

Định dạng triển khai lát cắt là: sequence[start:stop:step]. Nếu không chỉ định giá trị cho các 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 được chỉ định. 

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

Chúng ta cũng có thể dùng chỉ mục âm, có thể dùng để đảo ngược dãy. Ví dụ, trong một list có 4 phần tử, chỉ mục 0 cũng là chỉ mục -4, và chỉ mục cuối cùng cũng là -1. Trong ví dụ code ở trên, kiến thức này được áp dụng vào tham số step của dãy. Do đó, chuỗi được in ngược lại, bắt đầu từ cuối dãy về chỉ mục 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 ban đầu của bạn là giá trị của b sẽ là 7 thay vì 12, bạn đã rơi vào bẫy của hoán đổi tại chỗ. 

Trong Python, chúng ta có thể giải nén (unpack) iterable vào các biến trong một lần gán bằng tự động giải nén. Chẳng hạn: 

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

"""
1
2
3
"""

Chúng 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. Dưới đây là ví dụ về packing.  

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

Kết hợp tự động packing và unpacking tạo nên kỹ thuật gọi là gán đồng thời. Chúng 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 so với 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. Nhưng điều tương tự không thể nói về tuple. Cả hai đều là iterable, cho phép đánh chỉ mục và lưu trữ kiểu dữ liệu hỗn hợp. 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à có thể thay đổi (mutable), nghĩa là chúng ta có thể chỉnh sửa tùy ý: 

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

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

Mặt khác, tuple là bất biến (immutable), nghĩa là cố gắng chỉnh sửa sẽ gây ra TypeError

Vì lý do này, tuple hiệu quả 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. Ngược lại, với list, phải cấp phát thêm bộ nhớ đề phòng chúng 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, thì 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 list từ một iterable khác – nhanh hơn nhiều so với dùng vòng lặp for. Nhưng chuyện gì xảy ra nếu bạn lỡ đổi ngoặc từ [] sang ()? Bạn sẽ nhận được một đối tượng generator.

Trong Python, ngoặc tròn với logic của list comprehension sẽ tạo ra thứ gọi là generator object. Generator là một loại iterable đặc biệt. Không giống list, chúng không lưu các phần tử. Thay vào đó, chúng lưu các chỉ 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 bằng kỹ thuật gọi là đánh giá lười. Lợi ích chính của mẹo dùng generator là tiết kiệm bộ nhớ vì toàn bộ dãy không được xây dựng 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. Do đó, 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 chúng 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. Đây là khái niệm aliasing. Thay đổi ở một alias sẽ ảnh hưởng đến alias còn lại. Đôi khi hành vi này là mong muốn, nhưng thường thì nó khiến ta trở tay không kịp. 

Một cách tránh là không alias 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 có rỗng hay không bằng toán tử not. Toán tử logic dựng sẵn của Python not trả về True nếu biểu thức không đúng, ngược lại trả về False – nó đảo giá trị chân trị của các biểu thức Boolean và đối tượng.  

Một cách dùng khác 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. 

Ban đầu có thể hơi khó hình dung, hãy thử áp dụng.

Mẹo về Chuỗi & Xuất kết quả

#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, chúng ta cần định dạng một đối tượng chuỗi; Python 3.6 giới thiệu tính năng hay gọi là f-string để đơn giản hóa quá trình này. Để đánh giá tốt hơn phương pháp mới, sẽ hữu ích nếu bạn hiểu cách định dạng chuỗi trước bản phát hành mới. 

Đây là cách chuỗi từng được định dạng: 

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ề cơ bản, cách định dạng mới nhanh hơn, dễ đọc hơn, ngắn gọn hơn, và khó mắc lỗi hơn.

Một công dụng khác của f-string là in tên định danh cùng với giá trị. Điều này được giới thiệu trong Python 3.8.

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

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

Xem 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 bất kỳ tham số tùy chọn nào. Do đó, 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 chúng ta có thể thay đổi là end. Tham số end chỉ định thứ sẽ được hiển thị ở cuối mỗi lần gọi câu lệnh print

Giá trị mặc định của end"\n" báo cho Python xuống dòng mới. Trong code trên, chúng tôi đã đổi thành khoảng trắng. Vì vậy, đầu ra trả về tất cả phần tử của list được in 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])
"""

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

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

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

Chúng tôi có khuyến nghị 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ó nhiều điều để nói thêm về mẹo này ngoài việc nó 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 cái gọi là toán tử ba ngôi – còn được 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 là:

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

print(name)
"""
John
"""

Mặc dù cả hai đoạn đều cho cùng kết quả, hãy chú ý cách toán tử ba ngôi cho phép ta viết code ngắn hơn và rõ ràng hơn. Đây là cách viết "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 thành list nếu muốn).

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

List có thứ tự, đánh chỉ mục từ 0, và mutable. Set là không có thứ tự và không có chỉ mục. Các phần tử trong set phải thuộc kiểu bất biến, dù bản thân set là mutable – cố gắng truy xuất phần tử bằng chỉ mục 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 thể chứa phần tử trùng lặp. Đây là điều giúp chúng ta loại bỏ phần tử trùng khỏi list.

#13 Dấu gạch dưới độc lập 

>>> 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, do đó có thể dùng để tham chiếu một đối tượng. Nhưng nó còn có trách nhiệm khác: lưu kết quả của lần tính toán cuối cùng.

Tài liệu nêu rằng "trình 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 các hàm dựng sẵn như print)."

Vì chúng ta chưa gán dấu gạch dưới cho một đối tượng trước khi gọi ở dòng đầu, nên nhận lỗi. Tuy nhiên, khi tính 1 + 2, trình thông dịch tương tác đã lưu kết quả trong định danh _ cho 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, chúng ta thấy trình thông dịch tương tác gán kết quả cuối cho đị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 diễn các đối tượng mà ta không quan tâm hoặc sẽ không dùng sau này trong chương trình. Điều này quan trọng vì dùng một định danh thay vì dấu gạch dưới (_) sẽ gây lỗi F841 khi lint chương trình. Lỗi F841 đơn giản cho biết một biến cục bộ đã được gán nhưng không được sử dụng trong chương trình, đây 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 vừa rồi về dấu gạch dưới của Python, một mục đích khác là tránh xung đột với từ khóa Python. 

PEP 8 đề cập rằng một dấu 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 "nói chung tốt hơn là thêm một dấu gạch dưới ở cuối thay vì dùng viết tắt hoặc làm sai chính tả. Do đó 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 những lập trình viên Python giàu kinh nghiệm thêm tiền tố gạch dưới trước tên định danh hoặc phương thức – và có lý do hợp lý.

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

Không như Java, Python không có phân định 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 đã thống nhất như vậy. Việc thêm chúng không ảnh hưởng đến hành vi chương trình của bạn.

#17 Gạch dưới để dễ nhìn

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

number = 1_500_000
print(number)

"""
15000000
"""

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

Ý tưởng là hỗ trợ khả năng đọc với các literal dài, hoặc các literal mà 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.")
"""

Khả năng cao 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 là "__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 chúng ta import mô-đun hiển thị trong ảnh chụp màn hì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 chúng ta sẽ có giá trị sai. Bởi vì khi import từ mô-đun khác, định danh __name__ được gán thành 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 một dictionary. Ví dụ, khi bạn theo dõi số lần xuất hiện của từ trong một corpus. Cách phổ biến để làm việc này như sau: 

  1. Kiểm tra xem khóa có tồn tại trong dictionary hay 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.

Đây là cách viết bằng code:

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

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

Tham số đầu tiên truyền vào phương thức là khóa muốn kiểm tra. Tham số thứ hai là giá trị sẽ gán cho khóa nếu khóa 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ị 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; Hầu hết 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 thứ đang tìm, làm sao tìm được? Câu trả lời là tìm theo mẫu.  

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

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

Học cách regex hoạt động là điều thiết yếu ngay 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 cho tính năng tìm và thay thế.

#21 Dấu ống (pipe) 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ó một ký tự đặc biệt gọi là pipe (|) cho phép bạn khớp một trong nhiều biểu thức, và có thể dùng ở bất kỳ đâu. Điều này rất hữu dụng khi bạn có nhiều mẫu tương tự.

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

Lưu ý điểm dễ nhầm: nếu tất cả biểu thức bạn muốn khớp đều xuất hiện trong cùng 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 hết khả năng của hàm print() là điều đáng ngại; Nếu “Hello World” là chương trình đầu tiên của bạn, thì print() có lẽ là một trong những hàm dựng sẵn đầu tiên bạn học khi bắt đầu với Python. Chúng 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 điều hơn thế ở print()

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

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

#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 các nội dung trung cấp – nâng cao mà 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 có vẻ phức tạp, nhưng thực ra khá đơn giản.

Trong ví dụ, chúng ta chỉ dùng một đối số, nhưng có thể dùng nhiều 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ỏ, bị giới hạn, ẩn danh chỉ trong một dòng. Chúng hoạt động như hàm thông thường được khai báo với def, chỉ khác là các hàm này 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() được áp dụng lên đối tượng chuỗi để cho phép chuyển chữ hoa thành chữ thường và ngược lại chỉ trong một dòng code. Không có nhiều trường hợp dùng cho swapcase(), nhưng biết cũng tốt.

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

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

"""
True
"""

Giả sử chúng ta tạo một chương trình yêu cầu người dùng nhập mật khẩu, và phải có sự kết hợp giữa chữ và số. Ta có thể làm điều này trong một dòng bằng cách gọi isalnum() trên đối tượng 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. Một 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ẽ dừng khi gặp lỗi.

Đôi khi, chúng ta không muốn hành vi này, chẳng hạn khi có người dùng cuối tương tác với code của ta. Sẽ tệ thế nào nếu code của ta kết thúc đột ngột trong trường hợp đó?

Có vài quan điểm về cách xử lý tình huống ngoại lệ. Hầu hết lập trình viên Python thường theo quan điểm rằng dễ xin tha thứ hơn là xin phép. Tức là họ muốn bắt lỗi được ném ra bằng cách cung cấp ngữ cảnh xung quanh có khả năng xử lý ngoại lệ. Ý tưởng là không đáng để lãng phí thời gian cố gắng phòng vệ trước mọi trường hợp ngoại lệ có thể có.

Nhưng điều này chỉ đúng khi có cơ chế đối phó với vấn đề sau khi 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ì lời giải 1 không giống hai lời giải 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}
"""

Chúng ta dùng *args**kwargs làm tham số cho hàm khi chúng ta không biết 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 cho hàm khi chúng không có tên khóa (tức là các tham số không yêu cầu tên đi kèm). Ngược lại, **kwargs cho phép truyền số lượng tham số có tên bất kỳ cho hàm.

Thực ra, các từ *args và **kwargs không hề thần kỳ: điều kỳ diệu nằm ở dấu hoa thị (*). Nghĩa là ta có thể dùng bất kỳ từ nào sau dấu hoa thị, nhưng dùng argskwargs là thông lệ và được cộng đồng Python áp dụng. 

#29 Dấu ba chấm (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 cách dù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à làm trình giữ chỗ (placeholder) trong một hàm chưa được triển khai. 

Nghĩa 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 tao 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 tinh vi như chúng ta đã làm ở code trên.

Có những cách khác để đạt mục tiêu tương tự; 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 lời giải này kém dễ đọc hơn so với list comprehension.

FAQs

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á xong vế phải trước khi gán.

Làm thế nào để 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 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í dư vào một tuple. **kwargs gom các đối số có tên dư vào một dictionary. Điều kỳ diệu nằm ở toán tử ***, không phải ở chính các từ — bạn có thể đặt tên khác.

Làm sao kiểm tra một list 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) sẽ xây toàn bộ list trong bộ nhớ ngay lập tức. Generator (ngoặc tròn) tạo giá trị từng cái khi được yêu cầu, 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, khi cả hai nhánh đều ngắn gọn và rõ ràng: name = "John" if condition else "Doe". Với logic phức tạp hơn, 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 trong một 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ủ đề

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