*args và **kwargs trong Python là gì?

Note - Tip - Trick Python

5.0 (3 đánh giá)
Tạo bởi Lê Châu Cập nhật lần cuối 16:41 07-03-2020 6.035 lượt xem 0 bình luận
Học nhanh

Danh sách bài học

*args và **kwargs trong Python là gì?

Dẫn nhập

Functions là cuộc sống, đúng không? nếu bạn là người mới vào học Python - là lính mới hay nhảy qua từ ngôn ngữ khác  - bạn học về số lượng tham số trong định nghĩa function khi đúng toàn bộ tham số thì mới tiếp tục.

Đó là nền tảng - thứ giúp chúng ta hiểu rõ từ bên ngoài. Tuy nhiên, nó cũng làm cho các bạn khá choáng váng khi bạn thấy *args hoặc **kwargs trong định nghĩa function.

Đừng để cú pháp làm sợ bạn. Nó không phải là những tham số đặc biệt thần thánh. Nó còn thậm chí không quá ảo, và chúng ta sẽ học cách sử dụng nó.


Tham số vị trí vs Tham số từ khóa

Có 2 khái niệm chúng ta cần phải tách ra nhằm để học *args**kwargs là gì.

Đầu tiên là khác nhau giữa tham số vị trí tham số từ khóa (Keyword). Ở những function cơ bản nhất, chúng ta chơi trò ghép cặp - đối số 1 sẽ đến tham số 1, đối số 2 đến tham số, và tiếp tục.

def printThese(a,b,c):
   print(a, "is stored in a")
   print(b, "is stored in b")
   print(c, "is stored in c")
printThese(1,2,3)
"""
1 is stored in a
2 is stored in b
3 is stored in c
"""

Lưu ý: Tất cả đối số phải có. Thiếu một sẽ gây ra lỗi.

def printThese(a,b,c):
   print(a, "is stored in a")
   print(b, "is stored in b")
   print(c, "is stored in c")
printThese(1,2)
"""
TypeError: printThese() missing 1 required positional argument: 'c'
"""

Nếu chúng ta cho giá trị mặc định cho tham số trong định nghĩa function, thì nó trở thành không bắt buộc

def printThese(a,b,c=None):
   print(a, "is stored in a")
   print(b, "is stored in b")
   print(c, "is stored in c")
printThese(1,2)
"""
1 is stored in a
2 is stored in b
None is stored in c
"""

Ngoài ra, tham số không bắt buộc sẽ trở thành keyword-eligible (từ khóa điều kiện), nghĩa là bạn có thể ghi rõ tên tham số khi gọi function để gán giá trị phù hợp.

Hãy gán 3 tham số có giá trị mặc định None và sẽ cách chúng ta gán giá trị không cần sắp xếp.

def printThese(a=None,b=None,c=None):
   print(a, "is stored in a")
   print(b, "is stored in b")
   print(c, "is stored in c")
printThese(c=3, a=1)
"""
def printThese(a=None,b=None,c=None):
   print(a, "is stored in a")
   print(b, "is stored in b")
   print(c, "is stored in c")
printThese(c=3, a=1)
"""
1 is stored in a
None is stored in b
3 is stored in c
"""

Toán tử Splat

Để tôi bắt đầu nói tôi yêu thích tên toán tử này - nó rất là … trực quan. * là  ký hiệu phổ biến nhất về phép nhân, nhưng ở Python nó còn có nghĩa toán tử Splat.

Tôi nghĩa toán tử này như cái hộp piñata - cái hộp nhét bánh kẹo vào trong rồi người ta dùng gậy đập tung nó ra. Tôi đã từng mô tả về toán tử mở rộng - một cái tương đương splat của JavaScript - nó giải nén một chuỗi domino rồi đẩy và một danh sách đơn lớn hơn, nhưng splat bảo đảm tương tự một cái mạnh mẽ hơn.

Một ví dụ cơ bản để bạn hiểu rõ hơn.

a = [1,2,3]
b = [*a,4,5,6]
print(b) # [1,2,3,4,5,6]

Trong ví dụ trên, chúng ta mang dữ liệu của a và giải nén đẩy vào toàn bộ list b.


Cách sử dụng *args và **kwargs

Vậy chúng ta đã biết toán tử splat giải nén toàn bộ dữ liệu có kí hiệu *, và có 2 loại tham số function. Vậy, nếu bạn chưa phát hiện ra, *args là viết tắt của (arguments) đối số, **kwargs là viết tắt của (keyword arguments) đối số từ khóa.

Nó được sử dụng để giải nén ra loại đối số tương ứng, cho phép gọi function có list đối số có số lượng giá trị thay đổi. Ví dụ, tạo một function in ra các điểm kiểm tra.

def printScores(student, *scores):
   print(f"Student Name: {student}")
   for score in scores:
      print(score)
printScores("Jonathan",100, 95, 88, 92, 99)
"""
Student Name: Jonathan
100
95
88
92
99
"""

Ủa khoan đã!!! Tôi không đặt tên *args? Đúng rồi, “args” chỉ là quy ước tiêu chuẩn nhưng vẫn chỉ là tên gọi.  Bí mật đã được bật mí, trong *args, dấu * thực sự là dân chơi, tạo 1 list mà toàn bộ giá trị là những đối số tương ứng khi gọi function.

Điều đó đã rõ ràng, **kwargs trở nên sẽ hiểu sâu. Cái tên không quan trọng, ** tạo ra một dictionary mà toàn bộ giá trị là là những đối số từ khóa khi gọi function.

Để minh họa, hãy tạo 1 function và in tên các con vật của người đó.

def printPetNames(owner, **pets):
   print(f"Owner Name: {owner}")
   for pet,name in pets.items():
      print(f"{pet}: {name}")
printPetNames("Jonathan", dog="Brock", fish=["Larry", "Curly", "Moe"], turtle="Shelldon")
"""
Owner Name: Jonathan
dog: Brock
fish: ['Larry', 'Curly', 'Moe']
turtle: Shelldon
"""

Lưu ý

Một vài lời khôn ngoan sẽ giúp bạn tránh lỗi thông thường và mở rộng kiến thức của bạn.

  • Sử dụng *args, **kwargs nhưng là quy ước tiêu chuẩn để bắt các đối số vị trí và từ khóa.
  • Bạn không thể đặt **kwargs trước *args, nếu không bạn sẽ nhận lỗi,
  • Cẩn thận việc trùng lặp tham số từ khóa và **kwargs khi giá trị được định nghĩa sẽ nằm ở **kwarg nhưng nó vô tình dính tên của tham số từ khóa.
  • Bạn có thể sử dụng toán tử splat khi gọi function.

Kết

Như vậy chúng ta đã tìm hiểu về *args và **kwargs trong Python là gì? 

Bài viết được dịch từ Medium.com. Bạn có thể tham khảo bài viết gốc tại đây: What Are *args and **kwargs in Python?

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần BÌNH LUẬN bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.

Nội dung bài viết

Tác giả/Dịch giả

Quan tâm lập trình và lịch sử.

Thích xem Anime, Marvel DC,..

Khóa học

Note - Tip - Trick Python

Note - Tip - Trick Python

Đánh giá

12312thaipro đã đánh giá 18:01 20-05-2020

Chat luong 1 sao

Trung Kien đã đánh giá 16:32 13-04-2020

Phạm Tấn Thành Moderator đã đánh giá 13:48 06-03-2020

Bình luận

Để bình luận, bạn cần đăng nhập bằng tài khoản Howkteam.

Đăng nhập
Không có video.