PHP
Python

Trang chủ

Tìm hiểu về hàm Trong Python

Ngôn ngữ Python là một ngôn ngữ lập trình đa mục đích, nổi tiếng với cú pháp dễ đọc, dễ học và tính ứng dụng cao. Trong lĩnh vực phát triển web, Python thường được sử dụng thông qua các framework như Django và Flask để xây dựng các ứng dụng web mạnh mẽ, bảo mật và dễ mở rộng. Trong chuyên mục này, Vietnix không chỉ cung cấp kiến thức nền tảng về ngôn ngữ Python mà còn hướng dẫn chi tiết cách xây dựng các ứng dụng web thực tế, sử dụng các framework phổ biến và áp dụng các kỹ thuật tiên tiến. Vietnix cam kết liên tục cập nhật những bài viết mới nhất về các tính năng mới của Python, các thư viện hỗ trợ hữu ích và những phương pháp tốt nhất, giúp bạn khai thác tối đa sức mạnh của Python và hoàn thiện kỹ năng lập trình web của mình.
html
CSS
javascript
sql
python
php
c
c++
bootstrap
react
mysql
reactjs
vuejs
Javascript Tutorials
08/01/2025
34 phút đọc
Theo dõi Vietnix trên

Tìm hiểu về hàm Trong Python

Hàm (function) là một khái niệm căn bản, đóng vai trò trung tâm trong lập trình Python. Hàm giúp chúng ta chia nhỏ chương trình thành các phần nhỏ hơn, dễ quản lý hơn. Bài viết này sẽ đưa bạn đi qua toàn bộ kiến thức về hàm trong Python, từ cú pháp đến cách sử dụng các loại đối số, các hàm đặc biệt, và các vấn đề liên quan khác.

Hàm trong Python là gì?

Hàm trong Python là một khối mã được tổ chức, có khả năng tái sử dụng, và được dùng để thực hiện một hành động đơn lẻ có liên quan. Hàm giúp chương trình của bạn trở nên dễ quản lý hơn, và có mức độ tái sử dụng mã cao.

Hàm trong Python là một khối mã có tổ chức và có khả năng tái sử dụng
Hàm trong Python là một khối mã có tổ chức và có khả năng tái sử dụng

Một cách tiếp cận từ trên xuống để xây dựng logic xử lý là định nghĩa các khối hàm độc lập có thể tái sử dụng. Một hàm Python có thể được gọi từ bất kỳ hàm nào khác bằng cách truyền dữ liệu cần thiết (được gọi là tham số hoặc đối số). Hàm được gọi sẽ trả kết quả trở lại môi trường gọi hàm.

Các loại hàm trong Python

Python cung cấp các loại hàm sau:

STTLoại & mô tả
1Hàm Tích Hợp Sẵn (Built-in functions)
Thư viện chuẩn của Python bao gồm một số hàm tích hợp sẵn. Một vài hàm tích hợp sẵn trong Python là print(), int(), len(), sum(),… Các hàm này luôn sẵn có vì chúng được nạp vào bộ nhớ của máy tính ngay khi bạn khởi động trình thông dịch Python.
2Hàm Định Nghĩa trong Các Module Tích Hợp Sẵn (Functions defined in built-in modules)
Thư viện chuẩn cũng cung cấp một số module (các thư viện con). Mỗi module chứa một nhóm các hàm được định nghĩa. Những hàm này không sẵn dùng ngay lập tức. Bạn cần import chúng vào bộ nhớ từ các module tương ứng trước khi có thể sử dụng.
3Hàm Do Người Dùng Định Nghĩa (User-defined functions)
Ngoài các hàm tích hợp sẵn và các hàm trong module tích hợp sẵn, bạn cũng có thể tự tạo các hàm riêng của mình. Các hàm này được gọi là hàm do người dùng định nghĩa.

Định nghĩa hàm trong Python

Bạn có thể tạo các hàm tùy chỉnh để cung cấp các chức năng cần thiết trong chương trình của mình. Dưới đây là các quy tắc đơn giản để định nghĩa một hàm trong Python:

  • Khối mã của một hàm bắt đầu bằng từ khóa def, theo sau là tên hàm và dấu ngoặc đơn ().
  • Các tham số đầu vào hoặc đối số cần thiết được đặt bên trong dấu ngoặc đơn này. Bạn cũng có thể định nghĩa các tham số này bên trong dấu ngoặc đơn.
  • Câu lệnh đầu tiên của hàm có thể là một câu lệnh tùy chọn; chuỗi tài liệu (docstring) của hàm.
  • Khối mã bên trong mỗi hàm bắt đầu bằng dấu hai chấm : và được thụt vào.
  • Câu lệnh return [biểu_thức] dùng để kết thúc hàm và có thể trả về một giá trị hoặc biểu thức cho nơi gọi hàm. Nếu return không có đối số, thì tương đương với return None.

Cú pháp định nghĩa hàm

def ten_ham(tham_so):
   "chuỗi_tài_liệu_của_hàm"
   khối_lệnh_của_hàm
   return [biểu_thức]

Lưu ý: Đoạn code trên không phải là một đoạn chương trình để chạy, mà là cú pháp tổng quát để khai báo hàm

Giải thích code:

  • def ten_ham(tham_so):: Khai báo một hàm với từ khóa def, theo sau là tên hàm ten_ham và danh sách các tham số tham_so đặt trong cặp dấu ngoặc đơn ().
  • "chuỗi_tài_liệu_của_hàm": Một chuỗi văn bản, đặt trong dấu nháy đôi hoặc nháy ba, để mô tả về chức năng và cách sử dụng của hàm. Chuỗi này là tùy chọn.
  • khối_lệnh_của_hàm: Là các câu lệnh Python nằm trong thân hàm. Chúng được thụt lề vào trong để xác định phạm vi của hàm.
  • return [biểu_thức]: Kết thúc hàm và trả về giá trị của biểu_thức (nếu có).

Theo mặc định, các tham số có hành vi theo vị trí (positional), tức là bạn cần phải truyền chúng theo đúng thứ tự đã định nghĩa. Khi hàm đã được định nghĩa xong, bạn có thể thực thi bằng cách gọi hàm đó từ một hàm khác, hoặc trực tiếp từ giao diện dòng lệnh Python.

Ví dụ về định nghĩa hàm trong Python

Ví dụ sau đây minh họa cách định nghĩa một hàm có tên là greetings(). Dấu ngoặc đơn () ở đây rỗng, có nghĩa là hàm này không có tham số đầu vào. Dòng đầu tiên của hàm là docstring, và khối mã của hàm kết thúc bằng câu lệnh return.

def greetings():
    "Đây là docstring của hàm greetings"
    print ("Xin chào Vietnix")
    return

Khi hàm này được gọi, thông điệp “Xin chào Vietnix” sẽ được in ra màn hình.

Giải thích code:

  • def greetings():: Khai báo một hàm có tên là greetings. Dấu ngoặc đơn rỗng () cho thấy hàm này không nhận tham số đầu vào.
  • "Đây là docstring của hàm greetings": Đây là docstring (chuỗi tài liệu) của hàm, dùng để mô tả chức năng của hàm. Nó được đặt trong dấu nháy đôi hoặc nháy ba.
  • print ("Xin chào Vietnix"): Lệnh này in ra thông điệp “Xin chào Vietnix” khi hàm được gọi.
  • return: Lệnh này kết thúc hàm, ở đây không có biểu thức sau return nên hàm sẽ không trả về giá trị cụ thể (tương đương với return None).

Gọi hàm trong Python

Việc định nghĩa hàm chỉ cho biết tên hàm, các tham số cần thiết và cấu trúc các khối lệnh của hàm. Khi bạn đã hoàn tất việc định nghĩa hàm, bạn có thể gọi hàm bằng cách sử dụng tên hàm. Nếu hàm có tham số, bạn cần truyền các tham số đó vào trong dấu ngoặc đơn khi gọi. Nếu hàm không có tham số, dấu ngoặc đơn để trống khi gọi.

Ví dụ gọi một hàm trong Python

Dưới đây là một ví dụ để minh họa cho việc gọi hàm printme():

# Định nghĩa hàm
def printme(str):
    "Hàm này in một chuỗi được truyền vào"
    print(str)
    return

# Gọi hàm
printme("Đây là lần gọi hàm đầu tiên!")
printme("Và đây là lần gọi hàm thứ hai.")

Khi đoạn code trên được thực thi, kết quả sẽ hiển thị như sau:

Đây là lần gọi hàm đầu tiên!

Và đây là lần gọi hàm thứ hai.

Giải thích code:

  • def printme(str):: Dòng này định nghĩa một hàm tên là printme, hàm này nhận một tham số đầu vào là str.
  • "Hàm này in một chuỗi được truyền vào": Đây là docstring (chuỗi tài liệu) của hàm, mô tả ngắn gọn về chức năng của hàm.
  • print(str): Câu lệnh này in giá trị của tham số str ra màn hình.
  • return: Câu lệnh này kết thúc hàm và trả về giá trị None (trong trường hợp này, không có giá trị nào được trả về cụ thể).
  • printme("Đây là lần gọi hàm đầu tiên!"): Dòng này gọi hàm printme với tham số đầu vào là chuỗi "Đây là lần gọi hàm đầu tiên!".
  • printme("Và đây là lần gọi hàm thứ hai."): Dòng này gọi lại hàm printme với một chuỗi khác.

Tham chiếu và giá trị

Trong các ngôn ngữ lập trình như C và C++, có hai cơ chế chính để truyền biến vào hàm, đó là truyền bằng giá trị (call by value) và truyền bằng tham chiếu (call by reference). Tuy nhiên, cách truyền biến vào hàm trong Python lại khác biệt.

Python sử dụng cơ chế truyền bằng tham chiếu. Trong Python, biến thực chất là một nhãn hoặc tham chiếu đến một đối tượng trong bộ nhớ. Do đó, cả biến được dùng làm đối số thực tế khi gọi hàm (actual argument) lẫn tham số hình thức (formal argument) đều tham chiếu đến cùng một đối tượng trong bộ nhớ. Ta có thể kiểm chứng điều này bằng cách xem id() của biến trước và sau khi truyền vào hàm.

  • Truyền bằng giá trị (call by value): Khi một biến được truyền vào hàm theo cơ chế này, giá trị của đối số thực tế được sao chép sang biến đại diện cho đối số hình thức. Do đó, bất kỳ thay đổi nào đối với đối số hình thức cũng không làm thay đổi giá trị của đối số thực tế.
  • Truyền bằng tham chiếu (call by reference): Với cơ chế này, một tham chiếu đến đối tượng trong bộ nhớ được truyền vào. Cả đối số hình thức và đối số thực tế (các biến trong đoạn mã gọi hàm) đều tham chiếu đến cùng một đối tượng. Vì vậy, mọi thay đổi đối với đối số hình thức đều được phản ánh ở đối số thực tế.
Sơ đồ minh họa tham chiếu và giá trị
Sơ đồ minh họa tham chiếu và giá trị

Ví dụ về id() của biến

Trong ví dụ dưới đây, ta sẽ kiểm tra giá trị id() của một biến:

def testfunction(arg):
    print("ID bên trong hàm:", id(arg))

var = "Xin chào"
print("ID trước khi truyền:", id(var))
testfunction(var)

Khi đoạn mã trên được thực thi, giá trị id() của biến var trước khi truyền vào hàm và bên trong hàm sẽ được hiển thị.

ID trước khi truyền: 140283679522768
ID bên trong hàm: 140283679522768

Giải thích code:

  • def testfunction(arg):: Định nghĩa một hàm testfunction nhận một tham số đầu vào arg.
  • print("ID bên trong hàm:", id(arg)): In ra giá trị id() của tham số arg bên trong hàm. Hàm id() trả về địa chỉ bộ nhớ của đối tượng.
  • var = "Xin chào": Gán giá trị "Xin chào" cho biến var.
  • print("ID trước khi truyền:", id(var)): In ra giá trị id() của biến var trước khi truyền vào hàm.
  • testfunction(var): Gọi hàm testfunction và truyền biến var vào.

Cơ chế hoạt động cũng phụ thuộc vào việc đối tượng được truyền vào có thay đổi được (mutable) hay không thay đổi được (immutable). Đối tượng số (numeric object) trong Python là bất biến. Khi một đối tượng số được truyền vào, và sau đó hàm thay đổi giá trị của đối số hình thức, thì thực tế hàm sẽ tạo một đối tượng mới trong bộ nhớ, giữ nguyên giá trị của biến ban đầu.

Ví dụ trên cho thấy rõ ràng rằng khi một biến được truyền vào hàm trong Python, biến đó thực chất là một tham chiếu đến một vùng nhớ chứa dữ liệu. Do đó, id của biến bên ngoài và trong hàm là giống nhau.

Ví dụ về đối tượng bất biến (Immutable)

Ví dụ dưới đây cho thấy cách một đối tượng bất biến (ví dụ như số nguyên) hoạt động khi được truyền vào một hàm:

def testfunction(arg):
   print("ID bên trong hàm:", id(arg))
   arg = arg + 1
   print("Đối tượng mới sau khi tăng:", arg, id(arg))

var = 10
print("ID trước khi truyền:", id(var))
testfunction(var)
print("Giá trị sau khi gọi hàm:", var)

Kêt quả sau khi chạy đoạn code trên:

ID trước khi truyền: 140719550297160

ID bên trong hàm: 140719550297160

Đối tượng mới sau khi tăng: 11 140719550297192

Giá trị sau khi gọi hàm: 10

Giải thích code:

  • def testfunction(arg):: Định nghĩa một hàm có tên testfunction với một tham số là arg.
  • print("ID bên trong hàm:", id(arg)): In ra ID của đối tượng mà tham số arg đang tham chiếu đến bên trong hàm.
  • arg = arg + 1: Tăng giá trị của arg lên 1 đơn vị. Điều quan trọng ở đây là việc này tạo ra một đối tượng số nguyên mới.
  • print("Đối tượng mới sau khi tăng:", arg, id(arg)): In ra giá trị và ID của đối tượng arg sau khi tăng.
  • var = 10: Khai báo biến var và gán giá trị ban đầu là 10.
  • print("ID trước khi truyền:", id(var)): In ID của biến var trước khi truyền vào hàm testfunction.
  • testfunction(var): Gọi hàm testfunction và truyền biến var vào làm đối số.
  • print("Giá trị sau khi gọi hàm:", var): In giá trị của biến var sau khi hàm testfunction đã được thực thi.

Hãy cùng xem điều gì sẽ xảy ra khi truyền một đối tượng khả biến (ví dụ như danh sách – list hoặc từ điển – dictionary) vào một hàm. Cơ chế truyền vẫn là truyền bằng tham chiếu, bằng chứng là ID của danh sách trước và sau khi truyền không thay đổi. Tuy nhiên, nếu ta thay đổi danh sách bên trong hàm, thì sự thay đổi này cũng được phản ánh ở phạm vi bên ngoài hàm (biến toàn cục).

Ví dụ về truyền tham chiếu trong Python

Trong ví dụ dưới đây, chúng ta sẽ truyền một list (mảng) vào một hàm, thêm một phần tử mới vào list đó, và sau đó kiểm tra nội dung của list gốc. Ta sẽ thấy rằng list gốc đã bị thay đổi:

def testfunction(arg):
   print ("Bên trong hàm:", arg)
   print ("ID bên trong hàm:", id(arg))
   arg.append(100)

var = [10, 20, 30, 40]
print ("ID trước khi truyền:", id(var))
testfunction(var)
print ("List sau khi gọi hàm:", var)

Đoạn code trên khi thực thi, sẽ cho ra kết quả như sau:

ID trước khi truyền: 140279525484544

Bên trong hàm: [10, 20, 30, 40]

ID bên trong hàm: 140279525484544

List sau khi gọi hàm: [10, 20, 30, 40, 100]

Giải thích code:

  • def testfunction(arg):: Định nghĩa hàm testfunction nhận một tham số arg.
  • print ("Bên trong hàm:", arg): In ra giá trị của arg (list) bên trong hàm.
  • print ("ID bên trong hàm:", id(arg)): In ra ID (địa chỉ bộ nhớ) của arg bên trong hàm.
  • arg.append(100): Thêm giá trị 100 vào cuối list arg. Đây là nơi list gốc bị thay đổi.
  • var = [10, 20, 30, 40]: Tạo một list tên là var.
  • print ("ID trước khi truyền:", id(var)): In ra ID của list var trước khi truyền vào hàm.
  • testfunction(var): Gọi hàm testfunction và truyền var vào.
  • print ("List sau khi gọi hàm:", var): In ra nội dung của list var sau khi hàm được thực thi.

Đối số hàm trong Python

Đối số hàm là các giá trị hoặc biến được truyền vào một hàm khi hàm đó được gọi. Cách một hàm hoạt động thường phụ thuộc vào các đối số mà nó nhận được.

Khi bạn định nghĩa một hàm, bạn cần chỉ định một danh sách các biến (được gọi là tham số hình thức) bên trong dấu ngoặc đơn (). Các tham số này đóng vai trò như các chỗ dành sẵn cho dữ liệu sẽ được truyền vào hàm khi nó được gọi. Khi hàm được gọi, giá trị cho mỗi tham số hình thức phải được cung cấp, và chúng được gọi là đối số thực tế.

Sơ đồ minh họa cho đối số hàm trong Python
Sơ đồ minh họa cho đối số hàm trong Python

Ví dụ về đối số hàm trong Python

Hãy thử thay đổi hàm greetings (chào hỏi) để có thêm một đối số là name. Khi đó, chuỗi được truyền vào hàm như một đối số thực tế sẽ trở thành biến name bên trong hàm:

def greetings(name):
    "Đây là docstring của hàm greetings"
    print ("Xin chào {}".format(name))
    return

greetings("Nam")
greetings("Lan")
greetings("Hùng")

Đoạn code này sẽ tạo ra kết quả như sau:

Xin chào Nam

Xin chào Lan

Xin chào Hùng

Giải thích code:

  • def greetings(name):: Định nghĩa hàm greetings với một tham số hình thức là name.
  • "Đây là docstring của hàm greetings": Chuỗi tài liệu (docstring) mô tả ngắn gọn về hàm.
  • print ("Xin chào {}".format(name)): In ra lời chào, sử dụng biến name được truyền vào hàm.
  • return: Kết thúc hàm và không trả về giá trị nào.
  • greetings("Nam"), greetings("Lan"), greetings("Hùng"): Các dòng này gọi hàm greetings với các đối số thực tế khác nhau.

Các loại đối số hàm trong Python

Dựa trên cách các đối số được khai báo khi định nghĩa một hàm Python, chúng được phân loại thành các loại sau:

  • Đối số vị trí hoặc đối số bắt buộc (Positional or Required Arguments)
  • Đối số từ khóa (Keyword Arguments)
  • Đối số mặc định (Default Arguments)
  • Đối số chỉ vị trí (Positional-only Arguments)
  • Đối số chỉ từ khóa (Keyword-only arguments)
  • Đối số tùy ý hoặc đối số độ dài biến đổi (Arbitrary or Variable-length Arguments)

Đối số vị trí hoặc đối số bắt buộc (Positional or Required Arguments)

Đối số bắt buộc là các đối số được truyền vào hàm theo đúng thứ tự vị trí. Số lượng đối số trong lời gọi hàm phải khớp chính xác với số lượng đối số được định nghĩa trong hàm. Nếu không, mã sẽ báo lỗi cú pháp.

Ví dụ

# Định nghĩa hàm
def printme(str):
    "Hàm này in một chuỗi được truyền vào"
    print(str)
    return

# Gọi hàm
printme()

Khi đoạn mã trên được thực thi, nó sẽ tạo ra kết quả như sau:

Traceback (most recent call last):

  File “test.py”, line 11, in <module>

    printme()

TypeError: printme() takes exactly 1 argument (0 given).

Trong đoạn mã trên, chúng ta gọi hàm printme() mà không có bất kỳ tham số nào, điều này sẽ gây ra lỗi.

Giải thích code:

  • def printme(str):: Định nghĩa hàm printme với một tham số bắt buộc là str.
  • printme(): Cố gắng gọi hàm printme mà không cung cấp đối số nào.
  • TypeError: printme() takes exactly 1 argument (0 given): Python báo lỗi kiểu dữ liệu (TypeError) vì hàm printme được định nghĩa là cần 1 đối số, nhưng lại được gọi mà không có đối số nào cả.

Đối số từ khóa (Keyword Arguments)

Đối số từ khóa (Keyword arguments) liên quan đến các lời gọi hàm. Khi bạn sử dụng đối số từ khóa trong lời gọi hàm, người gọi xác định các đối số bằng tên tham số. Điều này cho phép bạn bỏ qua các đối số hoặc đặt chúng ra khỏi thứ tự vì trình thông dịch Python có thể sử dụng các từ khóa được cung cấp để khớp các giá trị với tham số.

Ví dụ 1

Ví dụ dưới đây minh họa cách sử dụng đối số từ khóa trong Python:

# Định nghĩa hàm
def printme(str):
    "Hàm này in một chuỗi được truyền vào."
    print(str)
    return

# Gọi hàm
printme(str = "Chuỗi của tôi")

Khi đoạn mã trên được thực thi, kết quả sẽ hiển thị như sau:

Chuỗi của tôi

Giải thích code:

  • def printme(str):: Định nghĩa một hàm printme có một tham số đầu vào là str.
  • print(str): Câu lệnh in giá trị của tham số str ra màn hình.
  • return: Lệnh kết thúc hàm.
  • printme(str = "Chuỗi của tôi"): Dòng này gọi hàm printme và truyền giá trị “Chuỗi của tôi” vào cho tham số str. Thay vì chỉ truyền giá trị, ta chỉ định rõ str = "Chuỗi của tôi" để thể hiện rõ vai trò của đối số này trong hàm.

Ví dụ 2

Ví dụ sau đây sẽ làm rõ hơn về cách hoạt động của đối số từ khóa. Bạn có thể thấy rằng, thứ tự của các tham số không còn quan trọng:

# Định nghĩa hàm
def printinfo(name, age):
    "Hàm này in thông tin được truyền vào."
    print("Tên:", name)
    print("Tuổi:", age)
    return

# Gọi hàm
printinfo(age=50, name="miki")

Khi đoạn mã trên được thực thi, kết quả sẽ như sau:

Tên: miki
Tuổi: 50

Giải thích code:

  • def printinfo(name, age):: Dòng này định nghĩa một hàm printinfo với hai tham số đầu vào là name (tên) và age (tuổi).
  • print("Tên:", name): Lệnh in ra màn hình dòng chữ “Tên:” và giá trị của tham số name.
  • print("Tuổi:", age): Lệnh in ra màn hình dòng chữ “Tuổi:” và giá trị của tham số age.
  • return: Lệnh kết thúc hàm.
  • printinfo(age=50, name="miki"): Dòng này gọi hàm printinfo với việc chỉ định tên tham số tương ứng. Ta có thể thấy rằng age được truyền vào giá trị 50name được gán bằng "miki". Điều đặc biệt là thứ tự truyền tham số khác với thứ tự định nghĩa tham số trong hàm.

Đối số mặc định (Default Arguments)

Một đối số mặc định là một đối số được gán một giá trị mặc định trước. Nếu khi gọi hàm, bạn không truyền giá trị cho đối số này, hàm sẽ sử dụng giá trị mặc định đã được gán trước đó.

Ví dụ về đối số mặc định

Ví dụ sau đây minh họa cách sử dụng đối số mặc định. Hàm sẽ sử dụng giá trị tuổi mặc định (35) nếu giá trị này không được cung cấp khi gọi hàm:

# Định nghĩa hàm
def printinfo(name, age=35):
    "Hàm này in thông tin được truyền vào."
    print("Tên:", name)
    print("Tuổi:", age)
    return

# Gọi hàm
printinfo(age=50, name="miki")
printinfo(name="miki")

Khi đoạn mã trên được thực thi, kết quả sẽ hiển thị như sau:

Tên: miki
Tuổi: 50
Tên: miki
Tuổi: 35

Giải thích code:

  • def printinfo(name, age=35):: Dòng này định nghĩa một hàm printinfo với hai tham số: nameage. Tham số age có một giá trị mặc định là 35.
  • print("Tên:", name): Lệnh in ra màn hình dòng chữ “Tên:” và giá trị của tham số name.
  • print("Tuổi:", age): Lệnh in ra màn hình dòng chữ “Tuổi:” và giá trị của tham số age.
  • return: Lệnh kết thúc hàm.
  • printinfo(age=50, name="miki"): Dòng này gọi hàm printinfo, và giá trị tuổi đã được truyền vào là 50. Lúc này hàm sẽ sử dụng giá trị 50 thay cho giá trị mặc định.
  • printinfo(name="miki"): Dòng này gọi hàm printinfo chỉ truyền vào tham số name, không truyền vào tham số age. Khi này hàm sẽ tự động gán giá trị 35 (được định nghĩa là mặc định ở hàm) cho tham số age.

Đối số chỉ vị trí (Positional-only Arguments)

Những đối số mà chỉ có thể được xác định bằng vị trí của chúng trong lời gọi hàm được gọi là đối số chỉ định theo vị trí (positional-only arguments). Các đối số này được định nghĩa bằng cách đặt một dấu gạch chéo (/) trong danh sách tham số của hàm, sau tất cả các tham số chỉ định theo vị trí. Tính năng này được giới thiệu từ phiên bản Python 3.8.

Lợi ích của việc sử dụng kiểu đối số này là nó đảm bảo rằng các hàm được gọi với đúng đối số và đúng thứ tự. Các đối số chỉ định theo vị trí phải được truyền vào hàm dưới dạng đối số vị trí, không phải đối số từ khóa.

Ví dụ

Trong ví dụ sau, chúng ta đã định nghĩa hai đối số chỉ định theo vị trí là x và y. Phương thức này phải được gọi với các đối số vị trí theo đúng thứ tự mà chúng được khai báo. Nếu không, chúng ta sẽ nhận được lỗi.

def posFun(x, y, /, z):
    print(x + y + z)

print("Đánh giá đối số chỉ định theo vị trí:")
posFun(33, 22, z=11)

Sau khi chạy đoạn code trên, kết quả sẽ là:

Đánh giá đối số chỉ định theo vị trí:
66

Giải thích code:

  • def posFun(x, y, /, z):: Định nghĩa hàm posFun với ba tham số: x, yz. Dấu / trong danh sách tham số chỉ định rằng xy là các đối số chỉ định theo vị trí.
  • print(x + y + z): Hàm này tính tổng ba tham số x, y, z và in kết quả.
  • print("Đánh giá đối số chỉ định theo vị trí:"): In ra một thông báo cho biết ta sắp thực hiện gọi hàm có đối số chỉ định theo vị trí.
  • posFun(33, 22, z=11): Gọi hàm posFun, truyền giá trị 33 cho x, 22 cho y và truyền 11 cho z thông qua đối số từ khóa.

Đối số chỉ từ khóa (Keyword-only arguments)

Những đối số mà bắt buộc phải được chỉ định bằng tên khi gọi hàm được gọi là đối số chỉ định theo từ khóa. Để định nghĩa các đối số này, bạn cần đặt một dấu hoa thị (*) trong danh sách tham số của hàm, ngay trước bất kỳ tham số chỉ định theo từ khóa nào. Loại đối số này chỉ có thể được truyền vào hàm dưới dạng đối số từ khóa, chứ không phải là đối số vị trí.

Ví dụ

Trong đoạn code dưới đây, ta định nghĩa một hàm với ba đối số chỉ định theo từ khóa. Để gọi hàm này, chúng ta bắt buộc phải truyền đối số từ khóa, nếu không sẽ xảy ra lỗi.

def posFun(*, num1, num2, num3):
    print(num1 * num2 * num3)

print("Đánh giá các đối số chỉ định theo từ khóa: ")
posFun(num1=6, num2=8, num3=5)

Đoạn code trên khi chạy sẽ cho ra kết quả sau:

Đánh giá các đối số chỉ định theo từ khóa:
240

Giải thích code:

  • def posFun(*, num1, num2, num3):: Dòng này định nghĩa hàm posFun với ba tham số là num1, num2, và num3. Dấu hoa thị * trước các tham số này đánh dấu chúng là đối số chỉ định theo từ khóa.
  • print(num1 * num2 * num3): Lệnh in kết quả tích của ba tham số num1, num2, và num3.
  • print("Đánh giá các đối số chỉ định theo từ khóa: "): Lệnh in thông báo.
  • posFun(num1=6, num2=8, num3=5): Dòng này gọi hàm posFun. Để ý rằng ta bắt buộc phải truyền tham số dưới dạng num1=6, num2=8, và num3=5. Nếu chúng ta gọi posFun(6, 8, 5) thì Python sẽ báo lỗi.

Đối số tùy ý trong Python

Đôi khi, bạn có thể cần một hàm để xử lý nhiều đối số hơn so với số lượng bạn đã chỉ định khi định nghĩa hàm. Những đối số này được gọi là đối số có độ dài thay đổi hoặc đối số tùy ý, và đối số này không có tên trong định nghĩa hàm (không giống như các đối số bắt buộc hoặc đối số mặc định).

Cú pháp

Cú pháp của một hàm có đối số không từ khóa với độ dài thay đổi như sau:

def ten_ham([tham_so_chinh_thuc,] *tuple_doi_so_thay_doi):
    "chuoi_tai_lieu_cua_ham"
    phan_than_cua_ham
    return [bieu_thuc]

Dấu hoa thị (*) được đặt trước tên biến chứa giá trị của tất cả các đối số không từ khóa có độ dài thay đổi. Tuple này sẽ trống nếu không có thêm đối số nào được chỉ định trong quá trình gọi hàm.

Ví dụ

Dưới đây là một ví dụ đơn giản về cách sử dụng đối số độ dài thay đổi trong Python:

# Định nghĩa hàm
def printinfo(arg1, *vartuple):
    "Hàm này in các đối số có độ dài thay đổi"
    print("Kết quả là:")
    print(arg1)
    for var in vartuple:
        print(var)
    return

# Gọi hàm
printinfo(10)
printinfo(70, 60, 50)

Khi đoạn mã trên được thực thi, kết quả sẽ hiển thị như sau:

Kết quả là:
10
Kết quả là:
70
60
50

Giải thích code:

  • def printinfo(arg1, *vartuple):: Dòng này định nghĩa hàm printinfo với một tham số bắt buộc arg1 và một tham số tùy ý *vartuple. Dấu * trước vartuple chỉ ra rằng hàm này có thể nhận nhiều đối số không từ khóa (có độ dài thay đổi) và chúng sẽ được gom thành một tuple gọi là vartuple.
  • print("Kết quả là:"): Dòng lệnh in ra thông báo “Kết quả là:”.
  • print(arg1): Dòng lệnh này in giá trị của tham số arg1.
  • for var in vartuple:: Vòng lặp for duyệt qua từng phần tử trong tuple vartuple.
  • print(var): Trong vòng lặp, mỗi phần tử var trong tuple sẽ được in ra.
  • return: Kết thúc hàm.
  • printinfo(10): Lệnh này gọi hàm với tham số đầu tiên là 10. vartuple sẽ là tuple rỗng.
  • printinfo(70, 60, 50): Lệnh này gọi hàm với arg1 = 70vartuple = (60, 50).

Thứ tự các đối số của hàm Python

Một hàm có thể có các đối số thuộc bất kỳ loại nào đã được định nghĩa. Tuy nhiên, các đối số này cần được khai báo theo một thứ tự cụ thể như sau:

  • Danh sách đối số bắt đầu bằng các đối số chỉ theo vị trí (positional-only arguments), tiếp theo là dấu gạch chéo (/).
  • Tiếp theo là các đối số vị trí thông thường, có thể được gọi hoặc không gọi bằng đối số từ khóa.
  • Sau đó, có thể có một hoặc nhiều đối số có giá trị mặc định.
  • Tiếp theo là các đối số vị trí tùy ý, được biểu diễn bằng một biến có tiền tố là dấu hoa thị đơn (*), và được xem như một tuple.
  • Nếu hàm có bất kỳ đối số chỉ theo từ khóa (keyword-only arguments) nào, bạn cần đặt một dấu hoa thị (*) trước tên của chúng. Một số đối số chỉ theo từ khóa có thể có giá trị mặc định.
  • Cuối cùng, trong ngoặc là đối số có hai dấu hoa thị (**) để chấp nhận một số lượng tùy ý các đối số từ khóa.

Sơ đồ sau đây cho thấy thứ tự của các đối số chính thức:

Thứ tự các đối số của hàm Python
Thứ tự các đối số của hàm Python

Hàm Python với lệnh return

Từ khóa return được sử dụng như câu lệnh cuối cùng trong định nghĩa hàm, báo hiệu kết thúc khối lệnh của hàm. Sau khi gặp return, chương trình sẽ quay trở lại hàm đã gọi hàm này. Mặc dù việc giảm thụt lề sau câu lệnh cuối cùng trong khối lệnh cũng ngầm định sự kết thúc của hàm, nhưng việc sử dụng return một cách tường minh vẫn được xem là một thói quen tốt.

Ngoài việc điều khiển luồng thực thi, hàm cũng có thể trả về giá trị của một biểu thức cho hàm đã gọi nó. Giá trị được trả về có thể được lưu trữ trong một biến để xử lý tiếp.

Ví dụ

Hãy cùng định nghĩa hàm add() để minh họa. Hàm add() sẽ cộng hai giá trị được truyền vào và trả về tổng của chúng. Giá trị được trả về sẽ được lưu trữ trong một biến có tên là result.

def add(x, y):
    z = x + y
    return z

a = 10
b = 20
result = add(a, b)
print ("a = {} b = {} a+b = {}".format(a, b, result))

Đoạn code trên khi chạy sẽ cho ra kết quả sau:

a = 10 b = 20 a+b = 30

Giải thích code:

  • def add(x, y):: Dòng này định nghĩa hàm add có hai tham số đầu vào là xy.
  • z = x + y: Trong hàm, biến z được gán bằng tổng của xy.
  • return z: Hàm trả về giá trị của biến z (tổng của xy) về nơi hàm được gọi.
  • a = 10b = 20: Hai biến ab được gán giá trị lần lượt là 1020.
  • result = add(a, b): Hàm add được gọi với đối số ab, giá trị trả về được gán cho biến result.
  • print ("a = {} b = {} a+b = {}".format(a, b, result)): Câu lệnh này in ra màn hình giá trị của các biến a, bresult, sử dụng format string để hiển thị kết quả rõ ràng.

Hàm Anonymous trong Python

Các hàm được gọi là “Anonymous” khi hàm này không được khai báo theo cách tiêu chuẩn, sử dụng từ khóa def. Thay vào đó, các hàm này được định nghĩa bằng cách sử dụng từ khóa lambda.

  • Hàm lambda có thể nhận bất kỳ số lượng đối số nào, nhưng chỉ trả về một giá trị duy nhất dưới dạng một biểu thức. Hàm này không thể chứa các lệnh (statement) hoặc nhiều biểu thức.
  • Một hàm vô danh không thể gọi trực tiếp hàm print vì lambda yêu cầu một biểu thức trả về một giá trị.
  • Các hàm lambda có không gian tên cục bộ riêng và không thể truy cập các biến bên ngoài danh sách tham số và các biến trong không gian tên toàn cục.
  • Mặc dù có vẻ như lambda là một phiên bản rút gọn một dòng của hàm thông thường, nhưng thực tế không tương đương với các lệnh nội tuyến (inline) trong C hoặc C++, mà mục đích của lệnh nội tuyến là bỏ qua việc cấp phát ngăn xếp hàm trong quá trình gọi để tăng hiệu suất.

Cú pháp của hàm lamba

Cú pháp của hàm lambda chỉ chứa một biểu thức duy nhất, như sau:

lambda [arg1 [,arg2,.....argn]]: biểu_thức

Ví dụ

Ví dụ dưới đây minh họa cách hàm lambda hoạt động:

# Định nghĩa hàm lambda
sum = lambda arg1, arg2: arg1 + arg2

# Gọi hàm lambda
print ("Giá trị tổng là : ", sum(10, 20))
print ("Giá trị tổng là : ", sum(20, 20))

Khi đoạn mã trên được thực thi, kết quả sẽ là:

Giá trị tổng là : 30
Giá trị tổng là : 40

Giải thích code:

  • sum = lambda arg1, arg2: arg1 + arg2: Đây là cách định nghĩa một hàm lambda có tên sum. Hàm này nhận hai tham số arg1arg2, và trả về tổng của chúng (arg1 + arg2). Cấu trúc này gọn nhẹ và tương đương với việc định nghĩa hàm thông thường với từ khóa def nhưng ngắn gọn hơn.
  • print ("Giá trị tổng là : ", sum(10, 20)): Gọi hàm sum (là một hàm lambda) với hai tham số là 1020. Sau đó in kết quả ra màn hình.
  • print ("Giá trị tổng là : ", sum(20, 20)): Tương tự, dòng này gọi hàm sum với hai tham số 2020, rồi in kết quả ra.

Phạm vi biến trong Python

Không phải tất cả các biến trong một chương trình đều có thể được truy cập ở mọi nơi. Điều này phụ thuộc vào vị trí bạn khai báo biến đó.

Phạm vi của một biến xác định phần nào của chương trình mà bạn có thể truy cập vào biến đó. Trong Python, có hai phạm vi biến cơ bản:

  1. Biến toàn cục (Global variables)
  2. Biến cục bộ (Local variables)

Biến toàn cục (Global) và biến cục bộ (Local)

Các biến được khai báo bên trong một hàm có phạm vi cục bộ, và các biến được khai báo bên ngoài có phạm vi toàn cục.

Điều này có nghĩa là biến cục bộ chỉ có thể được truy cập bên trong hàm mà chúng được khai báo, trong khi đó biến toàn cục có thể được truy cập ở bất cứ đâu trong chương trình và bởi tất cả các hàm. Khi bạn gọi một hàm, các biến được khai báo bên trong hàm sẽ bắt đầu có hiệu lực trong phạm vi đó.

Ví dụ

Dưới đây là một ví dụ minh họa phạm vi cục bộ và toàn cục:

total = 0  # Đây là biến toàn cục

# Định nghĩa hàm
def sum(arg1, arg2):
    # Cộng hai tham số và trả về kết quả.
    total = arg1 + arg2 # Đây là biến cục bộ
    print("Trong hàm, biến cục bộ total:", total)
    return total

# Gọi hàm sum
sum(10, 20)
print("Ngoài hàm, biến toàn cục total:", total)

Khi đoạn mã trên được thực thi, kết quả sẽ như sau:

Trong hàm, biến cục bộ total: 30
Ngoài hàm, biến toàn cục total: 0

Giải thích code:

  • total = 0: Đây là khai báo biến total bên ngoài hàm sum, tức đây là biến toàn cục (global).
  • def sum(arg1, arg2):: Khai báo một hàm sum có hai tham số arg1arg2.
  • total = arg1 + arg2: Bên trong hàm sum, lại có một biến total được khai báo và gán giá trị. Đây là một biến cục bộ (local).
  • print("Trong hàm, biến cục bộ total:", total): Lệnh này in ra giá trị của biến total cục bộ bên trong hàm sum.
  • return total: Lệnh này trả về giá trị của biến total cục bộ.
  • sum(10, 20): Gọi hàm sum với hai đối số là 10 và 20.
  • print("Ngoài hàm, biến toàn cục total:", total): Lệnh này in ra giá trị của biến total toàn cục bên ngoài hàm sum.

Lời kết

Vậy là chúng ta vừa cùng nhau khám phá chi tiết về hàm trong Python, từ khái niệm cơ bản đến cách ứng dụng hàm trong thực tế. Hy vọng rằng những kiến thức này sẽ giúp bạn viết code Python một cách hiệu quả và tối ưu hơn. Hãy tiếp tục luyện tập và đừng ngần ngại thử sức với các hàm phức tạp hơn để nâng cao kỹ năng lập trình.

Cao Lê Viết Tiến

PHP Leader
tại
Vietnix

Kết nối với mình qua

Icon Quote
Icon Quote

Học lập trình online cùng vietnix

Học lập trình online cùng Vietnix

PHPXem thêmThu gọn