Con người khá hạn chế về khả năng lưu giữ các mẩu thông tin riêng biệt trong bộ nhớ làm việc của họ. Nghiên cứu cho thấy rằng đối với hầu hết mọi người, số khối không liên quan là khoảng bảy. Ngược lại, máy tính không gặp khó khăn gì trong việc quản lý hàng nghìn mẩu thông tin riêng biệt mà không bao giờ quên hoặc nhầm lẫn chúng.
Ghi chú
Xem The Magical Number Seven, Plus or Minus Two để biết thêm về chủ đề hấp dẫn này
Để con người [lập trình viên] có thể viết các chương trình phức tạp có thể kéo dài hàng nghìn dòng mã, ngôn ngữ lập trình có các tính năng cho phép lập trình viên sử dụng sức mạnh trừu tượng để đặt tên cho một chuỗi hướng dẫn và sau đó sử dụng lệnh mới.
Chương này thảo luận về các hàm, một trong những tính năng ngôn ngữ của Python hỗ trợ loại trừu tượng này
5. 1. Định nghĩa và sử dụng hàm¶
Trong ngữ cảnh lập trình, một hàm là một chuỗi các câu lệnh được đặt tên thực hiện một thao tác mong muốn. Hoạt động này được chỉ định trong một định nghĩa chức năng. Trong Python, cú pháp cho một định nghĩa hàm là
def NAME[ LIST OF PARAMETERS ]: STATEMENTS
Bạn có thể tạo bất kỳ tên nào bạn muốn cho các chức năng bạn tạo, ngoại trừ việc bạn không thể sử dụng tên là từ khóa Python. Danh sách các tham số chỉ định thông tin nào, nếu có, bạn phải cung cấp để sử dụng chức năng mới
Có thể có bất kỳ số lượng câu lệnh nào bên trong hàm, nhưng chúng phải được thụt vào từ
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None2
Định nghĩa hàm là các câu lệnh ghép, tương tự như các câu lệnh rẽ nhánh và lặp mà chúng ta đã thấy trong chương Điều kiện và vòng lặp , có nghĩa là chúng có .
Tiêu đề bắt đầu bằng từ khóa và kết thúc bằng dấu hai chấm
Nội dung bao gồm một hoặc nhiều câu lệnh Python, mỗi câu lệnh được thụt vào cùng một lượng [4 dấu cách là tiêu chuẩn của Python] từ tiêu đề
Trong một định nghĩa hàm, từ khóa trong tiêu đề là
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None2, theo sau là tên của hàm và danh sách các tham số được đặt trong ngoặc đơn. Danh sách tham số có thể trống hoặc có thể chứa bất kỳ số lượng tham số nào. Trong cả hai trường hợp, dấu ngoặc đơn là bắt buộc
5. 2. Dựa trên những gì bạn đã học ở trường trung học Đại số¶
Quay trở lại lớp Đại số ở trường trung học, bạn đã được giới thiệu về các hàm toán học. Có lẽ bạn đã được xem sơ đồ của một “máy chức năng” trông giống như thế này
Ý tưởng đằng sau sơ đồ này là một chức năng giống như một cỗ máy nhận đầu vào,
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None4 và biến nó thành đầu ra,
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None5. Hộp màu vàng nhạt
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None6 là một bản tóm tắt của quy trình được sử dụng để thực hiện chuyển đổi từ
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None4 sang
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None5
Các hàm trong Python có thể được hiểu theo cùng một cách và sự tương đồng với các hàm trong Đại số có thể giúp bạn hiểu chúng
Hàm bậc hai sau đây là một ví dụ
f[x] = 3x 2 - 2x + 5
Đây là chức năng tương tự trong Python
________số 8
Xác định chức năng mới không làm cho chức năng chạy. Để làm điều đó, chúng ta cần một lời gọi hàm. Các lệnh gọi hàm chứa tên của hàm đang được thực thi, theo sau là danh sách các giá trị, được gọi là đối số, được gán cho các tham số trong định nghĩa hàm
Đây là chức năng của chúng tôi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None6 được gọi với một số đối số khác nhau
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None0
Định nghĩa hàm trước tiên phải được nhập vào trình bao Python trước khi nó có thể được gọi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None1
Các lệnh gọi hàm liên quan đến việc gán ngầm đối số cho tham số
Mối quan hệ giữa tham số và đối số trong định nghĩa và cách gọi hàm là mối quan hệ của phép gán ngầm định. Như thể chúng ta đã thực hiện các câu lệnh gán lần lượt là
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None20,
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None21,
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None22,
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None23 và
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None24 trước khi gọi hàm tới
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None6 trong ví dụ trước
5. 3. Câu lệnh >>> def mystery[]:
.. return
...
>>> what_is_it = mystery[]
>>> what_is_it
>>> type[what_is_it]
>>> print[what_is_it]
None
26¶
Câu lệnh return khiến một hàm dừng ngay lập tức việc thực thi các câu lệnh trong thân hàm và gửi lại [hoặc trả về] giá trị sau từ khóa
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None26 cho câu lệnh gọi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None0
Một câu lệnh return không có giá trị sau khi nó vẫn trả về một giá trị, thuộc loại mà chúng ta chưa từng thấy trước đây
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None28 là giá trị duy nhất của
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None29 của Python. Chúng tôi sẽ sử dụng nó thường xuyên sau này để biểu thị một giá trị không xác định hoặc chưa được gán. Hiện tại, bạn cần lưu ý rằng đó là giá trị được trả về bởi câu lệnh
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None26 mà không có đối số
Tất cả các lệnh gọi hàm Python đều trả về một giá trị. Nếu lệnh gọi hàm kết thúc việc thực thi các câu lệnh trong phần thân của nó mà không nhấn vào câu lệnh
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None26, thì hàm sẽ trả về giá trị
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None28
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None2
Vì
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None83 không có câu lệnh trả về với giá trị, nên nó trả về giá trị
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None28, giá trị này được gán cho
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None85. Các giá trị
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None28 không hiển thị trong trình bao Python trừ khi chúng được in rõ ràng
Bất kỳ câu lệnh nào trong phần thân của hàm sau khi gặp câu lệnh
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None26 sẽ không bao giờ được thực thi và được gọi là mã chết
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None8
5. 4. Luồng thực thi¶
Để đảm bảo rằng một hàm được xác định trước lần sử dụng đầu tiên, bạn phải biết thứ tự các câu lệnh được thực thi, được gọi là luồng thực thi
Việc thực thi luôn bắt đầu ở câu lệnh đầu tiên của chương trình. Các câu lệnh được thực thi lần lượt theo thứ tự từ trên xuống dưới
Các định nghĩa hàm không làm thay đổi luồng thực thi của chương trình, nhưng hãy nhớ rằng các câu lệnh bên trong hàm không được thực thi cho đến khi hàm được gọi
Các lời gọi hàm giống như một đường vòng trong luồng thực thi. Thay vì chuyển sang câu lệnh tiếp theo, luồng sẽ nhảy đến dòng đầu tiên của hàm được gọi, thực hiện tất cả các câu lệnh ở đó, rồi quay lại tiếp tục từ nơi nó dừng lại
Điều đó nghe có vẻ đơn giản, cho đến khi bạn nhớ rằng một chức năng có thể gọi một chức năng khác. Khi đang ở giữa một hàm, chương trình có thể phải thực hiện các câu lệnh trong một hàm khác. Nhưng trong khi thực hiện chức năng mới đó, chương trình có thể phải thực hiện thêm một chức năng khác
May mắn thay, Python rất giỏi trong việc theo dõi vị trí của nó, vì vậy mỗi khi một chức năng hoàn thành, chương trình sẽ tiếp tục từ nơi nó đã dừng lại trong chức năng đã gọi nó. Khi đến cuối chương trình, nó kết thúc
Đạo đức của câu chuyện bẩn thỉu này là gì? . Thay vào đó, hãy làm theo quy trình thực hiện. Nhìn vào chương trình này
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None4
Đầu ra của chương trình này là
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None5
Theo dõi quy trình thực thi và xem liệu bạn có thể hiểu tại sao nó lại làm như vậy không
5. 5. Đóng gói và khái quát hóa¶
Đóng gói là quá trình gói một đoạn mã trong một hàm, cho phép bạn tận dụng tất cả những thứ mà hàm tốt cho
Tổng quát hóa có nghĩa là lấy một cái gì đó cụ thể, chẳng hạn như đếm số chữ số trong một số nguyên dương nhất định và làm cho nó trở nên tổng quát hơn, chẳng hạn như đếm số chữ số của bất kỳ số nguyên nào
Để xem quy trình này hoạt động như thế nào, hãy bắt đầu với một chương trình đếm số chữ số trong số
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None88
def f[x]: return 3 * x ** 2 - 2 * x + 50
Áp dụng những gì bạn đã học trong Truy tìm chương trình cho đến khi bạn cảm thấy tự tin rằng mình hiểu cách thức hoạt động của chương trình. Chương trình này thể hiện một mẫu tính toán quan trọng được gọi là bộ đếm. Biến
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None89 được khởi tạo bằng 0 và sau đó tăng dần mỗi khi thân vòng lặp được thực thi. Khi thoát khỏi vòng lặp,
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None89 chứa kết quả — tổng số lần phần thân vòng lặp được thực thi, bằng với số lượng chữ số.
Bước đầu tiên trong việc đóng gói logic này là gói nó trong một hàm
def f[x]: return 3 * x ** 2 - 2 * x + 51
Chạy chương trình này sẽ cho chúng ta kết quả như trước, nhưng lần này chúng ta đang gọi một hàm. Có vẻ như chúng tôi không thu được gì khi làm điều này, vì chương trình của chúng tôi dài hơn trước và thực hiện cùng một việc, nhưng bước tiếp theo sẽ tiết lộ điều gì đó mạnh mẽ
def f[x]: return 3 * x ** 2 - 2 * x + 52
Bằng cách tham số hóa giá trị, giờ đây chúng ta có thể sử dụng logic của mình để đếm các chữ số của bất kỳ số nguyên dương nào. Một cuộc gọi đến
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None41 sẽ in ra
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None42. Một cuộc gọi đến
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None43 sẽ in ra
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None44, v.v.
Chức năng này cũng có lỗi. Nếu chúng ta gọi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None45, nó sẽ trả về một
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None46, khi đó nó sẽ trả về một
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None47. Nếu chúng ta gọi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None48, chương trình sẽ đi vào một vòng lặp vô hạn. Bạn sẽ được yêu cầu sửa cả hai lỗi này như một bài tập
5. 6. Thành phần¶
Cũng giống như các hàm toán học, các hàm Python có thể được tổng hợp, nghĩa là bạn sử dụng kết quả của một hàm làm đầu vào cho một hàm khác
def f[x]: return 3 * x ** 2 - 2 * x + 53
Chúng ta cũng có thể sử dụng một biến làm đối số
def f[x]: return 3 * x ** 2 - 2 * x + 54
Chú ý một cái gì đó rất quan trọng ở đây. Tên của biến mà chúng ta chuyển vào làm đối số [
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None49] không liên quan gì đến tên của tham số [
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None4]. Một lần nữa, như thể
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None51 được thực thi khi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None52 được gọi. Không quan trọng giá trị được đặt tên trong trình gọi là gì, bên trong
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None6 và
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None54, tên của nó là
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None4
5. 7. Hàm cũng là dữ liệu¶
Các hàm bạn định nghĩa trong Python là một loại dữ liệu
def f[x]: return 3 * x ** 2 - 2 * x + 55
Giá trị của hàm có thể là thành phần của danh sách. Giả sử
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None6,
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None54 và
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None58 đã được định nghĩa như trong phần Thành phần ở trên.
def f[x]: return 3 * x ** 2 - 2 * x + 56
Như thường lệ, bạn nên theo dõi quá trình thực hiện ví dụ này cho đến khi bạn cảm thấy tự tin rằng mình hiểu cách thức hoạt động của nó
5. 8. Liệt kê tham số¶
Truyền danh sách dưới dạng đối số thực sự chuyển tham chiếu đến danh sách, không phải bản sao của danh sách. Vì danh sách là những thay đổi có thể thay đổi được thực hiện đối với tham số nên đối số cũng thay đổi. Ví dụ: hàm bên dưới lấy một danh sách làm đối số và nhân mỗi phần tử trong danh sách với 2
def f[x]: return 3 * x ** 2 - 2 * x + 57
Để kiểm tra chức năng này, chúng tôi sẽ đặt nó vào một tệp có tên
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None59 và nhập nó vào trình bao Python của chúng tôi, chúng tôi có thể thử nghiệm với nó không
def f[x]: return 3 * x ** 2 - 2 * x + 58
Ghi chú
Tệp chứa mã đã nhập phải có phần mở rộng tệp
def f[x]: return 3 * x ** 2 - 2 * x + 500, phần mở rộng này không được ghi trong câu lệnh nhập
Tham số
def f[x]: return 3 * x ** 2 - 2 * x + 501 và biến
def f[x]: return 3 * x ** 2 - 2 * x + 502 là bí danh cho cùng một đối tượng. Sơ đồ trạng thái trông như thế này
Vì đối tượng danh sách được chia sẻ bởi hai khung, chúng tôi đã vẽ nó giữa chúng
Nếu một chức năng sửa đổi một tham số danh sách, người gọi sẽ thấy sự thay đổi
5. 9. Hàm thuần túy và công cụ sửa đổi¶
Các hàm lấy danh sách làm đối số và thay đổi chúng trong quá trình thực thi được gọi là công cụ sửa đổi và những thay đổi mà chúng tạo ra được gọi là tác dụng phụ
Một chức năng thuần túy không tạo ra tác dụng phụ. Nó chỉ giao tiếp với chương trình gọi thông qua các tham số mà nó không sửa đổi và giá trị trả về. Đây là
def f[x]: return 3 * x ** 2 - 2 * x + 503 được viết dưới dạng một hàm thuần túy
def f[x]: return 3 * x ** 2 - 2 * x + 59
Phiên bản này của
def f[x]: return 3 * x ** 2 - 2 * x + 504 không thay đổi đối số của nó
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None00
Để sử dụng phiên bản hàm thuần túy của
def f[x]: return 3 * x ** 2 - 2 * x + 504 để sửa đổi
def f[x]: return 3 * x ** 2 - 2 * x + 502, bạn sẽ gán lại giá trị trả về cho
def f[x]: return 3 * x ** 2 - 2 * x + 502
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None01
5. 10. Cái nào tốt hơn?¶
Bất cứ điều gì có thể được thực hiện với công cụ sửa đổi cũng có thể được thực hiện với các hàm thuần túy. Trên thực tế, một số ngôn ngữ lập trình chỉ cho phép các hàm thuần túy. Có một số bằng chứng cho thấy các chương trình sử dụng các hàm thuần túy sẽ phát triển nhanh hơn và ít bị lỗi hơn các chương trình sử dụng các công cụ sửa đổi. Tuy nhiên, công cụ sửa đổi đôi khi thuận tiện và trong một số trường hợp, các chương trình chức năng kém hiệu quả hơn
Nói chung, chúng tôi khuyên bạn nên viết các hàm thuần túy bất cứ khi nào thấy hợp lý và chỉ sử dụng các công cụ sửa đổi nếu có lợi thế thuyết phục. Cách tiếp cận này có thể được gọi là phong cách lập trình chức năng
5. 11. Đa hình và gõ vịt¶
Khả năng gọi cùng một chức năng với các loại dữ liệu khác nhau được gọi là đa hình. Trong Python, việc triển khai tính đa hình rất dễ dàng, vì các hàm Python xử lý các loại thông qua kiểu gõ vịt. Về cơ bản, điều này có nghĩa là miễn là tất cả các hoạt động trên một tham số chức năng là hợp lệ, chức năng sẽ xử lý cuộc gọi chức năng mà không có khiếu nại. Ví dụ đơn giản sau minh họa khái niệm
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None02
Vì
def f[x]: return 3 * x ** 2 - 2 * x + 508 được xác định cho số nguyên, chuỗi, danh sách, số float và bộ dữ liệu, nên việc gọi hàm
def f[x]: return 3 * x ** 2 - 2 * x + 509 của chúng tôi với bất kỳ loại nào trong số này làm đối số không phải là vấn đề. Tuy nhiên,
def f[x]: return 3 * x ** 2 - 2 * x + 508 không được xác định cho Không có loại, do đó, việc gửi hàm
def f[x]: return 3 * x ** 2 - 2 * x + 509 một giá trị
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None28 dẫn đến lỗi thời gian chạy
5. 12. Bảng hai chiều¶
Bảng hai chiều là bảng mà bạn đọc giá trị tại giao điểm của một hàng và một cột. Bảng cửu chương là một ví dụ điển hình. Giả sử bạn muốn in bảng cửu chương cho các giá trị từ 1 đến 6
Một cách hay để bắt đầu là viết một vòng lặp in bội số của 2, tất cả trên một dòng
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None03
Ở đây, chúng tôi đã sử dụng hàm
def f[x]: return 3 * x ** 2 - 2 * x + 513, nhưng làm cho nó bắt đầu chuỗi từ 1. Khi vòng lặp thực thi, giá trị của
def f[x]: return 3 * x ** 2 - 2 * x + 514 thay đổi từ 1 thành 6. Khi tất cả các phần tử của phạm vi đã được gán cho
def f[x]: return 3 * x ** 2 - 2 * x + 514, vòng lặp kết thúc. Mỗi lần qua vòng lặp, nó sẽ hiển thị giá trị của
def f[x]: return 3 * x ** 2 - 2 * x + 516, theo sau là ba dấu cách
Một lần nữa, đối số
def f[x]: return 3 * x ** 2 - 2 * x + 517 bổ sung trong hàm
def f[x]: return 3 * x ** 2 - 2 * x + 518 sẽ chặn dòng mới và thay vào đó sử dụng ba dấu cách. Sau khi vòng lặp hoàn thành, lệnh gọi tới
def f[x]: return 3 * x ** 2 - 2 * x + 518 ở dòng 3 kết thúc dòng hiện tại và bắt đầu một dòng mới
Đầu ra của chương trình là
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None04
Càng xa càng tốt. Bước tiếp theo là tóm tắt và khái quát hóa
5. 13. Đóng gói nhiều hơn¶
Hàm này đóng gói vòng lặp trước đó và khái quát hóa nó để in bội số của
def f[x]: return 3 * x ** 2 - 2 * x + 520
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None05
Để đóng gói, tất cả những gì chúng ta phải làm là thêm dòng đầu tiên khai báo tên của hàm và danh sách tham số. Để khái quát hóa, tất cả những gì chúng ta phải làm là thay thế giá trị 2 bằng tham số
def f[x]: return 3 * x ** 2 - 2 * x + 520
Nếu chúng ta gọi hàm này với đối số 2, chúng ta sẽ nhận được kết quả giống như trước đây. Với đối số 3, đầu ra là
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None06
Với đối số 4, đầu ra là
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None07
Bây giờ bạn có thể đoán cách in bảng cửu chương — bằng cách gọi liên tục
def f[x]: return 3 * x ** 2 - 2 * x + 522 với các đối số khác nhau. Trong thực tế, chúng ta có thể sử dụng một vòng lặp khác
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None08
Lưu ý vòng lặp này tương tự như thế nào với vòng lặp bên trong
def f[x]: return 3 * x ** 2 - 2 * x + 522. Tất cả những gì chúng tôi đã làm là thay thế hàm
def f[x]: return 3 * x ** 2 - 2 * x + 518 bằng một lệnh gọi hàm
Đầu ra của chương trình này là một bảng cửu chương
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None09
5. 14. Vẫn đóng gói nhiều hơn¶
Để chứng minh tính đóng gói một lần nữa, hãy lấy mã từ phần trước và gói nó trong một hàm
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None10
Quá trình này là một kế hoạch phát triển chung. Chúng tôi phát triển mã bằng cách viết các dòng mã bên ngoài bất kỳ chức năng nào hoặc nhập chúng vào trình thông dịch. Khi chúng tôi làm cho mã hoạt động, chúng tôi giải nén nó và gói nó trong một hàm
Kế hoạch phát triển này đặc biệt hữu ích nếu bạn không biết cách chia chương trình thành các chức năng khi bắt đầu viết. Cách tiếp cận này cho phép bạn thiết kế khi bạn thực hiện
5. 15. Biến cục bộ¶
Bạn có thể thắc mắc làm thế nào chúng ta có thể sử dụng cùng một biến,
def f[x]: return 3 * x ** 2 - 2 * x + 514, trong cả
def f[x]: return 3 * x ** 2 - 2 * x + 522 và
def f[x]: return 3 * x ** 2 - 2 * x + 527. Nó không gây ra vấn đề khi một trong các hàm thay đổi giá trị của biến?
Câu trả lời là không, vì
def f[x]: return 3 * x ** 2 - 2 * x + 514 trong
def f[x]: return 3 * x ** 2 - 2 * x + 522 và
def f[x]: return 3 * x ** 2 - 2 * x + 514 trong
def f[x]: return 3 * x ** 2 - 2 * x + 527 không phải là cùng một biến
Các biến được tạo bên trong một định nghĩa hàm là cục bộ; . Điều đó có nghĩa là bạn có thể tự do đặt nhiều biến có cùng tên miễn là chúng không cùng chức năng
Python kiểm tra tất cả các câu lệnh trong một hàm — nếu bất kỳ câu lệnh nào trong số chúng gán giá trị cho một biến, thì đó là manh mối mà Python sử dụng để biến biến đó thành biến cục bộ
Sơ đồ ngăn xếp cho chương trình này cho thấy hai biến có tên
def f[x]: return 3 * x ** 2 - 2 * x + 514 không phải là cùng một biến. Chúng có thể đề cập đến các giá trị khác nhau và việc thay đổi giá trị này không ảnh hưởng đến giá trị kia
Giá trị của
def f[x]: return 3 * x ** 2 - 2 * x + 514 trong
def f[x]: return 3 * x ** 2 - 2 * x + 527 đi từ 1 đến 6. Trong sơ đồ, nó xảy ra là 3. Lần tiếp theo qua vòng lặp, nó sẽ là 4. Mỗi lần qua vòng lặp,
def f[x]: return 3 * x ** 2 - 2 * x + 527 gọi
def f[x]: return 3 * x ** 2 - 2 * x + 522 với giá trị hiện tại là
def f[x]: return 3 * x ** 2 - 2 * x + 514 làm đối số. Giá trị đó được gán cho tham số
def f[x]: return 3 * x ** 2 - 2 * x + 520
Bên trong
def f[x]: return 3 * x ** 2 - 2 * x + 522, giá trị của
def f[x]: return 3 * x ** 2 - 2 * x + 514 đi từ 1 đến 6. Trong sơ đồ, nó xảy ra là 2. Thay đổi biến này không ảnh hưởng đến giá trị của
def f[x]: return 3 * x ** 2 - 2 * x + 514 trong
def f[x]: return 3 * x ** 2 - 2 * x + 527
Việc có các biến cục bộ khác nhau có cùng tên là điều phổ biến và hoàn toàn hợp pháp. Đặc biệt, các tên như
def f[x]: return 3 * x ** 2 - 2 * x + 514 và
def f[x]: return 3 * x ** 2 - 2 * x + 544 được sử dụng thường xuyên làm biến vòng lặp. Nếu bạn tránh sử dụng chúng trong một chức năng chỉ vì bạn đã sử dụng chúng ở một chức năng khác, bạn có thể sẽ khiến chương trình khó đọc hơn.
5. 16. Cấu trúc dữ liệu đệ quy¶
Tất cả các kiểu dữ liệu Python mà chúng ta đã thấy có thể được nhóm bên trong các danh sách và bộ dữ liệu theo nhiều cách khác nhau. Danh sách và bộ dữ liệu cũng có thể được lồng vào nhau, cung cấp vô số khả năng để tổ chức dữ liệu. Việc tổ chức dữ liệu nhằm mục đích làm cho nó dễ sử dụng hơn được gọi là cấu trúc dữ liệu
Đã đến lúc bầu cử và chúng tôi đang giúp tính toán các phiếu bầu khi họ đến. Các phiếu bầu đến từ từng phường, khu bầu cử, thành phố tự trị, quận và tiểu bang đôi khi được báo cáo dưới dạng tổng số phiếu bầu và đôi khi dưới dạng danh sách tổng số phiếu bầu. Sau khi xem xét cách lưu trữ số liệu tốt nhất, chúng tôi quyết định sử dụng danh sách số lồng nhau mà chúng tôi xác định như sau
Danh sách số lồng nhau là danh sách có các phần tử hoặc
con số
danh sách số lồng nhau
Lưu ý rằng thuật ngữ, danh sách số lồng nhau được sử dụng theo định nghĩa riêng của nó. Các định nghĩa đệ quy như thế này khá phổ biến trong toán học và khoa học máy tính. Chúng cung cấp một cách ngắn gọn và mạnh mẽ để mô tả các cấu trúc dữ liệu đệ quy bao gồm một phần các phiên bản nhỏ hơn và đơn giản hơn của chính chúng. Định nghĩa không phải là vòng tròn, vì đến một lúc nào đó chúng ta sẽ đạt được một danh sách không có bất kỳ danh sách nào làm phần tử
Bây giờ, giả sử công việc của chúng ta là viết một hàm tính tổng tất cả các giá trị trong danh sách số lồng nhau. Python có một hàm tích hợp tìm tổng của một dãy số
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None11
Tuy nhiên, đối với danh sách số lồng nhau của chúng tôi,
def f[x]: return 3 * x ** 2 - 2 * x + 545 sẽ không hoạt động
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None12
Vấn đề là phần tử thứ ba của danh sách này,
def f[x]: return 3 * x ** 2 - 2 * x + 546, chính nó là một danh sách, không thể thêm vào
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None47,
def f[x]: return 3 * x ** 2 - 2 * x + 548 và
def f[x]: return 3 * x ** 2 - 2 * x + 549
5. 17. Đệ quy¶
Để tính tổng tất cả các số trong danh sách số lồng nhau đệ quy của chúng ta, chúng ta cần duyệt qua danh sách, truy cập từng phần tử trong cấu trúc lồng nhau của nó, thêm bất kỳ phần tử số nào vào tổng của chúng ta và lặp lại quy trình này với bất kỳ phần tử nào là danh sách
Các ngôn ngữ lập trình hiện đại thường hỗ trợ đệ quy, có nghĩa là các hàm có thể gọi chính chúng theo định nghĩa của chúng. Nhờ đệ quy, mã Python cần thiết để tính tổng các giá trị của danh sách số lồng nhau ngắn một cách đáng ngạc nhiên
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None13
Phần thân của
def f[x]: return 3 * x ** 2 - 2 * x + 550 chủ yếu bao gồm một vòng lặp
def f[x]: return 3 * x ** 2 - 2 * x + 551 chạy ngang qua
def f[x]: return 3 * x ** 2 - 2 * x + 552. Nếu
def f[x]: return 3 * x ** 2 - 2 * x + 553 là một giá trị số [nhánh
def f[x]: return 3 * x ** 2 - 2 * x + 554], nó chỉ cần được thêm vào
def f[x]: return 3 * x ** 2 - 2 * x + 555. Nếu
def f[x]: return 3 * x ** 2 - 2 * x + 553 là một danh sách, thì
def f[x]: return 3 * x ** 2 - 2 * x + 550 được gọi lại, với phần tử làm đối số. Câu lệnh bên trong định nghĩa hàm trong đó hàm gọi chính nó được gọi là lời gọi đệ quy
Đệ quy thực sự là một trong những công cụ đẹp và thanh lịch nhất trong khoa học máy tính
Một vấn đề phức tạp hơn một chút là tìm giá trị lớn nhất trong danh sách số lồng nhau của chúng tôi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None14
Tài liệu được đưa vào để cung cấp các ví dụ về
def f[x]: return 3 * x ** 2 - 2 * x + 558 tại nơi làm việc
Thêm vào vấn đề này là tìm một giá trị số để khởi tạo
def f[x]: return 3 * x ** 2 - 2 * x + 559. Chúng tôi không thể chỉ sử dụng
def f[x]: return 3 * x ** 2 - 2 * x + 560, vì đó là một số hoặc một danh sách. Để giải quyết vấn đề này, chúng tôi sử dụng vòng lặp while gán
def f[x]: return 3 * x ** 2 - 2 * x + 559 cho giá trị số đầu tiên bất kể nó được lồng sâu đến đâu
Hai ví dụ trên đều có trường hợp cơ sở không dẫn đến lệnh gọi đệ quy. trường hợp phần tử là một số và không phải là một danh sách. Không có trường hợp cơ sở, bạn có đệ quy vô hạn và chương trình của bạn sẽ không hoạt động. Python dừng sau khi đạt đến độ sâu đệ quy tối đa và trả về lỗi thời gian chạy
Viết phần sau vào một tệp có tên
def f[x]: return 3 * x ** 2 - 2 * x + 562
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None15
Tại dấu nhắc lệnh unix trong cùng thư mục mà bạn đã lưu chương trình của mình, hãy nhập nội dung sau
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None16
Sau khi xem các tin nhắn lướt qua, bạn sẽ thấy phần cuối của một truy nguyên dài kết thúc bằng phần sau
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None17
Chúng tôi chắc chắn sẽ không bao giờ muốn điều gì đó như thế này xảy ra với người dùng của một trong các chương trình của chúng tôi, vì vậy trước khi kết thúc cuộc thảo luận về đệ quy, hãy xem các lỗi như thế này được xử lý như thế nào trong Python
5. 18. Ngoại lệ¶
Bất cứ khi nào xảy ra lỗi thời gian chạy, nó sẽ tạo ra một ngoại lệ. Chương trình dừng chạy tại thời điểm này và Python in truy nguyên, kết thúc với ngoại lệ đã xảy ra
Ví dụ: chia cho 0 sẽ tạo ra một ngoại lệ
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None18
Việc truy cập vào một mục danh sách không tồn tại cũng vậy
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None19
Hoặc cố gắng gán một mục trên một tuple
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None00
Trong mỗi trường hợp, thông báo lỗi ở dòng cuối cùng có hai phần. loại lỗi trước dấu hai chấm và thông tin cụ thể về lỗi sau dấu hai chấm
Đôi khi chúng ta muốn thực hiện một thao tác có thể gây ra ngoại lệ, nhưng chúng ta không muốn chương trình dừng lại. Chúng tôi có thể xử lý ngoại lệ bằng cách sử dụng các câu lệnh
def f[x]: return 3 * x ** 2 - 2 * x + 563 và
def f[x]: return 3 * x ** 2 - 2 * x + 564
Ví dụ: chúng tôi có thể nhắc người dùng nhập tên tệp và sau đó thử mở tệp đó. Nếu tệp không tồn tại, chúng tôi không muốn chương trình bị lỗi;
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None01
Câu lệnh
def f[x]: return 3 * x ** 2 - 2 * x + 563 thực thi các câu lệnh trong khối đầu tiên. Nếu không có ngoại lệ nào xảy ra, nó sẽ bỏ qua câu lệnh
def f[x]: return 3 * x ** 2 - 2 * x + 564. Nếu có bất kỳ ngoại lệ nào xảy ra, nó sẽ thực thi các câu lệnh trong nhánh
def f[x]: return 3 * x ** 2 - 2 * x + 564 rồi tiếp tục
Chúng ta có thể gói gọn khả năng này trong một hàm.
def f[x]: return 3 * x ** 2 - 2 * x + 568 lấy tên tệp và trả về true nếu tệp tồn tại, sai nếu không
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None02
Bạn có thể sử dụng nhiều khối
def f[x]: return 3 * x ** 2 - 2 * x + 564 để xử lý các loại ngoại lệ khác nhau [xem bài học về Lỗi và Ngoại lệ từ Hướng dẫn Python của tác giả Python Guido van Rossum để thảo luận đầy đủ hơn về các ngoại lệ]
Nếu chương trình của bạn phát hiện một tình trạng lỗi, bạn có thể làm cho nó đưa ra một ngoại lệ. Dưới đây là một ví dụ nhận đầu vào từ người dùng và kiểm tra xem số đó có âm không
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None03
Câu lệnh
def f[x]: return 3 * x ** 2 - 2 * x + 570 có hai đối số. loại ngoại lệ và thông tin cụ thể về lỗi.
def f[x]: return 3 * x ** 2 - 2 * x + 571 là ngoại lệ tích hợp phù hợp nhất với loại lỗi mà chúng tôi muốn nêu ra. Danh sách đầy đủ các ngoại lệ tích hợp được tìm thấy trong phần Ngoại lệ tích hợp của Tài liệu tham khảo thư viện Python, một lần nữa bởi người tạo ra Python, Guido van Rossum
Nếu chức năng được gọi là
def f[x]: return 3 * x ** 2 - 2 * x + 572 xử lý lỗi, thì chương trình có thể tiếp tục;
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None04
Thông báo lỗi bao gồm loại ngoại lệ và thông tin bổ sung mà bạn đã cung cấp
Sử dụng xử lý ngoại lệ, giờ đây chúng ta có thể sửa đổi
def f[x]: return 3 * x ** 2 - 2 * x + 562 để nó dừng khi đạt đến độ sâu đệ quy tối đa cho phép
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None05
Chạy phiên bản này và quan sát kết quả
5. 19. Đệ quy đuôi¶
Khi thứ duy nhất được trả về từ một hàm là một lời gọi đệ quy, nó được gọi là đệ quy đuôi
Đây là phiên bản của hàm
def f[x]: return 3 * x ** 2 - 2 * x + 574 từ chương 6 được viết bằng cách sử dụng đệ quy đuôi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None06
Bất kỳ tính toán nào có thể được thực hiện bằng cách sử dụng phép lặp cũng có thể được thực hiện bằng cách sử dụng đệ quy. Đây là phiên bản của
def f[x]: return 3 * x ** 2 - 2 * x + 575 được viết bằng đệ quy đuôi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None07
Đệ quy đuôi được coi là một cách làm không tốt trong Python, vì trình biên dịch Python không xử lý tối ưu hóa cho các cuộc gọi đệ quy đuôi. Giải pháp đệ quy trong những trường hợp như thế này sử dụng nhiều tài nguyên hệ thống hơn giải pháp lặp tương đương
5. 20. Hàm toán học đệ quy¶
Một số hàm toán học nổi tiếng được định nghĩa đệ quy. Ví dụ, giai thừa được cung cấp bởi toán tử đặc biệt,
def f[x]: return 3 * x ** 2 - 2 * x + 576, và được xác định bởi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None08
Chúng ta có thể dễ dàng viết mã này vào Python
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None09
Một quan hệ đệ quy nổi tiếng khác trong toán học là dãy fibonacci, được xác định bởi
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None0
Điều này cũng có thể được viết dễ dàng bằng Python
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None1
Gọi
def f[x]: return 3 * x ** 2 - 2 * x + 577 sẽ vượt quá độ sâu đệ quy tối đa. Và thử chạy
def f[x]: return 3 * x ** 2 - 2 * x + 578 xem mất bao lâu để hoàn thành [kiên nhẫn sẽ hoàn thành]
Bạn sẽ được yêu cầu viết một phiên bản lặp lại của
def f[x]: return 3 * x ** 2 - 2 * x + 579 như một bài tập, và chúng ta sẽ thấy cách tốt hơn để xử lý
def f[x]: return 3 * x ** 2 - 2 * x + 580 trong chương tiếp theo
5. 21. Bảng thuật ngữ¶
tranh luậnMột giá trị được cung cấp cho một chức năng khi chức năng được gọi. Giá trị này được gán cho tham số tương ứng trong hàm
luồng thực hiệnThứ tự thực hiện các câu lệnh trong khi chạy chương trình
khungMột hộp trong sơ đồ ngăn xếp biểu thị một lệnh gọi hàm. Nó chứa các biến cục bộ và tham số của hàm
hàm sốMột chuỗi các câu lệnh được đặt tên thực hiện một số thao tác hữu ích. Các hàm có thể có hoặc không có tham số và có thể có hoặc không có kết quả
gọi hàmMột câu lệnh thực thi một chức năng. Nó bao gồm tên của hàm theo sau là danh sách các đối số được đặt trong dấu ngoặc đơn
thành phần chức năngSử dụng đầu ra từ một lệnh gọi hàm này làm đầu vào cho một lệnh gọi khác
chức năng định nghĩaMột câu lệnh tạo một hàm mới, chỉ định tên, tham số và các câu lệnh mà nó thực thi
tiêu đềPhần đầu tiên của một câu lệnh ghép. Tiêu đề bắt đầu bằng từ khóa và kết thúc bằng dấu hai chấm [. ]
biến cục bộMột biến được định nghĩa bên trong một hàm. Một biến cục bộ chỉ có thể được sử dụng bên trong chức năng của nó
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None28
The sole value of .
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None28 is often used to represent the absence of a value. It is also returned by a
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None26 statement with no argument or a function that reaches the end of its body without hitting a
>>> def mystery[]: .. return ... >>> what_is_it = mystery[] >>> what_is_it >>> type[what_is_it] >>> print[what_is_it] None26 statement containing a value.tham số
Tên được sử dụng bên trong hàm để chỉ giá trị được truyền dưới dạng đối số
sơ đồ ngăn xếpBiểu diễn đồ họa của một chồng các hàm, các biến của chúng và các giá trị mà chúng tham chiếu tới
tìm lạiDanh sách các chức năng đang thực thi, được in khi xảy ra lỗi thời gian chạy. Truy nguyên cũng thường được gọi là theo dõi ngăn xếp, vì nó liệt kê các chức năng theo thứ tự mà chúng được lưu trữ trong ngăn xếp thời gian chạy