Hướng dẫn return false python



Các khóa học miễn phí qua video:
Lập trình C Java C# SQL Server PHP HTML5-CSS3-JavaScript

Mục lục bài viết:

  • Bắt đầu với các hàm Python
  • Hiểu câu lệnh trả về Python
    • Tuyên bố trả lại rõ ràng
    • Báo cáo trả lại ngầm định
  • Trả lại và in
  • Trả lại nhiều giá trị
  • Sử dụng câu lệnh trả về Python: Các phương pháp hay nhất
    • Trả lại Không rõ ràng
    • Ghi nhớ giá trị trả lại
    • Tránh các biểu thức phức tạp
    • Trả lại giá trị so với sửa đổi toàn cầu
    • Sử dụng trả lại có điều kiện
    • Trả lại Đúng hay Sai
    • Vòng lặp ngắn
    • Nhận biết mã chết
    • Trả lại nhiều đối tượng được đặt tên
  • Chức năng quay lại: Đóng cửa
  • Chức năng Nhận và Trả hàng: Trang trí
  • Trả lại các đối tượng do người dùng xác định: Mẫu ban đầu
  • Sử dụng trả lại trong lần thử… cuối cùng là Khối
  • Sử dụng return trong các Hàm của Trình tạo
  • Phần kết luận


Câu returnlệnh Python là một thành phần chính của các hàm và phương thức . Bạn có thể sử dụng returncâu lệnh để làm cho các hàm của bạn gửi các đối tượng Python trở lại mã người gọi. Các đối tượng này được gọi là giá trị trả về của hàm . Bạn có thể sử dụng chúng để thực hiện tính toán thêm trong các chương trình của mình.

Sử dụng returncâu lệnh một cách hiệu quả là một kỹ năng cốt lõi nếu bạn muốn viết mã các hàm tùy chỉnh theo kiểu Pythonic và mạnh mẽ.

Trong hướng dẫn này, bạn sẽ học:

  • Cách sử dụng câu lệnh Pythonreturn trong các hàm của bạn
  • Cách trả về một hoặc nhiều giá trị từ các hàm của bạn
  • Các phương pháp hay nhất cần tuân thủ khi sử dụng returncâu lệnh

Với kiến ​​thức này, bạn sẽ có thể viết các hàm dễ đọc, dễ bảo trì và ngắn gọn hơn bằng Python. Nếu bạn hoàn toàn mới với các hàm Python, thì bạn có thể xem Định nghĩa hàm Python của riêng bạn trước khi đi sâu vào hướng dẫn này.

Phần thưởng miễn phí: 5 Suy nghĩ khi Làm chủ Python , một khóa học miễn phí dành cho các nhà phát triển Python, cho bạn thấy lộ trình và tư duy mà bạn sẽ cần để nâng các kỹ năng Python của mình lên một cấp độ tiếp theo.

Bắt đầu với các hàm Python

Hầu hết các ngôn ngữ lập trình cho phép bạn gán tên cho một khối mã thực hiện một phép tính cụ thể. Các khối mã được đặt tên này có thể được sử dụng lại nhanh chóng vì bạn có thể sử dụng tên của chúng để gọi chúng từ các vị trí khác nhau trong mã của mình.

Các lập trình viên gọi các khối mã được đặt tên này là các chương trình con , quy trình , thủ tục hoặc hàm tùy thuộc vào ngôn ngữ mà họ sử dụng. Trong một số ngôn ngữ, có sự khác biệt rõ ràng giữa một quy trình hoặc thủ tục và một hàm.

Đôi khi sự khác biệt đó quá mạnh đến mức bạn cần sử dụng một từ khóa cụ thể để xác định một thủ tục hoặc chương trình con và một từ khóa khác để xác định một hàm. Ví dụ, ngôn ngữ lập trình Visual Basic sử dụng Subvà Functionđể phân biệt giữa hai ngôn ngữ này .

Nói chung, một thủ tục là một khối mã được đặt tên thực hiện một tập hợp các hành động mà không tính toán giá trị hoặc kết quả cuối cùng. Mặt khác, một hàm là một khối mã được đặt tên thực hiện một số hành động với mục đích tính toán giá trị hoặc kết quả cuối cùng, sau đó được gửi trở lại mã người gọi. Cả thủ tục và hàm đều có thể hoạt động dựa trên một tập giá trị đầu vào , thường được gọi là đối số .

Trong Python, các loại khối mã được đặt tên này được gọi là các hàm vì chúng luôn gửi một giá trị trở lại trình gọi. Tài liệu Python định nghĩa một hàm như sau:

Một loạt các câu lệnh trả về một số giá trị cho một người gọi. Nó cũng có thể được truyền không hoặc nhiều đối số có thể được sử dụng trong quá trình thực thi phần thân. ( Nguồn )

Mặc dù tài liệu chính thức nói rằng một hàm “trả về một số giá trị cho người gọi”, bạn sẽ sớm thấy rằng các hàm có thể trả về bất kỳ đối tượng Python nào cho mã người gọi.

Nói chung, một hàm nhận đối số (nếu có), thực hiện một số hoạt động và trả về một giá trị (hoặc đối tượng). Giá trị mà một hàm trả về cho người gọi thường được gọi là giá trị trả về của hàm . Tất cả các hàm Python đều có giá trị trả về, rõ ràng hoặc ngầm định. Bạn sẽ đề cập đến sự khác biệt giữa các giá trị trả về rõ ràng và ngầm định ở phần sau trong hướng dẫn này.

Để viết một hàm Python, bạn cần một tiêu đề bắt đầu bằng deftừ khóa , theo sau là tên của hàm, danh sách tùy chọn các đối số được phân tách bằng dấu phẩy bên trong một cặp dấu ngoặc đơn bắt buộc và dấu hai chấm cuối cùng.

Thành phần thứ hai của một hàm là khối mã hoặc nội dung của nó . Python định nghĩa các khối mã bằng cách sử dụng thụt đầu dòng thay vì dấu ngoặc beginvà endtừ khóa, v.v. Vì vậy, để xác định một hàm trong Python, bạn có thể sử dụng cú pháp sau:

def function_name(arg1, arg2,..., argN):
    # Function's code goes here...
    pass

Khi bạn đang mã hóa một hàm Python, bạn cần xác định tiêu đề với deftừ khóa, tên của hàm và danh sách các đối số trong dấu ngoặc đơn. Lưu ý rằng danh sách các đối số là tùy chọn, nhưng các dấu ngoặc đơn là bắt buộc về mặt cú pháp. Sau đó, bạn cần xác định khối mã của hàm, khối này sẽ bắt đầu một mức thụt lề về bên phải.

Trong ví dụ trên, bạn sử dụng một passcâu lệnh . Loại câu lệnh này hữu ích khi bạn cần một câu lệnh giữ chỗ trong mã của mình để làm cho nó chính xác về mặt cú pháp, nhưng bạn không cần phải thực hiện bất kỳ hành động nào. passcác câu lệnh còn được gọi là thao tác null vì chúng không thực hiện bất kỳ hành động nào.

Lưu ý: Cú pháp đầy đủ để xác định các hàm và đối số của chúng nằm ngoài phạm vi của hướng dẫn này. Để có tài nguyên chuyên sâu về chủ đề này, hãy xem Định nghĩa hàm Python của riêng bạn .

Để sử dụng một chức năng, bạn cần phải gọi nó. Một lệnh gọi hàm bao gồm tên của hàm theo sau là các đối số của hàm trong dấu ngoặc đơn:

function_name(arg1, arg2, ..., argN)

Bạn sẽ chỉ cần chuyển các đối số cho một lệnh gọi hàm nếu hàm yêu cầu chúng. Mặt khác, dấu ngoặc đơn luôn được yêu cầu trong một lệnh gọi hàm. Nếu bạn quên chúng, thì bạn sẽ không gọi hàm mà tham chiếu nó như một đối tượng hàm.

Để làm cho các hàm của bạn trả về một giá trị, bạn cần sử dụng câu lệnh Pythonreturn . Đó là những gì bạn sẽ đề cập từ thời điểm này.

Tìm hiểu về Python returnTuyên Bố

Câu lệnh Pythonreturn là một câu lệnh đặc biệt mà bạn có thể sử dụng bên trong một hàm hoặc phương thức để gửi kết quả của hàm trở lại trình gọi. Một returncâu lệnh bao gồm returntừ khóa theo sau là giá trị trả về tùy chọn .

Giá trị trả về của một hàm Python có thể là bất kỳ đối tượng Python nào. Mọi thứ trong Python đều là một đối tượng. Vì vậy, chức năng của bạn có thể trở lại các giá trị số ( intfloatvà complexgiá trị), các bộ sưu tập và trình tự của các đối tượng ( list,tuple , dictionary, hoặc setđối tượng), các đối tượng người dùng định nghĩa, các lớp học, chức năng, và thậm chí cả các module hoặc gói .

Bạn có thể bỏ qua giá trị trả về của một hàm và sử dụng returngiá trị trả về không có giá trị trả về. Bạn cũng có thể bỏ qua toàn bộ returncâu lệnh. Trong cả hai trường hợp, giá trị trả về sẽ là None.

Trong hai phần tiếp theo, bạn sẽ trình bày những kiến ​​thức cơ bản về cách returnhoạt động của câu lệnh và cách bạn có thể sử dụng nó để trả kết quả của hàm trở lại mã người gọi.

returnTuyên bố rõ ràng

Một câu lệnh rõ ràngreturn ngay lập tức chấm dứt thực thi một hàm và gửi giá trị trả về trở lại mã người gọi. Để thêm một returncâu lệnh rõ ràng vào một hàm Python, bạn cần sử dụng returntheo sau là một giá trị trả về tùy chọn:

>>>

>>> def return_42():
...     return 42  # An explicit return statement
...

>>> return_42()  # The caller code gets 42
42

Khi bạn xác định return_42(), bạn thêm một returncâu lệnh rõ ràng ( return 42) vào cuối khối mã của hàm. 42là giá trị trả về rõ ràng của return_42(). Điều này có nghĩa là bất kỳ lúc nào bạn gọi return_42(), chức năng sẽ gửi 42lại cho người gọi.

Lưu ý: Bạn có thể sử dụng các returncâu lệnh rõ ràng có hoặc không có giá trị trả về. Nếu bạn xây dựng một returncâu lệnh mà không chỉ định giá trị trả về, thì bạn sẽ hoàn toàn trả về None.

Nếu bạn xác định một hàm bằng một returncâu lệnh rõ ràng có giá trị trả về rõ ràng, thì bạn có thể sử dụng giá trị trả về đó trong bất kỳ biểu thức nào:

>>>

>>> num = return_42()
>>> num
42

>>> return_42() * 2
84

>>> return_42() + 5
47

Vì return_42()trả về một giá trị số, bạn có thể sử dụng giá trị đó trong một biểu thức toán học hoặc bất kỳ loại biểu thức nào khác trong đó giá trị có ý nghĩa logic hoặc mạch lạc. Đây là cách mã người gọi có thể tận dụng giá trị trả về của một hàm.

Lưu ý rằng bạn chỉ có thể sử dụng một returncâu lệnh bên trong định nghĩa hàm hoặc phương thức. Nếu bạn sử dụng nó ở bất kỳ nơi nào khác, thì bạn sẽ nhận được SyntaxError:

>>>

>>> return 42
  File "<stdin>", line 1
SyntaxError: 'return' outside function

Khi bạn sử dụng returnbên ngoài một hàm hoặc phương thức, bạn sẽ nhận được SyntaxErrorthông báo rằng không thể sử dụng câu lệnh bên ngoài một hàm.

Bạn có thể sử dụng bất kỳ đối tượng Python nào làm giá trị trả về. Vì mọi thứ trong Python là một đối tượng, bạn có thể trả về chuỗi , danh sách, bộ giá trị, từ điển, hàm, lớp, phiên bản , đối tượng do người dùng định nghĩa và thậm chí cả mô-đun hoặc gói.

Ví dụ: giả sử bạn cần viết một hàm lấy danh sách các số nguyên và trả về một danh sách chỉ chứa các số chẵn trong danh sách ban đầu. Đây là một cách mã hóa hàm này:

>>>

>>> def get_even(numbers):
...     even_nums = [num for num in numbers if not num % 2]
...     return even_nums
...

>>> get_even([1, 2, 3, 4, 5, 6])
[2, 4, 6]

get_even()sử dụng khả năng hiểu danh sách để tạo danh sách lọc ra các số lẻ trong bản gốc numbers. Sau đó, hàm trả về danh sách kết quả, chỉ chứa các số chẵn.

Một thực tế phổ biến là sử dụng kết quả của một biểu thức làm giá trị trả về trong một returncâu lệnh. Để áp dụng ý tưởng này, bạn có thể viết lại get_even()như sau:

>>>

>>> def get_even(numbers):
...     return [num for num in numbers if not num % 2]
...

>>> get_even([1, 2, 3, 4, 5, 6])
[2, 4, 6]

Khả năng hiểu danh sách được đánh giá và sau đó hàm trả về với danh sách kết quả. Lưu ý rằng bạn chỉ có thể sử dụng các biểu thức trong một returncâu lệnh. Biểu thức khác với các câu lệnh như điều kiện hoặc vòng lặp .

Lưu ý: Mặc dù các từ khóa listhiểu được xây dựng bằng cách sử dụng forvà (tùy chọn) if, chúng được coi là biểu thức chứ không phải là câu lệnh. Đó là lý do tại sao bạn có thể sử dụng chúng trong một returncâu lệnh.

Đối với một ví dụ khác, giả sử bạn cần tính giá trị trung bình của một mẫu các giá trị số. Để làm điều đó, bạn cần chia tổng các giá trị cho số giá trị. Dưới đây là một ví dụ sử dụng các hàm tích hợp sum()và len():

>>>

>>> def mean(sample):
...     return sum(sample) / len(sample)
...

>>> mean([1, 2, 3, 4])
2.5

Trong đó mean(), bạn không sử dụng một biến cục bộ để lưu trữ kết quả của phép tính. Thay vào đó, bạn sử dụng trực tiếp biểu thức làm giá trị trả về. Đầu tiên Python đánh giá biểu thức sum(sample) / len(sample)và sau đó trả về kết quả đánh giá, trong trường hợp này là giá trị 2.5.

returnTuyên bố ngầm

Một hàm Python sẽ luôn có giá trị trả về. Không có khái niệm về thủ tục hoặc quy trình trong Python. Vì vậy, nếu bạn không sử dụng rõ ràng giá trị trả về trong một returncâu lệnh hoặc nếu bạn hoàn toàn bỏ qua returncâu lệnh, thì Python sẽ mặc nhiên trả về một giá trị mặc định cho bạn. Giá trị trả về mặc định đó sẽ luôn là None.

Giả sử bạn đang viết một hàm thêm 1vào một số x, nhưng bạn quên cung cấp một returncâu lệnh. Trong trường hợp này, bạn sẽ nhận được một câu lệnh ngầmreturn sử dụng Nonelàm giá trị trả về:

>>>

>>> def add_one(x):
...     # No return statement at all
...     result = x + 1
...

>>> value = add_one(5)
>>> value

>>> print(value)
None

Nếu bạn không cung cấp một returncâu lệnh rõ ràng với giá trị trả về rõ ràng, thì Python sẽ cung cấp một returncâu lệnh ngầm sử dụng Nonelàm giá trị trả về. Trong ví dụ trên, add_one()thêm 1vào xvà lưu trữ giá trị vào resultnhưng nó không trả về result. Đó là lý do tại sao bạn nhận được value = Nonethay vì value = 6. Để khắc phục sự cố, bạn cần thực hiện return resulthoặc trực tiếp return x + 1.

Một ví dụ về một hàm trả về Nonelà print(). Mục tiêu của chức năng này là in các đối tượng ra tệp dòng văn bản, thường là đầu ra tiêu chuẩn (màn hình của bạn). Vì vậy, hàm này không cần một returncâu lệnh rõ ràng vì nó không trả về bất kỳ điều gì hữu ích hoặc có ý nghĩa:

>>>

>>> return_value = print("Hello, World")
Hello, World

>>> print(return_value)
None

Cuộc gọi print()in Hello, Worldra màn hình. Vì đây là mục đích của nó print(), nên hàm không cần trả về bất kỳ thứ gì hữu ích, vì vậy bạn sẽ nhận được Nonedưới dạng giá trị trả về.

Lưu ý: Trình thông dịch Python không hiển thị None. Vì vậy, để hiển thị giá trị trả về Nonetrong một phiên tương tác , bạn cần phải sử dụng rõ ràng print().

Bất kể hàm của bạn dài và phức tạp như thế nào, bất kỳ hàm nào không có returncâu lệnh rõ ràng hoặc hàm có returncâu lệnh không có giá trị trả về sẽ trả về None.

Trả lại và in

Nếu bạn đang làm việc trong một phiên tương tác, thì bạn có thể nghĩ rằng việc in một giá trị và trả về một giá trị là các thao tác tương đương. Hãy xem xét hai chức năng sau và đầu ra của chúng:

>>>

>>> def print_greeting():
...     print("Hello, World")
...

>>> print_greeting()
Hello, World

>>> def return_greeting():
...     return "Hello, World"
...

>>> return_greeting()
'Hello, World'

Cả hai chức năng dường như làm cùng một điều. Trong cả hai trường hợp, bạn thấy Hello, Worldđược in trên màn hình của mình. Chỉ có một sự khác biệt nhỏ có thể nhìn thấy — các dấu ngoặc kép trong ví dụ thứ hai. Nhưng hãy xem điều gì sẽ xảy ra nếu bạn trả về một kiểu dữ liệu khác, giả sử một intđối tượng:

>>>

>>> def print_42():
...     print(42)
...

>>> print_42()
42

>>> def return_42():
...     return 42
...

>>> return_42()
42

Không có sự khác biệt rõ ràng bây giờ. Trong cả hai trường hợp, bạn có thể thấy 42trên màn hình của mình. Hành vi đó có thể gây nhầm lẫn nếu bạn mới bắt đầu với Python. Bạn có thể nghĩ rằng trả lại và in một giá trị là các hành động tương đương.

Bây giờ, giả sử bạn đang hiểu sâu hơn về Python và bạn đang bắt đầu viết tập lệnh đầu tiên của mình. Bạn mở một trình soạn thảo văn bản và nhập mã sau:

 1def add(a, b):
 2    result = a + b
 3    return result
 4
 5add(2, 2)

add()lấy hai số, thêm chúng và trả về kết quả. Trên dòng 5 , bạn gọi add()đến tổng 2cộng 2. Vì bạn vẫn đang tìm hiểu sự khác biệt giữa trả về và in một giá trị, bạn có thể mong đợi tập lệnh của mình được in 4ra màn hình. Tuy nhiên, đó không phải là những gì xảy ra và bạn không nhận được gì trên màn hình của mình.

Hãy thử nó một mình. Lưu tập lệnh của bạn vào một tệp được gọi adding.pyvà chạy nó từ dòng lệnh của bạn như sau:

Nếu bạn chạy adding.pytừ dòng lệnh của mình, thì bạn sẽ không thấy bất kỳ kết quả nào trên màn hình của mình. Đó là bởi vì khi bạn chạy một tập lệnh, các giá trị trả về của các hàm mà bạn gọi trong tập lệnh không được in ra màn hình giống như chúng làm trong một phiên tương tác.

Nếu bạn muốn tập lệnh của mình hiển thị kết quả của cuộc gọi add()trên màn hình, thì bạn cần phải gọi một cách rõ ràng print(). Kiểm tra bản cập nhật sau của adding.py:

 1def add(a, b):
 2    result = a + b
 3    return result
 4
 5print(add(2, 2))

Bây giờ, khi bạn chạy adding.py, bạn sẽ thấy số 4trên màn hình của mình.

Vì vậy, nếu bạn đang làm việc trong một phiên tương tác, thì Python sẽ hiển thị kết quả của bất kỳ lệnh gọi hàm nào trực tiếp lên màn hình của bạn. Nhưng nếu bạn đang viết một tập lệnh và bạn muốn xem giá trị trả về của một hàm, thì bạn cần phải sử dụng một cách rõ ràng print().

Trả lại nhiều giá trị

Bạn có thể sử dụng một returncâu lệnh để trả về nhiều giá trị từ một hàm. Để làm điều đó, bạn chỉ cần cung cấp một số giá trị trả về được phân tách bằng dấu phẩy.

Ví dụ: giả sử bạn cần viết một hàm lấy một mẫu dữ liệu số và trả về một bản tóm tắt các phép đo thống kê. Để viết mã cho hàm đó, bạn có thể sử dụng mô-đun chuẩn Python statistics, mô-đun này cung cấp một số hàm để tính toán thống kê toán học của dữ liệu số.

Đây là cách triển khai chức năng của bạn có thể:

import statistics as st

def describe(sample):
    return st.mean(sample), st.median(sample), st.mode(sample)

Trong đó describe(), bạn tận dụng khả năng của Python để trả về nhiều giá trị trong một returncâu lệnh bằng cách trả về giá trị trung bình, giá trị trung bình và chế độ của mẫu cùng một lúc. Lưu ý rằng, để trả về nhiều giá trị, bạn chỉ cần viết chúng trong danh sách được phân tách bằng dấu phẩy theo thứ tự bạn muốn chúng được trả về.

Khi bạn đã mã hóa describe(), bạn có thể tận dụng tính năng mạnh mẽ của Python được gọi là giải nén có thể lặp lại để giải nén ba biện pháp thành ba biến riêng biệt hoặc bạn chỉ có thể lưu trữ mọi thứ trong một biến:

>>>

>>> sample = [10, 2, 4, 7, 9, 3, 9, 8, 6, 7]
>>> mean, median, mode = describe(sample)

>>> mean
6.5

>>> median
7.0

>>> mode
7

>>> desc = describe(sample)
>>> desc
(6.5, 7.0, 7)

>>> type(desc)
<class 'tuple'>

Ở đây, bạn giải nén ba giá trị trở lại của describe()thành các biến meanmedianvà mode. Lưu ý rằng trong ví dụ cuối cùng, bạn lưu trữ tất cả các giá trị trong một biến duy nhất, biến descnày hóa ra là một Python tuple.

Lưu ý: Bạn có thể tạo Python tuplebằng cách chỉ định một số giá trị được phân tách bằng dấu phẩy cho một biến duy nhất. Không cần sử dụng dấu ngoặc đơn để tạo một tuple. Đó là lý do tại sao nhiều giá trị trả về được đóng gói trong a tuple.

Hàm dựng sẵn divmod()cũng là một ví dụ về hàm trả về nhiều giá trị. Hàm nhận hai số (không phức tạp) làm đối số và trả về hai số, thương của hai giá trị đầu vào và phần còn lại của phép chia:

>>>

>>> divmod(15, 3)
(5, 0)

>>> divmod(8, 3)
(2, 2)

Lệnh gọi divmod()trả về một bộ giá trị chứa thương và phần dư là kết quả của việc chia hai số không phức được cung cấp dưới dạng đối số. Đây là một ví dụ về một hàm có nhiều giá trị trả về.

Sử dụng returnTuyên bố Python : Các phương pháp hay nhất

Cho đến nay, bạn đã trình bày những kiến ​​thức cơ bản về cách returnhoạt động của câu lệnh Python . Bây giờ bạn biết cách viết các hàm trả về một hoặc nhiều giá trị cho trình gọi. Ngoài ra, bạn đã biết rằng nếu bạn không thêm một returncâu lệnh rõ ràng với giá trị trả về rõ ràng vào một hàm nhất định, thì Python sẽ thêm nó cho bạn. Giá trị đó sẽ là None.

Trong phần này, bạn sẽ trình bày một số ví dụ sẽ hướng dẫn bạn qua một tập hợp các phương pháp lập trình tốt để sử dụng returncâu lệnh một cách hiệu quả . Những thực hành này sẽ giúp bạn viết các hàm dễ đọc, dễ bảo trì, mạnh mẽ và hiệu quả hơn trong Python.

Trả lại một Nonecách rõ ràng

Một số lập trình viên dựa vào returncâu lệnh ngầm mà Python thêm vào bất kỳ hàm nào mà không có một câu lệnh rõ ràng. Điều này có thể gây nhầm lẫn cho các nhà phát triển đến từ các ngôn ngữ lập trình khác, trong đó một hàm không có giá trị trả về được gọi là một thủ tục .

Có những tình huống mà bạn có thể thêm một cách rõ ràng return Nonevào các chức năng của mình. Tuy nhiên, trong các tình huống khác, bạn có thể dựa vào hành vi mặc định của Python:

  • Nếu hàm của bạn thực hiện các hành động nhưng không có returngiá trị rõ ràng và hữu ích , thì bạn có thể bỏ qua việc trả về Nonevì làm điều đó sẽ chỉ là thừa và khó hiểu. Bạn cũng có thể sử dụng một returngiá trị trống không có giá trị trả về chỉ để làm rõ ý định quay lại của bạn từ hàm.

  • Nếu hàm của bạn có nhiều returncâu lệnh và trả về Nonelà một tùy chọn hợp lệ, thì bạn nên xem xét việc sử dụng rõ ràng return Nonethay vì dựa vào hành vi mặc định của Python.

Những thực hành này có thể cải thiện khả năng đọc và khả năng bảo trì của mã của bạn bằng cách truyền đạt ý định của bạn một cách rõ ràng.

Khi nói đến việc quay lại None, bạn có thể sử dụng một trong ba cách tiếp cận có thể có:

  1. Bỏ qua returncâu lệnh và dựa vào hành vi trả về mặc định None.
  2. Sử dụng returngiá trị trống không có giá trị trả về, giá trị này cũng trả về None.
  3. Trả lại Nonemột cách rõ ràng.

Đây là cách điều này hoạt động trong thực tế:

>>>

>>> def omit_return_stmt():
...     # Omit the return statement
...     pass
...
>>> print(omit_return_stmt())
None

>>> def bare_return():
...     # Use a bare return
...     return
...
>>> print(bare_return())
None

>>> def return_none_explicitly():
...     # Return None explicitly
...     return None
...
>>> print(return_none_explicitly())
None

Việc có trở lại Nonemột cách rõ ràng hay không là một quyết định cá nhân. Tuy nhiên, bạn nên xem xét rằng trong một số trường hợp, một thông báo rõ ràng return Nonecó thể tránh được các vấn đề về khả năng bảo trì. Điều này đặc biệt đúng đối với các nhà phát triển đến từ các ngôn ngữ lập trình khác không hoạt động như Python.

Ghi nhớ giá trị trả lại

Khi viết các hàm tùy chỉnh, bạn có thể vô tình quên trả về một giá trị từ một hàm. Trong trường hợp này, Python sẽ trả về Nonecho bạn. Điều này có thể gây ra các lỗi nhỏ mà một nhà phát triển Python mới bắt đầu có thể khó hiểu và gỡ lỗi .

Bạn có thể tránh vấn đề này bằng cách viết returncâu lệnh ngay sau tiêu đề của hàm. Sau đó, bạn có thể thực hiện một lần vượt qua thứ hai để viết phần thân của hàm. Đây là một mẫu mà bạn có thể sử dụng khi mã hóa các hàm Python của mình:

def template_func(args):
    result = 0  # Initialize the return value
    # Your code goes here...
    return result  # Explicitly return the result

Nếu bạn đã quen với việc bắt đầu các chức năng của mình như thế này, thì rất có thể bạn sẽ không còn bỏ sót returncâu lệnh nữa. Với cách tiếp cận này, bạn có thể viết phần thân của hàm, kiểm tra nó và đổi tên các biến khi bạn biết rằng hàm hoạt động.

Thực hành này có thể tăng năng suất của bạn và làm cho các chức năng của bạn ít bị lỗi hơn. Nó cũng có thể giúp bạn tiết kiệm rất nhiều thời gian gỡ lỗi .

Tránh các biểu thức phức tạp

Như bạn đã thấy trước đây, một thực tế phổ biến là sử dụng kết quả của một biểu thức làm giá trị trả về trong các hàm Python. Nếu biểu thức bạn đang sử dụng quá phức tạp, thì phương pháp này có thể dẫn đến các hàm khó hiểu, khó gỡ lỗi và duy trì.

Ví dụ: nếu bạn đang thực hiện một phép tính phức tạp, thì việc tính toán dần dần kết quả cuối cùng bằng cách sử dụng các biến tạm thời có tên có nghĩa sẽ dễ đọc hơn .

Hãy xem xét hàm sau để tính toán phương sai của một mẫu dữ liệu số:

>>>

>>> def variance(data, ddof=0):
...     mean = sum(data) / len(data)
...     return sum((x - mean) ** 2 for x in data) / (len(data) - ddof)
...

>>> variance([3, 4, 7, 5, 6, 2, 9, 4, 1, 3])
5.24

Cách diễn đạt mà bạn sử dụng ở đây khá phức tạp và khó hiểu. Cũng khó gỡ lỗi vì bạn đang thực hiện nhiều thao tác trong một biểu thức. Để giải quyết vấn đề cụ thể này, bạn có thể tận dụng phương pháp phát triển gia tăng để cải thiện khả năng đọc của hàm.

Hãy xem cách triển khai thay thế sau đây của variance():

>>>

>>> def variance(data, ddof=0):
...     n = len(data)
...     mean = sum(data) / n
...     total_square_dev = sum((x - mean) ** 2 for x in data)
...     return total_square_dev / (n - ddof)
...

>>> variance([3, 4, 7, 5, 6, 2, 9, 4, 1, 3])
5.24

Trong lần triển khai thứ hai này variance(), bạn tính toán phương sai trong một số bước. Mỗi bước được biểu diễn bằng một biến tạm thời có tên có nghĩa.

Các biến tạm thời như nmeanvà total_square_devthường hữu ích khi gỡ lỗi mã của bạn. Ví dụ, nếu có gì đó không ổn với một trong số chúng, thì bạn có thể gọi print()để biết điều gì đang xảy ra trước khi returncâu lệnh chạy.

Nói chung, bạn nên tránh sử dụng các biểu thức phức tạp trong returncâu lệnh của mình . Thay vào đó, bạn có thể chia mã của mình thành nhiều bước và sử dụng các biến tạm thời cho mỗi bước. Sử dụng các biến tạm thời có thể giúp mã của bạn dễ gỡ lỗi, hiểu và bảo trì hơn.

Trả lại giá trị so với sửa đổi toàn cầu

Các hàm không có returncâu lệnh rõ ràng với giá trị trả về có ý nghĩa thường tạo ra các hành động có tác dụng phụ . Một tác dụng phụ có thể là, ví dụ, in thứ gì đó ra màn hình, sửa đổi một biến toàn cục , cập nhật trạng thái của một đối tượng, ghi một số văn bản vào tệp , v.v.

Việc sửa đổi các biến toàn cục thường được coi là một phương pháp lập trình tồi. Cũng giống như các chương trình có biểu thức phức tạp, các chương trình sửa đổi các biến toàn cục có thể khó gỡ lỗi, hiểu và bảo trì.

Khi bạn sửa đổi một biến toàn cục, bạn có khả năng ảnh hưởng đến tất cả các hàm, lớp, đối tượng và bất kỳ phần nào khác của chương trình dựa trên biến toàn cục đó.

Để hiểu một chương trình sửa đổi các biến toàn cục, bạn cần phải biết tất cả các phần của chương trình có thể xem, truy cập và thay đổi các biến đó. Vì vậy, thực tiễn tốt khuyên bạn nên viết các hàm tự chứa lấy một số đối số và trả về một giá trị hữu ích (hoặc các giá trị) mà không gây ra bất kỳ tác dụng phụ nào đối với các biến toàn cục.

Ngoài ra, các hàm có returncâu lệnh rõ ràng trả về giá trị có nghĩa dễ kiểm tra hơn các hàm sửa đổi hoặc cập nhật các biến toàn cục.

Ví dụ sau đây cho thấy một hàm thay đổi một biến toàn cục. Hàm sử dụng globalcâu lệnh , cũng được coi là một phương pháp lập trình tồi trong Python:

>>>

>>> counter = 0

>>> def increment():
...     global counter
...     counter += 1
...

>>> increment()
>>> counter
1

Trong ví dụ này, trước tiên bạn tạo một biến toàn cục counter, với giá trị ban đầu là 0. Bên trong increment(), bạn sử dụng một globalcâu lệnh để cho hàm biết rằng bạn muốn sửa đổi một biến toàn cục. Báo cáo kết quả cuối cùng increments counterbằng 1.

Kết quả của việc gọi increment()sẽ phụ thuộc vào giá trị ban đầu của counter. Các giá trị ban đầu khác nhau cho countersẽ tạo ra các kết quả khác nhau, do đó, kết quả của hàm không thể được kiểm soát bởi chính hàm.

Để tránh loại hành vi này, bạn có thể viết một hàm chứa các increment()đối số và trả về một giá trị nhất quán chỉ phụ thuộc vào các đối số đầu vào:

>>>

>>> counter = 0

>>> def increment(var):
...     return var + 1
...

>>> increment(counter)
1

>>> counter
0

>>> # Explicitly assign a new value to counter
>>> counter = increment(counter)
>>> counter
1

Bây giờ kết quả của việc gọi increment()chỉ phụ thuộc vào các đối số đầu vào hơn là vào giá trị ban đầu của counter. Điều này làm cho chức năng mạnh mẽ hơn và dễ kiểm tra hơn.

Ngoài ra, khi bạn cần cập nhật counter, bạn có thể thực hiện việc này một cách rõ ràng bằng một cuộc gọi tới increment(). Bằng cách này, bạn sẽ có nhiều quyền kiểm soát hơn đối với những gì đang xảy ra countertrong suốt mã của mình.

Nói chung, bạn nên tránh các hàm sửa đổi các biến toàn cục. Nếu có thể, hãy cố gắng viết các hàm độc lập với một returncâu lệnh rõ ràng trả về một giá trị có ý nghĩa và mạch lạc.

Sử dụng có returnđiều kiện

Các hàm Python không bị hạn chế chỉ có một returncâu lệnh duy nhất . Nếu một hàm nhất định có nhiều hơn một returncâu lệnh, thì câu lệnh đầu tiên gặp phải sẽ xác định thời điểm kết thúc thực thi của hàm và cả giá trị trả về của nó.

Một cách phổ biến để viết các hàm với nhiều returncâu lệnh là sử dụng các câu lệnh điều kiện cho phép bạn cung cấp các returncâu lệnh khác nhau tùy thuộc vào kết quả đánh giá một số điều kiện.

Giả sử bạn cần mã hóa một hàm nhận một số và trả về giá trị tuyệt đối của nó. Nếu số lớn hơn 0, thì bạn sẽ trả về cùng một số. Nếu số nhỏ hơn 0, thì bạn sẽ trả về giá trị ngược lại hoặc không âm của nó.

Đây là cách triển khai có thể thực hiện cho chức năng này:

>>>

>>> def my_abs(number):
...     if number > 0:
...         return number
...     elif number < 0:
...         return -number
...

>>> my_abs(-15)
15

>>> my_abs(15)
15

my_abs()có hai returncâu lệnh rõ ràng , mỗi câu được gói gọn trong một ifcâu lệnh riêng . Nó cũng có một returntuyên bố ngầm . Nếu numberxảy ra 0, thì không có điều kiện nào là đúng và hàm kết thúc mà không nhấn vào bất kỳ returncâu lệnh rõ ràng nào . Khi điều này xảy ra, bạn sẽ tự động nhận được None.

Hãy xem lời gọi sau để my_abs()sử dụng 0làm đối số:

>>>

>>> print(my_abs(0))
None

Khi bạn gọi my_abs()bằng cách sử dụng 0làm đối số, Nonekết quả là bạn sẽ nhận được . Đó là bởi vì luồng thực thi đến cuối hàm mà không đạt được bất kỳ returncâu lệnh rõ ràng nào . Thật không may, giá trị tuyệt đối của 0là 0, không phải None.

Để khắc phục sự cố này, bạn có thể thêm returncâu lệnh thứ ba , trong một elifmệnh đề mới hoặc trong một elsemệnh đề cuối cùng :

>>>

>>> def my_abs(number):
...     if number > 0:
...         return number
...     elif number < 0:
...         return -number
...     else:
...         return 0
...

>>> my_abs(0)
0

>>> my_abs(-15)
15

>>> my_abs(15)
15

Bây giờ, my_abs()kiểm tra mọi điều kiện có thể, number > 0number < 0, và number == 0. Mục đích của ví dụ này là để chỉ ra rằng khi bạn đang sử dụng câu lệnh điều kiện để cung cấp nhiều returncâu lệnh, bạn cần đảm bảo rằng mọi tùy chọn có thể có đều có returncâu lệnh riêng . Nếu không, chức năng của bạn sẽ có một lỗi ẩn.

Cuối cùng, bạn có thể triển khai my_abs()theo cách ngắn gọn, hiệu quả và Pythonic hơn bằng cách sử dụng một ifcâu lệnh duy nhất :

>>>

>>> def my_abs(number):
...     if number < 0:
...         return -number
...     return number
...

>>> my_abs(0)
0

>>> my_abs(-15)
15

>>> my_abs(15)
15

Trong trường hợp này, hàm của bạn truy cập vào returncâu lệnh đầu tiên nếu number < 0. Trong tất cả các trường hợp khác, cho dù number > 0hoặc number == 0, nó đánh vào returncâu lệnh thứ hai . Với cách triển khai mới này, chức năng của bạn trông tốt hơn rất nhiều. Nó dễ đọc hơn, ngắn gọn và hiệu quả hơn.

Lưu ý: Có một hàm Python tích hợp sẵn tiện lợi được gọi abs()để tính toán giá trị tuyệt đối của một số. Chức năng trong ví dụ trên chỉ nhằm minh họa cho điểm đang thảo luận.

Nếu bạn đang sử dụng các ifcâu lệnh để cung cấp một số returncâu lệnh, thì bạn không cần một elsemệnh đề để bao hàm điều kiện cuối cùng. Chỉ cần thêm một returncâu lệnh vào cuối khối mã của hàm và ở mức thụt lề đầu tiên.

Trở lại TruehoặcFalse

Một trường hợp sử dụng phổ biến khác cho sự kết hợp của ifvà các returncâu lệnh là khi bạn đang mã hóa một vị từ hoặc một hàm có giá trị Boolean . Loại hàm này trả về một trong hai Truehoặc Falsetheo một điều kiện nhất định.

Ví dụ, nói rằng bạn cần phải viết một chức năng mà phải mất hai số nguyên, avà b, và trả về Truenếu alà chia hết cho b. Nếu không, hàm sẽ trả về False. Đây là cách triển khai khả thi:

>>>

>>> def is_divisible(a, b):
...     if not a % b:
...         return True
...     return False
...

>>> is_divisible(4, 2)
True

>>> is_divisible(7, 4)
False

is_divisible()trả về Truenếu phần còn lại của phép chia acho bbằng 0. Nếu không, nó sẽ trả về False. Lưu ý rằng trong Python, một 0giá trị là falsy , vì vậy bạn cần phải sử dụng các nottoán tử để phủ nhận giá trị thật của tình trạng này.

Đôi khi bạn sẽ viết các hàm vị từ liên quan đến các toán tử như sau:

  • Các toán tử so sánh == , !=>>=<, và<=
  • Nhà điều hành thành viên in
  • Nhà điều hành danh tính is
  • Toán tử Boolean not

Trong những trường hợp này, bạn có thể sử dụng trực tiếp biểu thức Boolean trong returncâu lệnh của mình . Điều này có thể xảy ra vì các toán tử này trả về một trong hai Truehoặc False. Theo ý tưởng này, đây là một triển khai mới của is_divisible():

>>>

>>> def is_divisible(a, b):
...     return not a % b
...

>>> is_divisible(4, 2)
True

>>> is_divisible(7, 4)
False

Nếu achia hết cho bthì a % btrả về 0, điều này là sai trong Python. Vì vậy, để quay lại True, bạn cần sử dụng nottoán tử.

Lưu ý: Python tuân theo một tập hợp các quy tắc để xác định giá trị chân lý của một đối tượng.

Ví dụ, các đối tượng sau được coi là giả :

  • Hằng số thích NoneFalse
  • Loại số với giá trị zero như 00.00jDecimal(0), vàFraction(0, 1)
  • Chuỗi rỗng và bộ sưu tập thích ""()[]{}set(), vàrange(0)
  • Các đối tượng triển khai __bool__()với giá trị trả về Falsehoặc __len__()với giá trị trả về là0

Bất kỳ đối tượng nào khác sẽ được coi là trung thực.

Mặt khác, nếu bạn cố gắng sử dụng các điều kiện liên quan đến toán tử Boolean như orvà andtheo cách bạn đã thấy trước đây, thì các hàm vị từ của bạn sẽ không hoạt động chính xác. Đó là bởi vì các toán tử này hoạt động khác nhau. Chúng trả về một trong các toán hạng trong điều kiện thay vì Truehoặc False:

>>>

>>> 0 and 1
0
>>> 1 and 2
2

>>> 1 or 2
1
>>> 0 or 1
1

Nói chung, andtrả về toán hạng sai đầu tiên hoặc toán hạng cuối cùng. Mặt khác, ortrả về toán hạng đúng đầu tiên hoặc toán hạng cuối cùng. Vì vậy, để viết một vị từ có liên quan đến một trong các toán tử này, bạn sẽ cần sử dụng một ifcâu lệnh rõ ràng hoặc một lệnh gọi hàm tích hợp sẵn bool().

Giả sử bạn muốn viết một hàm vị từ nhận hai giá trị và trả về Truenếu cả hai đều đúng và Falsengược lại. Đây là cách tiếp cận đầu tiên của bạn đối với chức năng này:

>>>

>>> def both_true(a, b):
...     return a and b
...
>>> both_true(1, 2)
2

Vì andtrả về toán hạng thay vì Truehoặc False, nên hàm của bạn không hoạt động chính xác. Có ít nhất ba khả năng để khắc phục sự cố này:

  1. Một tuyên bố rõ ràngif
  2. Một biểu thức điều kiện (toán tử bậc ba)
  3. Hàm Python tích hợp sẵn bool()

Nếu bạn sử dụng cách tiếp cận đầu tiên, thì bạn có thể viết both_true()như sau:

>>>

>>> def both_true(a, b):
...     if a and b:
...         return True
...     return False
...

>>> both_true(1, 2)
True

>>> both_true(1, 0)
False

Câu iflệnh kiểm tra nếu avà bcả hai đều là trung thực. Nếu vậy, sau đó both_true()quay trở lại True. Nếu không, nó sẽ trả về False.

Mặt khác, nếu bạn sử dụng biểu thức điều kiện Python hoặc toán tử bậc ba, thì bạn có thể viết hàm vị ngữ của mình như sau:

>>>

>>> def both_true(a, b):
...     return True if a and b else False
...
>>> both_true(1, 2)
True

>>> both_true(1, 0)
False

Ở đây, bạn sử dụng biểu thức điều kiện để cung cấp giá trị trả về cho both_true(). Biểu thức điều kiện được đánh giá Truenếu cả hai avà bđều đúng. Nếu không, kết quả cuối cùng là False.

Cuối cùng, nếu bạn sử dụng bool(), thì bạn có thể viết mã both_true()như sau:

>>>

>>> def both_true(a, b):
...     return bool(a and b)
...

>>> both_true(1, 2)
True

>>> both_true(1, 0)
False

bool()trả về Truenếu avà bđúng và Falsenếu không. Việc sử dụng cách tiếp cận nào để giải quyết vấn đề này là tùy thuộc vào bạn. Tuy nhiên, giải pháp thứ hai có vẻ dễ đọc hơn. Bạn nghĩ sao?

Vòng lặp ngắn

Một returncâu lệnh bên trong một vòng lặp thực hiện một số loại ngắn mạch . Nó phá vỡ việc thực thi vòng lặp và làm cho hàm trả về ngay lập tức. Để hiểu rõ hơn về hành vi này, bạn có thể viết một hàm mô phỏng any(). Hàm tích hợp này nhận một hàm có thể lặp lại và trả về Truenếu ít nhất một trong các mục của nó là trung thực.

Để mô phỏng any(), bạn có thể viết mã một hàm như sau:

>>>

>>> def my_any(iterable):
...     for item in iterable:
...         if item:
...             # Short-circuit
...             return True
...     return False

>>> my_any([0, 0, 1, 0, 0])
True

>>> my_any([0, 0, 0, 0, 0])
False

Nếu bất kỳ itemtrong nào iterablelà đúng, thì luồng thực thi sẽ đi vào trong ifkhối. Câu returnlệnh phá vỡ vòng lặp và trả về ngay lập tức với giá trị trả về là True. Nếu không có giá trị nào iterablelà true, thì my_any()trả về False.

Chức năng này thực hiện đánh giá ngắn mạch . Ví dụ: giả sử bạn chuyển một tệp có thể lặp lại chứa một triệu mục. Nếu mục đầu tiên trong mục có thể lặp lại đó là true, thì vòng lặp chỉ chạy một lần chứ không phải một triệu lần. Điều này có thể giúp bạn tiết kiệm rất nhiều thời gian xử lý khi chạy mã của mình.

Điều quan trọng cần lưu ý là để sử dụng một returncâu lệnh bên trong một vòng lặp, bạn cần phải gói câu lệnh đó trong một ifcâu lệnh. Nếu không, vòng lặp sẽ luôn bị phá vỡ trong lần lặp đầu tiên của nó.

Nhận biết mã chết

Ngay sau khi một hàm truy cập vào một returncâu lệnh, nó sẽ kết thúc mà không thực thi bất kỳ mã nào tiếp theo. Do đó, mã xuất hiện sau returncâu lệnh của hàm thường được gọi là mã chết . Trình thông dịch Python hoàn toàn bỏ qua mã chết khi chạy các chức năng của bạn. Vì vậy, có loại mã đó trong một hàm là vô ích và khó hiểu.

Hãy xem xét hàm sau, hàm này thêm mã vào sau returncâu lệnh của nó :

>>>

>>> def dead_code():
...     return 42
...     # Dead code
...     print("Hello, World")
...

>>> dead_code()
42

Câu lệnh print("Hello, World")trong ví dụ này sẽ không bao giờ thực thi vì câu lệnh đó xuất hiện sau returncâu lệnh của hàm . Xác định mã chết và loại bỏ nó là một phương pháp hay mà bạn có thể áp dụng để viết các hàm tốt hơn.

Cần lưu ý rằng nếu bạn đang sử dụng câu lệnh điều kiện để cung cấp nhiều returncâu lệnh, thì bạn có thể có mã sau một returncâu lệnh sẽ không bị chết miễn là nó nằm ngoài ifcâu lệnh:

>>>

>>> def no_dead_code(condition):
...     if condition:
...         return 42
...     print("Hello, World")
...

>>> no_dead_code(True)
42
>>> no_dead_code(False)
Hello, World

Mặc dù lệnh gọi đến print()sau một returncâu lệnh, nó không phải là mã chết. Khi conditionđược đánh giá đến Falseprint()cuộc gọi sẽ chạy và bạn sẽ được Hello, Worldin ra màn hình.

Trả lại nhiều đối tượng được đặt tên

Khi bạn đang viết một hàm trả về nhiều giá trị trong một returncâu lệnh, bạn có thể cân nhắc sử dụng một collections.namedtupleđối tượng để làm cho các hàm của bạn dễ đọc hơn. namedtuplelà một lớp tập hợp trả về một lớp con tuplecó các trường hoặc thuộc tính. Bạn có thể truy cập các thuộc tính đó bằng ký hiệu dấu chấm hoặc thao tác lập chỉ mục .

Trình khởi tạo của namedtuplecó một số đối số. Tuy nhiên, để bắt đầu sử dụng namedtuplemã của bạn, bạn chỉ cần biết về hai điều đầu tiên:

  1. typenamegiữ tên của lớp giống tuple mà bạn đang tạo. Nó cần phải là một chuỗi.
  2. field_namesgiữ tên của các trường hoặc thuộc tính của lớp giống tuple. Nó có thể là một chuỗi các chuỗi chẳng hạn như ["x", "y"]hoặc một chuỗi đơn với mỗi tên được phân tách bằng khoảng trắng hoặc dấu phẩy, chẳng hạn như "x y"hoặc "x, y".

Sử dụng một namedtuplekhi bạn cần trả về nhiều giá trị có thể làm cho các hàm của bạn dễ đọc hơn đáng kể mà không cần quá nhiều nỗ lực. Hãy xem xét bản cập nhật sau về describe()việc sử dụng namedtuplegiá trị trả về:

import statistics as st
from collections import namedtuple

def describe(sample):
    Desc = namedtuple("Desc", ["mean", "median", "mode"])
    return Desc(
        st.mean(sample),
        st.median(sample),
        st.mode(sample),
    )

Bên trong describe(), bạn tạo một cuộc namedtuplegọi Desc. Đối tượng này có thể có các thuộc tính được đặt tên mà bạn có thể truy cập bằng cách sử dụng ký hiệu dấu chấm hoặc bằng cách sử dụng thao tác lập chỉ mục. Trong ví dụ này, những thuộc tính này là "mean""median", và "mode".

Bạn có thể tạo một Descđối tượng và sử dụng nó làm giá trị trả về. Để làm điều đó, bạn cần phải khởi tạo Descgiống như cách bạn làm với bất kỳ lớp Python nào. Lưu ý rằng bạn cần cung cấp một giá trị cụ thể cho từng thuộc tính được đặt tên, giống như bạn đã làm trong returncâu lệnh của mình .

Đây là cách describe()hoạt động bây giờ:

>>>

>>> sample = [10, 2, 4, 7, 9, 3, 9, 8, 6, 7]
>>> stat_desc = describe(sample)

>>> stat_desc
Desc(mean=5.7, median=6.0, mode=6)

>>> # Get the mean by its attribute name
>>> stat_desc.mean
5.7

>>> # Get the median by its index
>>> stat_desc[1]
6.0

>>> # Unpack the values into three variables
>>> mean, median, mode = describe(sample)

>>> mean
5.7

>>> mode
6

Khi bạn gọi describe()với một mẫu dữ liệu số, bạn sẽ nhận được một namedtupleđối tượng chứa giá trị trung bình, trung vị và chế độ của mẫu. Lưu ý rằng bạn có thể truy cập từng phần tử của bộ tuple bằng cách sử dụng ký hiệu dấu chấm hoặc thao tác lập chỉ mục.

Cuối cùng, bạn cũng có thể sử dụng thao tác giải nén có thể lặp lại để lưu trữ từng giá trị trong biến độc lập của riêng nó.

Chức năng quay lại: Đóng cửa

Trong Python, các hàm là các đối tượng hạng nhất . Đối tượng hạng nhất là một đối tượng có thể được gán cho một biến, được truyền làm đối số cho một hàm hoặc được sử dụng như một giá trị trả về trong một hàm. Vì vậy, bạn có thể sử dụng một đối tượng hàm làm giá trị trả về trong bất kỳ returncâu lệnh nào .

Một hàm nhận một hàm làm đối số, trả về một hàm dưới dạng kết quả hoặc cả hai là một hàm bậc cao hơn . Hàm nhà máy đóng là một ví dụ phổ biến về hàm bậc cao trong Python. Loại hàm này nhận một số đối số và trả về một hàm bên trong . Hàm bên trong thường được gọi là hàm đóng .

Một bao đóng mang thông tin về phạm vi thực thi bao quanh của nó. Điều này cung cấp một cách để giữ lại thông tin trạng thái giữa các lần gọi hàm. Các chức năng của nhà máy đóng cửa rất hữu ích khi bạn cần viết mã dựa trên khái niệm đánh giá lười biếng hoặc trì hoãn .

Giả sử bạn cần viết một hàm trợ giúp nhận một số và trả về kết quả của phép nhân số đó với một thừa số đã cho. Bạn có thể viết mã chức năng đó như sau:

def by_factor(factor, number):
    return factor * number

by_factor()nhận factorvà numberlàm đối số và trả về sản phẩm của họ. Vì factorhiếm khi thay đổi trong ứng dụng của bạn, bạn cảm thấy khó chịu khi cung cấp cùng một hệ số trong mọi lệnh gọi hàm. Vì vậy, bạn cần một cách để giữ lại trạng thái hoặc giá trị của factorgiữa các lần gọi đến by_factor()và chỉ thay đổi nó khi cần thiết. Để giữ lại giá trị hiện tại factorgiữa các cuộc gọi, bạn có thể sử dụng một lệnh đóng.

Việc triển khai sau đây by_factor()sử dụng một bao đóng để giữ lại giá trị của factorgiữa các cuộc gọi:

>>>

>>> def by_factor(factor):
...     def multiply(number):
...         return factor * number
...     return multiply
...

>>> double = by_factor(2)
>>> double(3)
6
>>> double(4)
8

>>> triple = by_factor(3)
>>> triple(3)
9
>>> triple(4)
12

Bên trong by_factor(), bạn xác định một hàm bên trong được gọi multiply()và trả về nó mà không cần gọi nó. Đối tượng hàm mà bạn trả về là một bao đóng lưu giữ thông tin về trạng thái của factor. Nói cách khác, nó ghi nhớ giá trị của factorgiữa các cuộc gọi. Đó là lý do tại sao doublenhớ rằng factorđã bằng 2và triplenhớ rằng factorđã bằng 3.

Lưu ý rằng bạn có thể tự do sử dụng lại doublevà triplevì họ không quên thông tin trạng thái tương ứng của họ.

Bạn cũng có thể sử dụng một lambdahàm để tạo các bao đóng. Đôi khi việc sử dụng một lambdahàm có thể làm cho nhà máy đóng cửa của bạn ngắn gọn hơn. Đây là cách triển khai thay thế của by_factor()việc sử dụng một lambdahàm:

>>>

>>> def by_factor(factor):
...     return lambda number: factor * number
...

>>> double = by_factor(2)
>>> double(3)
6
>>> double(4)
8

Việc triển khai này hoạt động giống như ví dụ ban đầu. Trong trường hợp này, việc sử dụng một lambdahàm cung cấp một cách nhanh chóng và ngắn gọn để viết mã by_factor().

Chức năng Nhận và Trả hàng: Trang trí

Một cách khác để sử dụng returncâu lệnh để trả về các đối tượng hàm là viết các hàm trang trí . Một hàm decorator nhận một đối tượng hàm làm đối số và trả về một đối tượng hàm. Trình trang trí xử lý chức năng được trang trí theo một cách nào đó và trả về hoặc thay thế nó bằng một chức năng hoặc đối tượng có thể gọi khác.

Trình trang trí rất hữu ích khi bạn cần thêm logic bổ sung vào các chức năng hiện có mà không cần sửa đổi chúng. Ví dụ: bạn có thể viết mã một trình trang trí để ghi nhật ký các lệnh gọi hàm, xác thực các đối số cho một hàm, đo thời gian thực thi của một hàm nhất định, v.v.

Ví dụ sau đây cho thấy một hàm decorator mà bạn có thể sử dụng để biết thời gian thực thi của một hàm Python nhất định:

>>>

>>> import time

>>> def my_timer(func):
...     def _timer(*args, **kwargs):
...         start = time.time()
...         result = func(*args, **kwargs)
...         end = time.time()
...         print(f"Execution time: {end - start}")
...         return result
...     return _timer
...

>>> @my_timer
... def delayed_mean(sample):
...     time.sleep(1)
...     return sum(sample) / len(sample)
...

>>> delayed_mean([10, 2, 4, 7, 9, 3, 9, 8, 6, 7])
Execution time: 1.0011096000671387
6.5

Cú pháp @my_timerphía trên tiêu đề của delayed_mean()tương đương với biểu thức delayed_mean = my_timer(delayed_mean). Trong trường hợp này, bạn có thể nói rằng đó my_timer()là trang trí delayed_mean().

Python chạy các hàm decorator ngay sau khi bạn nhập hoặc chạy một mô-đun hoặc một tập lệnh. Vì vậy, khi bạn gọi delayed_mean(), bạn thực sự đang gọi giá trị trả về my_timer(), là đối tượng hàm _timer. Lệnh gọi đến trang trí delayed_mean()sẽ trả về giá trị trung bình của mẫu và cũng sẽ đo thời gian thực hiện của bản gốc delayed_mean().

Trong trường hợp này, bạn sử dụng time()để đo thời gian thực hiện bên trong trình trang trí. time()sống trong một mô-đun được gọi là mô-đun timecung cấp một tập hợp các chức năng liên quan đến thời gian. time()trả về thời gian tính bằng giây kể từ kỷ nguyên dưới dạng số dấu phẩy động. Sự khác biệt giữa thời gian trước và sau khi gọi tới delayed_mean()sẽ cho bạn biết về thời gian thực thi của hàm.

Ví dụ phổ biến khác của trang trí bằng Python là classmethod(),staticmethod() , và property(). Nếu bạn muốn tìm hiểu sâu hơn về trình trang trí Python, thì hãy xem phần Sơ đồ trang trí trên Python . Bạn cũng có thể kiểm tra Python Decorator 101 .

Trả lại các đối tượng do người dùng xác định: Mẫu ban đầu

Câu returnlệnh Python cũng có thể trả về các đối tượng do người dùng định nghĩa . Nói cách khác, bạn có thể sử dụng các đối tượng tùy chỉnh của riêng mình làm giá trị trả về trong một hàm. Một trường hợp sử dụng phổ biến cho khả năng này là mô hình nhà máy .

Factory pattern xác định một giao diện để tạo các đối tượng một cách nhanh chóng nhằm đáp ứng các điều kiện mà bạn không thể đoán trước khi viết chương trình. Bạn có thể triển khai một nhà máy sản xuất các đối tượng do người dùng xác định bằng cách sử dụng một hàm nhận một số đối số khởi tạo và trả về các đối tượng khác nhau theo đầu vào cụ thể.

Giả sử bạn đang viết một ứng dụng vẽ tranh. Bạn cần tạo nhanh các hình dạng khác nhau để đáp ứng các lựa chọn của người dùng. Chương trình của bạn sẽ có hình vuông, hình tròn, hình chữ nhật, v.v. Để tạo những hình dạng đó một cách nhanh chóng, trước tiên bạn cần tạo các lớp hình dạng mà bạn sẽ sử dụng:

class Circle:
    def __init__(self, radius):
        self.radius = radius
    # Class implementation...

class Square:
    def __init__(self, side):
        self.side = side
    # Class implementation...

Khi bạn đã có một lớp cho mỗi hình dạng, bạn có thể viết một hàm lấy tên của hình dạng dưới dạng chuỗi và danh sách tùy chọn các đối số ( *args) và các đối số từ khóa ( **kwargs) để tạo và khởi tạo các hình dạng một cách nhanh chóng:

def shape_factory(shape_name, *args, **kwargs):
    shapes = {"circle": Circle, "square": Square}
    return shapes[shape_name](*args, **kwargs)

Hàm này tạo một thể hiện của hình dạng cụ thể và trả về nó cho người gọi. Giờ đây, bạn có thể sử dụng shape_factory()để tạo các đối tượng có hình dạng khác nhau theo nhu cầu của người dùng:

>>>

>>> circle = shape_factory("circle", radius=20)
>>> type(circle)
<class '__main__.Circle'>
>>> circle.radius
20

>>> square = shape_factory("square", side=10)
>>> type(square)
<class '__main__.Square'>
>>> square.side
10

Nếu bạn gọi shape_factory()với tên của hình dạng cần thiết dưới dạng chuỗi, thì bạn sẽ nhận được một phiên bản mới của hình dạng phù hợp với hình dạng shape_namebạn vừa chuyển đến nhà máy.

Sử dụng returntrong try… finallyKhối

Khi bạn sử dụng một returncâu lệnh bên trong một trycâu lệnh với một finallymệnh đề, finallymệnh đề đó luôn được thực thi trước returncâu lệnh. Điều này đảm bảo rằng mã trong finallymệnh đề sẽ luôn chạy. Kiểm tra ví dụ sau:

>>>

>>> def func(value):
...     try:
...         return float(value)
...     except ValueError:
...         return str(value)
...     finally:
...         print("Run this before returning")
...

>>> func(9)
Run this before returning
9.0

>>> func("one")
Run this before returning
'one'

Khi bạn gọi func(), bạn sẽ được valuechuyển đổi thành một số dấu phẩy động hoặc một đối tượng chuỗi. Trước khi làm điều đó, hàm của bạn chạy finallymệnh đề và in một thông báo ra màn hình của bạn. Bất kỳ mã nào bạn thêm vào finallymệnh đề sẽ được thực thi trước khi hàm chạy returncâu lệnh của nó .

Sử dụng returntrong các chức năng của máy phát điện

Một hàm Python với một yieldcâu lệnh trong phần thân của nó là một hàm trình tạo . Khi bạn gọi một hàm trình tạo, nó sẽ trả về một trình lặp của trình tạo . Vì vậy, bạn có thể nói rằng một chức năng máy phát điện là một nhà máy sản xuất máy phát điện .

Bạn có thể sử dụng một returncâu lệnh bên trong một hàm của trình tạo để chỉ ra rằng trình tạo đã được thực hiện. Câu returnlệnh sẽ làm cho máy phát điện tăng lên a StopIteration. Giá trị trả về sẽ được chuyển làm đối số cho bộ khởi tạo của StopIterationvà sẽ được gán cho .valuethuộc tính của nó .

Đây là một trình tạo sản lượng 1và 2theo yêu cầu và sau đó trả về 3:

>>>

>>> def gen():
...     yield 1
...     yield 2
...     return 3
...

>>> g = gen()
>>> g
<generator object gen at 0x7f4ff4853c10>

>>> next(g)
1
>>> next(g)
2

>>> next(g)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    next(g)
StopIteration: 3

gen()trả về một đối tượng trình tạo sản lượng 1và 2theo yêu cầu. Để truy xuất từng số của đối tượng trình tạo, bạn có thể sử dụng next(), đây là một hàm tích hợp để truy xuất mục tiếp theo từ trình tạo Python.

Hai cuộc gọi đầu tiên để next()truy xuất 1và 2, tương ứng. Trong cuộc gọi thứ ba, máy phát điện bị cạn kiệt và bạn nhận được một StopIteration. Lưu ý rằng giá trị trả về của hàm tạo ( 3) trở thành .valuethuộc tính của StopIterationđối tượng.

Phần kết luận

Câu returnlệnh Python cho phép bạn gửi bất kỳ đối tượng Python nào từ các hàm tùy chỉnh của bạn trở lại mã người gọi. Câu lệnh này là một phần cơ bản của bất kỳ hàm hoặc phương thức Python nào. Nếu bạn thành thạo cách sử dụng nó, thì bạn sẽ sẵn sàng viết mã các hàm mạnh mẽ.

Trong hướng dẫn này, bạn đã học cách:

  • Sử dụng hiệu quả câu lệnh Pythonreturn trong các hàm của bạn
  • Trả lại một hoặc nhiều giá trị từ các hàm của bạn cho mã người gọi
  • Áp dụng các phương pháp hay nhất khi sử dụng returncâu lệnh

Ngoài ra, bạn đã học được một số trường hợp sử dụng nâng cao hơn cho returncâu lệnh, chẳng hạn như cách viết mã một hàm nhà máy đóng và một hàm trang trí . Với kiến ​​thức này, bạn sẽ có thể viết nhiều hàm Pythonic , mạnh mẽ và dễ bảo trì hơn bằng Python.


Các khóa học miễn phí qua video:
Lập trình C Java C# SQL Server PHP HTML5-CSS3-JavaScript
« Prev: Python: Tôi có thể làm gì với Python?
» Next: Python: Cách in có định dạng trong Python với bài toán in các thừa số nguyên tố

Copied !!!