Các hàm trong python là gì? Trả về giá trị từ một hàm. tuyên bố trở lại

Một chức năng là một cái gì đó dự định được thực hiện. nhiệm vụ cụ thể một khối mã riêng biệt có thể được sử dụng lại. Các hàm làm cho mã chương trình trở nên mô-đun và nhỏ gọn hơn.

Python cung cấp nhiều hàm tích hợp. Chắc hẳn bạn đã quen với những điều này:

  • print() in đối tượng tới thiết bị đầu cuối.
  • int() chuyển đổi chuỗi hoặc số thành số nguyên.
  • len() trả về độ dài của đối tượng.

Tên hàm chứa dấu ngoặc đơn và có thể chứa tham số.

Hướng dẫn này sẽ hướng dẫn bạn cách xác định các hàm tùy chỉnh.

Định nghĩa hàm

Đầu tiên, hãy thử chuyển đổi một chương trình đơn giản"Chào thế giới!" thành một hàm.

Tạo một cái mới tập tin văn bản hello.py rồi xác định hàm.

Để xác định hàm, sử dụng từ khóa def, sau đó chỉ định tên hàm và dấu ngoặc đơn có thể chứa tham số (nếu không có tham số thì dấu ngoặc đơn để trống), theo sau là dấu hai chấm.

Để xác định hàm hello(), hãy thêm phần sau vào tệp hello.py của bạn:

Đây là định nghĩa ban đầu của hàm.

chắc chắn xin chào():
print("Xin chào thế giới!")

Chức năng bây giờ đã được xác định. Nhưng nếu trên ở giai đoạn này chạy chương trình, sẽ không có gì xảy ra: để hàm hoạt động, nó không chỉ phải được xác định mà còn phải được gọi.

Sau khi xác định một hàm, hãy gọi nó:

chắc chắn xin chào():
print("Xin chào thế giới!")
Xin chào()

Bây giờ hãy chạy chương trình:

Nó sẽ trở lại:

Hàm hello() là một ví dụ khá đơn giản. Các hàm có thể phức tạp hơn nhiều, chứa các vòng lặp for, biểu thức điều kiện và các thành phần khác.

Khi hàm đạt đến câu lệnh return, nó sẽ dừng thực thi.

# Tệp return_loop.py
def loop_5():
cho x trong phạm vi (0, 25):
in(x)
nếu x == 5:
# Dừng hàm tại x == 5
trở lại
print("Dòng này sẽ không được thực thi.")
loop_5()

Tuyên bố trả lại trong vòng lặp for dừng thực thi hàm nên các dòng sau hàm sẽ không được thực thi. Nếu nó được sử dụng thay thế tuyên bố phá vỡ, chương trình sẽ ngừng thực thi vòng lặp chứ không phải hàm và câu lệnh print() cuối cùng sẽ được xử lý.

chức năng chính

TRONG Ngôn ngữ Python một hàm có thể được gọi ở cuối chương trình và nó sẽ chạy (như trong các ví dụ trước), tuy nhiên một số ngôn ngữ lập trình (chẳng hạn như C++ hoặc Java) yêu cầu hàm chính. Hàm main() trong Python là tùy chọn, nhưng nó cho phép bạn cấu trúc chương trình Python một cách logic và kết hợp các thành phần quan trọng nhất của nó thành một hàm duy nhất. Nó cũng làm cho các chương trình Python dễ đọc hơn đối với các lập trình viên làm việc bằng các ngôn ngữ khác.

Quay lại tệp hello.py và thêm hàm main(), trong khi vẫn giữ hàm hello().

chắc chắn xin chào():
print("Xin chào thế giới!")
chắc chắn chính():

Thêm câu lệnh print() vào hàm main(). Sau đó gọi hàm hello() bên trong hàm main().

chắc chắn xin chào():
print("Xin chào thế giới!")
chắc chắn chính():
print("Đây là chức năng chính")
Xin chào()

Ở cuối file, gọi hàm main().

chắc chắn xin chào():
print("Xin chào thế giới!")
chắc chắn chính():
print("Đây là chức năng chính.")
Xin chào()
chủ yếu()

Bây giờ bạn có thể chạy chương trình:

trăn xin chào.py
Đây là chức năng chính.
Chào thế giới!

Bây giờ hãy thử sử dụng một số chức năng.

Hàm trong lập trình là một đoạn mã riêng biệt có thể được gọi bằng cách gọi nó bằng tên mà nó được đặt tên. Khi được gọi, các lệnh của thân hàm sẽ được thực thi.

Các chức năng có thể được so sánh với các chương trình nhỏ không được thực thi độc lập, nghĩa là tự động mà được tích hợp vào chương trình thường xuyên. Chúng thường được gọi là chương trình con. Người khác sự khác biệt chính Không có chức năng từ các chương trình. Các hàm cũng có thể nhận và trả về dữ liệu khi cần thiết. Thông thường, họ nhận được chúng không phải từ đầu vào (bàn phím, tệp, v.v.), mà từ chương trình gọi điện. Đây là nơi họ trả lại kết quả công việc của mình.

Có rất nhiều chức năng được tích hợp trong ngôn ngữ lập trình. Chúng tôi đã gặp một số điều này trong Python. Đó là print(), input(), int(), float(), str(), type(). Chúng ta không thể nhìn thấy mã của cơ thể chúng, nó ở đâu đó “ẩn bên trong ngôn ngữ”. Chúng tôi chỉ được cung cấp một giao diện - tên của hàm.

Mặt khác, lập trình viên luôn có thể xác định các chức năng của riêng mình. Chúng được gọi là tùy chỉnh. TRONG trong trường hợp này Khi nói "người dùng", chúng tôi muốn nói đến lập trình viên chứ không phải người sử dụng chương trình. Hãy cùng tìm hiểu lý do tại sao chúng ta cần những hàm này và cách tạo ra chúng.

Giả sử bạn cần yêu cầu một cặp số ba lần liên tiếp và cộng chúng lại. Với mục đích này, bạn có thể sử dụng một vòng lặp:

tôi = 0 trong khi tôi< 3 : a = int (input () ) b = int (input () ) print (a+b) i += 1

Tuy nhiên, điều gì sẽ xảy ra nếu trước mỗi yêu cầu về số, bạn cần hiển thị một dòng chữ tại sao chúng lại cần thiết và mỗi lần dòng chữ này lại khác nhau. Chúng ta không thể phá vỡ một chu kỳ và sau đó quay lại cùng một chu kỳ. Bạn sẽ phải từ bỏ nó và rồi nó sẽ thành công mã dài, chứa trong Những nơi khác nhauà, các phần giống hệt nhau:

print () a = int (input () ) b = int (input() ) print ("Tổng", a+b, "cái." ) print () a = int (input() ) b = int (input () ) in ("Tổng", a+b, "chiếc." )

Ví dụ thực hiện chương trình:

Có bao nhiêu quả chuối và quả dứa cho khỉ? 15 5 Tổng cộng 20 chiếc. Có bao nhiêu con bọ và giun cho nhím? 50 12 Tổng cộng 62 chiếc. Có bao nhiêu cá và động vật có vỏ cho rái cá? 16 8 Tổng cộng 24 chiếc.

Việc giới thiệu các chức năng cho phép bạn giải quyết vấn đề sao chép mã ở các vị trí khác nhau của chương trình. Nhờ chúng, bạn có thể thực thi cùng một đoạn mã không phải ngay lập tức mà chỉ khi cần thiết.

Định nghĩa của một chức năng. toán tử def

Bằng ngôn ngữ Lập trình Python các hàm được xác định bằng câu lệnh def. Hãy nhìn vào mã:

def countFood() : a = int (input() ) b = int (input() ) print ("Tổng", a+b, "chiếc." )

Đây là một ví dụ về định nghĩa hàm. Giống như các hướng dẫn phức tạp khác như điều hành có điều kiện và vòng lặp, một hàm bao gồm phần đầu và phần thân. Tiêu đề kết thúc bằng dấu hai chấm và chuyển sang dòng mới. Cơ thể được thụt vào.

Từ khóa def cho trình thông dịch biết rằng đây là một định nghĩa hàm. def được theo sau bởi tên của hàm. Nó có thể là bất cứ thứ gì, giống như bất kỳ mã định danh nào, chẳng hạn như một biến. Trong lập trình, việc đặt cho mọi thứ những cái tên có ý nghĩa là rất cần thiết. Vì vậy, trong trường hợp này, hàm này được gọi là “countFood” được dịch sang tiếng Nga.

Tên hàm được theo sau bởi dấu ngoặc đơn. Trong ví dụ đã cho chúng trống. Điều này có nghĩa là hàm này không chấp nhận bất kỳ dữ liệu nào từ chương trình gọi nó. Tuy nhiên, nó có thể chấp nhận chúng và khi đó cái gọi là tham số sẽ được chỉ định trong ngoặc.

Theo sau dấu hai chấm là phần thân chứa các lệnh được thực thi khi hàm được gọi. Cần phải phân biệt giữa việc định nghĩa một hàm và gọi nó. TRONG Mã chương trình họ không gần gũi và không cùng nhau. Bạn có thể định nghĩa một hàm nhưng không bao giờ gọi nó. Bạn không thể gọi một hàm chưa được xác định. Nếu bạn xác định một hàm nhưng không bao giờ gọi nó, bạn sẽ không bao giờ thực thi phần thân của nó.

Gọi một hàm

Hãy xem xét phiên bản đầy đủ chương trình có chức năng:

def countFood() : a = int (input() ) b = int (input() ) print ("Tổng", a+b, "chiếc." ) print ( “Có bao nhiêu quả chuối và quả dứa cho lũ khỉ?”) countFood() in ( "Có bao nhiêu bọ và sâu cho nhím?") countFood() in ( "Có bao nhiêu cá và động vật có vỏ cho rái cá?") countFood()

Sau khi mỗi thông báo thông tin được hiển thị, một lệnh gọi hàm sẽ được thực hiện, hoạt động này đơn giản giống như nhắc đến tên của hàm đó trong dấu ngoặc đơn. Vì chúng ta không truyền bất cứ thứ gì vào hàm nên các dấu ngoặc lại trống. Trong đoạn mã trên, hàm được gọi ba lần.

Khi một hàm được gọi, luồng chương trình sẽ nhảy tới định nghĩa của nó và bắt đầu thực thi phần thân của nó. Sau khi phần thân hàm được thực thi, luồng thực thi sẽ quay trở lại mã chính tại nơi hàm được gọi. Tiếp theo, biểu thức theo sau lệnh gọi sẽ được thực thi.

Trong Python, định nghĩa hàm phải đặt trước lệnh gọi hàm. Điều này là do trình thông dịch đọc từng dòng mã và chưa biết hạ lưu là gì. Do đó, nếu một lệnh gọi hàm đứng trước định nghĩa của nó thì sẽ xảy ra lỗi (một ngoại lệ NameError được đưa ra):

in( “Có bao nhiêu quả chuối và quả dứa cho lũ khỉ?”) countFood() in ( "Có bao nhiêu bọ và sâu cho nhím?") countFood() in ( "Có bao nhiêu cá và động vật có vỏ cho rái cá?") countFood() def countFood() : a = int (input() ) b = int (input() ) print ("Tổng", a+b, "chiếc." )

Kết quả:

Có bao nhiêu quả chuối và quả dứa cho khỉ? TracBack (cuộc gọi gần đây nhất gần đây nhất ): Tệp "test.py" , dòng 2 , trong< module>countFood() NameError: tên "countFood" không được xác định

Đối với nhiều ngôn ngữ được biên dịch thì đây không phải là điều kiện bắt buộc. Ở đó bạn có thể định nghĩa và gọi một hàm ở những vị trí tùy ý trong chương trình. Tuy nhiên, để dễ đọc mã, ngay cả trong trường hợp này, các lập trình viên cũng thích tuân theo các quy tắc nhất định.

Các hàm cung cấp cấu trúc chương trình

Lợi ích của hàm không chỉ là khả năng gọi cùng một mã nhiều lần từ các vị trí khác nhau trong chương trình. Điều quan trọng không kém là chúng mang lại cấu trúc đúng cho chương trình. Các chức năng dường như chia nó thành các phần riêng biệt, mỗi phần thực hiện nhiệm vụ cụ thể của riêng mình.

Giả sử bạn cần viết một chương trình tính diện tích của các hình khác nhau. Người dùng cho biết diện tích của hình mình muốn tính. Sau đó, nhập dữ liệu ban đầu. Ví dụ: chiều dài và chiều rộng trong trường hợp hình chữ nhật. Để chia một luồng thực thi thành nhiều nhánh, bạn nên sử dụng câu lệnh if-elif-else:

figure = input () if figure == "1" : a = float (input ("Width: " ) ) b = float (input ("Height: " ) ) print ("Diện tích: %.2f" % (a* b) ) hình elif == "2" : a = float (đầu vào ("Cơ sở: " ) ) h = float (đầu vào ("Chiều cao: " ) ) print ("Diện tích: %.2f" % (0,5 * a * h) ) elif figure == "3" : r = float (input ("Bán kính: " ) ) print ("Diện tích: %.2f" % (3.14 * r**2 ) ) else : print ("Lỗi đầu vào" )

Không có chức năng nào ở đây và mọi thứ đều ổn. Nhưng hãy viết một phiên bản có chức năng:

def hình chữ nhật() : a = float (đầu vào ("Chiều rộng: " ) ) b = float (đầu vào ("Chiều cao: " ) ) print ("Diện tích: %.2f" % (a*b) ) def Triangle() : a = float (input ("Cơ sở: " ) ) h = float (đầu vào ("Chiều cao: " ) ) print ("Diện tích: %.2f" % (0.5 * a * h) ) def round() : r = float (đầu vào ("Bán kính: " ) ) print ("Diện tích: %.2f" % (3.14 * r**2 ) ) figure = input ( "1 hình chữ nhật, 2 hình tam giác, 3 hình tròn: ") if hình == "1" : hình chữ nhật() hình elif == "2" : hình tam giác() hình elif == "3" : hình tròn() else : in ("Lỗi đầu vào")

Nó có vẻ phức tạp hơn và mỗi hàm trong số ba hàm chỉ được gọi một lần. Tuy nhiên, từ logic chung của chương trình, các hướng dẫn tìm kiếm khu vực đã bị loại bỏ và cô lập. Chương trình hiện bao gồm các "gạch Lego" riêng lẻ. Ở nhánh chính chúng ta có thể kết hợp chúng theo ý muốn. Nó đóng vai trò của một cơ chế kiểm soát.

Nếu chúng ta muốn tính diện tích hình tam giác bằng công thức Heron thay vì chiều cao, chúng ta sẽ không phải tìm kiếm mã trong toàn bộ chương trình (hãy tưởng tượng nó có hàng nghìn dòng mã như chương trình thực tế). Chúng ta sẽ đi đến nơi xác định các hàm và thay đổi nội dung của một trong số chúng.

Nếu chúng ta cần sử dụng các hàm này trong một số chương trình khác, chúng ta có thể nhập chúng vào đó bằng cách tham khảo tập tin này bằng mã (cách thực hiện việc này bằng Python sẽ được thảo luận sau).

Công việc thực tế

Trong lập trình, bạn có thể gọi một hàm khác từ một hàm. Để minh họa khả năng này, hãy viết một chương trình với mô tả sau.

Nhánh chính của chương trình, không tính các tiêu đề hàm, bao gồm một dòng mã. Đây là lệnh gọi hàm test(). Nó yêu cầu một đầu vào số nguyên. Nếu nó là dương thì hàm dương () sẽ được gọi, phần thân của hàm này chứa lệnh hiển thị từ “Tích cực” trên màn hình. Nếu số âm thì hàm âm() sẽ được gọi, phần thân của nó chứa biểu thức để hiển thị từ "Âm".

Ngày 5 tháng 8 năm 2008 lúc 4:14 chiều

Khái niệm cơ bản về Python- Tóm tắt. Phần 5. Định nghĩa chức năng, cơ bản.

  • Python

Khi tôi bắt đầu viết chương về OOP, tôi nhận ra rằng tôi đã hoàn toàn quên đề cập đến một phần lớn và cần thiết của Python dưới dạng hàm. Chủ đề này có quy mô và phạm vi rộng nên để không kéo dài thời gian tạm dừng giữa các bài học quá nhiều, tôi quyết định chia thành 2 phần. Đầu tiên, tôi sẽ cho bạn biết những điều cơ bản, sau đó là các tính năng chuyên sâu về kỹ thuật hàm của Python.

Các hàm trong Python được khai báo không đơn giản mà rất đơn giản. Đây là một ví dụ về cách đơn giản nhất:

def trống_func(): vượt qua
Quảng cáo bắt đầu bằng từ khóa def, như bạn có thể đoán, là tên viết tắt của định nghĩa. Tiếp theo là tên của hàm. Sau cái tên trong dấu ngoặc đơn một danh sách các tham số được chỉ định bị thiếu trong trường hợp này.
Thân hàm được thụt lề bằng hàng tiếp theo. Xin lưu ý rằng các hàm có phần thân trống bị cấm trong Python, do đó, thẻ "toán tử trống" được sử dụng làm phần thân của hàm trên.
Bây giờ hãy xem một ví dụ nghiêm túc hơn.

Def safe_div(x, y): """Thực hiện phép chia an toàn:-) cho vui và kiếm lợi nhuận""" if y != 0: z = x / y print z return z else: print "Yippie-kay-yay, mẹ kiếp___er!"
Có một số đổi mới trong ví dụ này. Điều đầu tiên đập vào mắt bạn là dòng tài liệu (chuỗi tài liệu) nằm ngay sau phần thân hàm.
Thông thường dòng này chiếm nhiều hơn một dòng văn bản nguồn(xin lỗi vì chơi chữ) và do đó được chỉ định trong dấu ngoặc kép. Nó nhằm mục đích mô tả chức năng, mục đích, các tham số, v.v. Tất cả IDE tốt biết cách làm việc với dòng này. Bạn cũng có thể truy cập nó từ chính chương trình bằng cách sử dụng thuộc tính __doc__:

In safe_div.__doc__
Thuộc tính này (vâng, vâng, chính xác là một thuộc tính, trong Python, ngay cả các hàm cũng thực sự là các lớp) thuận tiện để sử dụng trong các phiên của bảng điều khiển tương tác.
>>> from ftplib import FTP >>> print FTP.__doc__ Một lớp máy khách FTP. Để tạo kết nối, hãy gọi lớp bằng cách sử dụng các đối số sau: máy chủ, người dùng, passwd, acct Đây đều là các chuỗi và có giá trị mặc định "". Sau đó sử dụng self.connect() với đối số cổng và máy chủ tùy chọn. # phần còn lại tôi làm :-)
Hãy quay trở lại chức năng ban đầu của chúng tôi. Bản chất của nó rất đơn giản, nó có 2 tham số: x và y. Nếu y khác 0, nó chia x cho y, in kết quả ra màn hình và trả về thương số của nó làm kết quả. Kết quả hàm được trả về bằng lệnh return. Nhờ cơ chế tuple được mô tả ở bài trước, các hàm trong Python có thể trả về nhiều đối tượng cùng một lúc.
Nếu số chia vẫn là bằng 0, hàm hiển thị thông báo lỗi. Sẽ là sai lầm nếu cho rằng trong trường hợp này hàm sẽ không trả về bất cứ thứ gì. Sẽ đúng hơn khi nói rằng hàm sẽ trả về “không có gì” :) Nói cách khác, nếu hàm không có câu lệnh return hoặc được gọi mà không có tham số thì hàm sẽ trả về Ý nghĩa đặc biệt Không có. Bạn có thể dễ dàng xác minh điều này bằng cách gọi một cái gì đó như print safe_div(10, 0).

Đây là một ví dụ phức tạp hơn một chút, được lấy từ báo cáo thuyết trình của Guido van Rossum.

Def gcd(a, b): "Tìm GCD" while a != 0: a,b = b%a,a # định nghĩa song song trả về b
Hàm này tìm ước chung lớn nhất của hai số.

Nói chung, hãy nhớ rằng các tham số trong hàm Python được truyền bằng tham chiếu. Một thực tế khác, có lẽ không tầm thường mà bạn sẽ phải làm quen là bản thân các hàm là một giá trị có thể được gán. Nếu sử dụng hàm safe_div cho các thử nghiệm tiếp theo, chúng ta có thể viết đoạn mã sau.

Mystic_function = safe_div in mystic_function(10, 4)
Lần này thế là xong, vẫn còn nhiều khía cạnh của việc xác định hàm trong Python còn “quá mức” sẽ được đề cập trong lần tới.

Bài tập để kiểm tra.
1. Dựa trên chức năng hiện cóđể tìm GCD, hãy viết hàm tìm BCNN của hai số.
2. Viết quy trình lập bảng cho hàm được truyền dưới dạng đối số. Các đối số cũng chỉ định ban đầu, giá trị cuối cùng và dừng tab.

Nhân tiện, độ dài tối ưu của một “bài học” là bao nhiêu? Điều gì tốt hơn - các chương lớn được xuất bản ít thường xuyên hơn hoặc “ít hơn là tốt hơn, thường xuyên hơn?”

Hàm được đặt tên, lệnh def

Hàm trong python là một đối tượng nhận đối số và trả về một giá trị. Thông thường, một hàm được xác định bằng câu lệnh def.

Hãy xác định hàm đơn giản nhất:

Câu lệnh return nói rằng trả về một giá trị. Trong trường hợp của chúng tôi, hàm trả về tổng của x và y.

Bây giờ chúng ta có thể gọi nó:

>>> cộng(1, 10)

>>> thêm ("abc", "def")

Hàm có thể có độ phức tạp bất kỳ và trả về bất kỳ đối tượng nào (danh sách, bộ dữ liệu và thậm chí cả hàm!):

>>> def newfunc(n):

Def myfunc(x):

Trả về x + n

Trả lại myfunc

>>> new = newfunc(100) # new là một hàm

>>> mới(200)

Hàm có thể không kết thúc bằng câu lệnh return, nhưng hàm sẽ trả về valueNone:

>>> def func():

>>> in(func())

Đối số hàm

Một hàm có thể nhận một số lượng đối số tùy ý hoặc không có đối số nào cả. Cũng phổ biến là các hàm có số lượng đối số tùy ý, các hàm có đối số vị trí và được đặt tên, bắt buộc và tùy chọn.

>>> def func(a, b, c=2): # c - đối số tùy chọn

Trả về a + b + c

>>> func(1, 2) # a = 1, b = 2, c = 2 (mặc định)

>>> func(1, 2, 3) # a = 1, b = 2, c = 3

>>> func(a=1, b=3) # a = 1, b = 3, c = 2

>>> func(a=3, c=6) # a = 3, c = 6, b không xác định

Traceback (cuộc gọi gần đây nhất):

Tệp "", dòng 1, trong

TypeError: func() nhận ít nhất 2 đối số (2 đối số đã cho)

Hàm cũng có thể nhận một số lượng đối số vị trí thay đổi, sau đó đặt dấu * trước tên:

>>> def func(*args):

>>> func(1, 2, 3, "abc")

(1, 2, 3, "abc")

>>> chức năng(1)

Như bạn có thể thấy trong ví dụ, args là một bộ gồm tất cả các đối số được truyền cho hàm và một biến có thể được xử lý theo cách tương tự như một bộ.

Hàm có thể lấy số lượng đối số được đặt tên tùy ý, sau đó đặt ** ở trước tên:

>>> def func(**kwargs):

Trả lại kwargs

>>> func(a=1, b=2, c=3)

("a": 1, "c": 3, "b": 2)

>>> func(a="python")

Trong biến kwargs, chúng ta lưu trữ một từ điển mà với nó, một lần nữa, chúng ta có thể làm bất cứ điều gì chúng ta muốn.

Hàm ẩn danh, hướng dẫn lambda

Hàm ẩn danh chỉ có thể chứa một biểu thức nhưng chúng cũng thực thi nhanh hơn. Các hàm ẩn danh được tạo bằng lệnh lambda. Ngoài ra, chúng không cần phải được gán cho một biến, như chúng ta đã làm với lệnh def func():

>>> func = lambda x, y: x + y

>>> hàm(1, 2)

>>> func("a", "b")

>>> (lambda x, y: x + y)(1, 2)

>>> (lambda x, y: x + y)("a", "b")

Hàm lambda, không giống như hàm thông thường, không yêu cầu lệnh trả về, nhưng mặt khác hoạt động giống hệt nhau:

>>> func = lambda *args: args

>>> hàm(1, 2, 3, 4)

19. Khái niệm đệ quy, triển khai trong Python

Trong lập trình, đệ quy là gọi một hàm (thủ tục) từ chính nó, trực tiếp (đệ quy đơn giản) hoặc thông qua các hàm khác (đệ quy phức tạp hoặc gián tiếp), ví dụ: một hàm gọi một hàm và một hàm gọi một hàm. Số lượng lệnh gọi lồng nhau đến một hàm hoặc thủ tục được gọi là độ sâu đệ quy.

Nói thì không thể đơn giản hơn được. Có một câu nói nổi tiếng về sự đệ quy:

Để hiểu đệ quy, trước tiên bạn phải hiểu đệ quy

Vì vậy, Python làm cho việc đệ quy trở nên dễ dàng và thoải mái. Ví dụ đầu tiên về đệ quy mà hầu hết các lập trình viên gặp phải là tìm giai thừa. Mã có thể như thế này:

giai thừa def (n):

nếu n<= 1: return 1

khác: trả về n * giai thừa (n - 1)

Như bạn có thể thấy, chúng tôi đã viết câu lệnh if else theo một cách hơi khác thường đối với Python, nhưng điều này được cho phép trong trường hợp này, do thực tế là khả năng đọc ở đây không bị suy giảm, nhưng phong cách này không nên bị lạm dụng. Và nói chung PEP8 sẽ phán xét mọi người. :)

Bây giờ hãy làm rõ một số tính năng quan trọng mà bạn phải luôn ghi nhớ khi làm việc với các phép đệ quy.

    Có một giới hạn về độ sâu của đệ quy. Theo mặc định là 1000.

    Để thay đổi giới hạn này, bạn cần gọi hàm sys.setrecursionlimit() và để xem giới hạn hiện tại, sys.getrecursionlimit().

    Mặc dù vậy, có một hạn chế về kích thước của ngăn xếp được cài đặt bởi hệ điều hành.

    Không thể sử dụng đệ quy trong Python trong các hàm tạo và coroutine. Tuy nhiên, bạn có thể sửa hành vi này nhưng tốt hơn hết là không nên làm vậy.

    Một điều cuối cùng - việc áp dụng các trình trang trí cho các hàm đệ quy có thể dẫn đến kết quả không mong muốn, vì vậy hãy hết sức cẩn thận khi trang trí các hàm đệ quy.

Ngoài ra, bạn phải luôn xác định điểm thoát khỏi các hàm đệ quy. Nó giống như các vòng lặp - một vòng lặp vô tận có thể thực sự lãng phí hệ điều hành của bạn. Và cuối cùng, sử dụng đệ quy ở đâu tốt hơn và ở đâu tốt hơn để kiềm chế và thực hiện, chẳng hạn như với các vòng lặp? Tất nhiên, ở đây có rất nhiều điều phụ thuộc vào nhiệm vụ, nhưng bạn nên luôn nhớ rằng đệ quy chậm hơn nhiều lần so với vòng lặp. Python được thiết kế theo cách mà việc gọi một hàm sẽ khiến bạn tốn rất nhiều chi phí :) Nói chung, bạn không nên gọi các hàm theo vòng lặp, càng không nên gọi các hàm đệ quy.

Đệ quy rất phù hợp khi hiệu suất không quá quan trọng nhưng khả năng đọc và bảo trì mã lại quan trọng hơn. Ví dụ: viết hai hàm để duyệt cây thư mục, một hàm đệ quy và một hàm có vòng lặp.

Điều hướng nhanh:
1.31 Danh sách - mảng. Buổi gặp gỡ đầu tiên. 1.30 Hàm trả về kết quả - return 1.29 Chương trình con: hàm và thủ tục trong Python 1.28 Chuyển đổi kiểu dữ liệu - int() 1.27 Nhập dữ liệu từ bàn phím - input() 1.26 Kiểu và kích thước dữ liệu 1.25 Vòng lặp với điều kiện tiên quyết - while. Số Fibonacci 1.24 Đo độ dài của một dòng, liệt kê 1.23 Cắt dòng - xuất ra một số ký tự nhất định từ văn bản hiện có 1.22 Chuỗi và ký tự điều khiển 1.21 Lỗi hệ thống trong quá trình gỡ lỗi chương trình 1.20 Toán tử phân nhánh - if, chú thích 1.19 In - print(), nhập dữ liệu nhanh, làm tròn, nhận xét 1.18 Các kiểu lập trình. Phần 2. Lập trình hướng đối tượng 1.17 Các kiểu lập trình. Phần 1. Lập trình có cấu trúc. Vòng lặp 1.16 Biểu diễn thông tin ký hiệu - ASCII 1.15 Phép chia số nhị phân 1.14 Các phép toán với số nhị phân 1.13 Thông tin được lưu trữ và ghi lại như thế nào. Bit và byte 1.12 Chuyển đổi số nguyên từ hệ thập phân sang hệ khác 1.11 Chuyển đổi số nguyên từ hệ thập lục phân sang thập phân 1.10 Chuyển đổi số nhị phân nguyên sang hệ thập lục phân 1.9 Chuyển đổi số nhị phân nguyên sang hệ số khác 1.8 Hệ thống số 1.7 Đại số Boolean. Biểu thức logic 1.6 Các khái niệm cơ bản. Phần 3 - Số, biểu thức, toán hạng, dấu phép tính 1.5 Các khái niệm cơ bản. Phần 2 - Chương trình, dữ liệu 1.4 Các khái niệm cơ bản. Phần 1 - Bài toán và thuật toán 1.3 Môi trường phát triển SI 1.2 Lịch sử các ngôn ngữ lập trình 1.1 Giới thiệu

Khi viết chương trình bằng bất kỳ ngôn ngữ lập trình nào, bạn phải cố gắng viết mã nhỏ gọn để có thể dễ dàng điều hướng chính mã đó.
Điều này xảy ra là không thể triển khai mã của bạn theo cách này và thông thường, mã chương trình trông giống như một cuộn tài liệu cổ dài vô tận chiếm 10 - 15 màn hình theo chiều dọc...
Tất nhiên, việc hiểu một chương trình như vậy có thể cực kỳ khó khăn đối với tác giả của một sáng tạo như vậy.

Trong trường hợp này, người lập trình có thể hỗ trợ việc chia mã chương trình thành chương trình con.

chương trình con- đây là một loại chương trình hoàn chỉnh, nhưng không độc lập.
Nó được gọi từ một số chương trình cấp cao hơn chỉ để thực hiện một hoặc một hành động khác.

Điều này trông như thế nào trong thực tế?

Ví dụ: trong một số chương trình rất lớn mà bạn cần tạo ra (chúng tôi đã xem xét thuật toán hoạt động của nó).
Và thay vì viết mã để tính các số Fibonacci trong mã chương trình lớn này mỗi lần, chúng tôi chỉ cần đặt nó vào một tệp riêng. Đây sẽ là chương trình con.
Sau đó, ở nơi cần thực hiện phép tính cần thiết của những con số này, chúng tôi chỉ chèn một số dấu hiệu cho thấy chương trình con của chúng tôi nên được gọi tại nơi này.

Trong trường hợp này, mã chương trình sẽ giảm đáng kể về khối lượng và sẽ dễ hiểu hoạt động của chương trình hơn nhiều.

Trong các ngôn ngữ lập trình khác nhau, các chương trình con như vậy được gọi là:

Thủ tục hoặc
- chức năng

Trong ngôn ngữ SI, các chương trình con như vậy được gọi là hàm.

Nhân tiện, chúng tôi đã sử dụng các chức năng này trong thực tế!
Ví dụ: chúng tôi đã sử dụng các hàm BUILT-IN trong trình thông dịch:

Print() - để in dữ liệu của các tham số nhất định được đặt trong dấu ngoặc đơn
- str() - để chuyển đổi dữ liệu sang kiểu chuỗi. Đây là những gì hàm print() chạy trước.
- int() - để chuyển đổi dữ liệu thành số nguyên
- float() - để chuyển đổi số nguyên thành kiểu phân số
- round() - để làm tròn một giá trị nhất định
và như thế.


Vì thế.
Để gọi một hàm, chỉ cần nhập tên của nó và liệt kê trong ngoặc đơn các tham số (đối số) bắt buộc mà chúng ta muốn truyền cho hàm này.

Nhưng sẽ hoàn toàn không thú vị nếu chúng ta không có cơ hội tạo ra những chức năng của riêng mình để thực hiện một số nhiệm vụ nhất định.
Còn với Python, nó có toán tử định nghĩa hàm đặc biệt với cú pháp như sau:

định nghĩa FUNCTION_NAME(PARAMETER_LIST):
Trình tự biểu thức

Tên hàm phải được chọn giống như tên biến - theo cùng một quy tắc: tên phải bắt đầu bằng một chữ cái Latinh.
- Danh sách các tham số chứa các giá trị nhất định được truyền vào hàm. Các tham số này được liệt kê cách nhau bằng dấu phẩy.

Trong Python, để định nghĩa một hàm, tham số đầu tiên là một từ hàm chắc chắn(tiêu đề hàm) (từ định nghĩa- định nghĩa) - với điều này, chúng tôi chỉ ra rằng chúng tôi sẽ gọi hàm.
Tiêu đề hàm sau dấu ngoặc đơn đóng kết thúc bằng dấu hai chấm (trong Python) và theo sau là các biểu thức cần thiết bắt đầu ở vị trí lệch so với đầu dòng (thường sử dụng phím TAB).

Quay trở lại việc tính các số Fibonacci, chúng ta hãy sử dụng ví dụ của anh ấy để xem xét cách hoạt động của lệnh gọi hàm.
Chúng tôi sẽ thực hiện một tùy chọn khác để tính các số Fibonacci mà trước đây chúng tôi chưa xem xét.
Nó dựa trên việc gán giá trị song song cho các biến.

Def fib(n): a, b = 0, 1 while a< n: print(a, end = " ") a, b = b, a + b print()

Nói tóm lại, dòng:
a, b = 0, 1
có nghĩa là (nhưng không hoàn toàn tương đương với):
a = 0 b = 1

Và dòng
a, b = b, a + b
có nghĩa là mục:
a = b b = a + b

Chúng ta hãy xem từng dòng mã:

1
def fib(n):
- định nghĩa ( chắc chắn) hàm theo tên bịa đặt với các tham số (đối số) được chỉ định trong ngoặc đơn mà chúng tôi muốn chuyển cho chính hàm này theo tên bịa đặt.
Những thứ kia. như một tham số N chúng tôi sẽ chuyển giá trị mà phép tính sẽ được thực hiện. Con số này sẽ được chuyển đến hàm của chúng ta dưới dạng đối số.

Sau dấu hai chấm, đầu vào được thụt vào trong trình thông dịch Python. Điều này cho thấy rằng dữ liệu này có liên quan trực tiếp đến chức năng này.

2
a, b = 0, 1
Chúng ta khởi tạo các biến với các giá trị thích hợp:
a = 0 b = 1

3
trong khi một< n:
Toán tử vòng lặp trong khi- sẽ được thực hiện miễn là điều kiện vòng lặp được đáp ứng Một
Ở đây, sau dấu hai chấm, một khối mới được mở chỉ liên quan TRỰC TIẾP đến chu trình.
Khối này sẽ được in sau nguồn cấp dữ liệu với sự thụt lề bổ sung.

4
in(a, end = "")
Chúng ta in dữ liệu của biến a và một khoảng trắng sau mỗi lần lặp của vòng lặp

5
a, b = b, a + b
Chúng ta gán giá trị thích hợp cho các biến:
a = b b = a + b
Để thay đổi dữ liệu ban đầu và tiếp tục công việc tính số Fibonacci

6
in()

Xin lưu ý rằng điều này in() cần in dưới trong khi... I E. nó không còn thuộc về phần thân của vòng lặp nữa trong khi, và vào phần thân của hàm bịa đặt
Tuy nhiên, tại sao chúng ta cần cái thứ hai? in() và thậm chí với dấu ngoặc trống?

Trong trường hợp này, đây là đầu ra của một dòng trống - thực hiện "ngắt" - ngắt dòng. Hay đúng hơn, hàm này in ký tự nguồn cấp dòng.
Trong trường hợp của chúng tôi, chúng tôi không phải sử dụng nó.

Vì vậy chúng tôi đã xác định hàm bịa đặtđể tính các số Fibonacci và như bạn đã thấy, nó không hoạt động.

Để nó hoạt động, bạn cần GỌI nó và truyền cho nó một tham số nhất định để tính toán.
Chúng tôi gọi hàm của mình và truyền giá trị làm đối số 40 .
Kết quả là chúng ta sẽ có được phép tính các số Fibonacci cho tất cả các số lên đến 40 :

Chúng tôi in bằng trình thông dịch Python:
xơ (40)
Chúng tôi nhận được:

0 1 1 2 3 5 8 13 21 34

Bạn có thể gọi lại hàm xơ() với một tham số khác và nhận được cùng một đầu ra của dữ liệu cần thiết.
Ví dụ: hãy nhập
xơ (400)
Và chúng tôi nhận được:

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Vì vậy, hàm của chúng ta có thể được chạy theo số lần yêu cầu.

Trong nhiều ngôn ngữ lập trình, thủ tục và hàm không đồng nghĩa và có sự khác biệt với nhau.
Chúng khác nhau như thế nào trong các ngôn ngữ lập trình như vậy?

Hàm - trả về giá trị
- Thủ tục - không trả về giá trị

Hãy giải thích bằng một ví dụ:


Nếu chúng ta có thể sử dụng ký hiệu như thế này (chỉ để làm ví dụ):
x = sợi(n)- thì đây là một hàm, nó gán giá trị kết quả cho một biến x(trong trường hợp này, sẽ không có gì được ghi vào biến x)

Nếu chỉ có thể ghi âm xơ (n)- thì đây là một thủ tục.

Vì vậy, chúng ta có thể nói rằng ví dụ của chúng ta là một THỦ TỤC.

Chúng ta sẽ xem xét cách sử dụng mã của chúng tôi bằng Python để tính các số Fibonacci dưới dạng hàm sau này...