Functions, call frames and returned results
Đã giới thiệu| English | Ý nghĩa |
|---|---|
| function/ˈfʌŋkʃn/ | Hàm |
| side effect/saɪd ɪˈfekt/ | Tác dụng phụ |
| contract/ˈkɒntrækt/ | Thỏa thuận |
| parameter/pəˈræmɪtə/ | Tham số |
| argument/ˈɑːɡjuːmənt/ | tham số thực |
| call frame/kɔːl freɪm/ | khung gọi |
| scope/skəʊp/ | phạm vi |
| local variable/ˈləʊkl ˈveərɪəbl/ | biến cục bộ |
| decomposition/ˌdiːkɒmpəˈzɪʃn/ | sự phân rã |
Giao mỗi hàm một nhiệm vụ rõ ràng
- Một hàm nhóm hợp một tác vụ có tên. Hãy nêu rõ đầu vào, kết quả trả về và bất kỳ tác động phụ nào, chẳng hạn như in ấn, trước khi viết thân hàm.
- Một hợp đồng nói rõ những gì người gọi có thể cung cấp và những gì hàm đảm bảo. Ở đây, các khoản tiền đều là số nguyên pence và phải là số nguyên không âm.
def add_fee(amount):
"""Return amount plus a fixed fee of 3 pence."""
return amount + 3
add_fee(8) đánh giá thành 11. Nó không in ra bất cứ thứ gì gì cả. Việc giữ riêng phần tính toán khỏi phần hiển thị giúp một hàm khác tái sử dụng kết quả đó.
Which contract lets another calculation use the fee-inclusive amount directly?
Độ khó 1/5 · 100 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
A returned result can be used in an expression; printed output is a separate side effect.
Phân biệt tên đầu vào với đối tượng đầu vào
- Trong định nghĩa,
amountlà một tham số. Trongadd_fee(8), biểu thức8cung cấp một đối số. Các biểu thức đối số được đánh giá trước khi thân hàm chạy. - Lệnh gọi gán tên tham số với đối tượng được cung cấp. Nó không tự động sao chép đối tượng đó hay tạo liên kết giữa tên của người gọi và tên tham số.
amount = 4
result = add_fee(amount * 2)
print(amount, result)
Biểu thức đối số cung cấp 8; bên trong lệnh gọi, amount trỏ đến số nguyên đó. Giá trị trả về 11 trở thành result. Modul amount vẫn trỏ đến 4, nên đầu ra là 4 11.
Match each term to its role in add_fee(8).
Độ khó 2/5 · 140 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
The argument is evaluated at the call; its object is bound to the parameter; return hands a result back.
Giữ một khung riêng biệt cho mỗi lần gọi
- Một khung gọi ghi lại một lần gọi hàm đang hoạt động, bao gồm các tham số và tên cục bộ của nó. Khi một hàm gọi hàm khác, người gọi chờ giá trị trả về.
- Đọc chương trình này theo thứ thi hành: modul →
twice→add_fee→twice→ modul. Các mũi tên bên dưới là luồng điều khiển khái niệm, không phải bố trí bộ nhớ vật lý.
def twice(amount):
subtotal = amount * 2
return add_fee(subtotal)
amount = 4
result = twice(amount)
print(amount, result)

Sử dụng bảng theo dõi để kiểm tra các lệnh gọi và giá trị trả về. Chi tiết khung cho thấy trạng thái tại lệnh gọi lồng nhau. Đây là bảng theo dõi do tác giả biên soạn cho ví dụ cụ thể này, không phải của trình biên dịch Python.
Trace twice(4) calling add_fee(8)
Separate local bindings from returned values.
Put these events in the order followed by result = twice(4).
Độ khó 3/5 · 200 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
The nested call finishes before twice can finish its return expression.
What integer is bound to amount inside add_fee during this nested call?
Độ khó 2/5 · 140 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
twice calculates subtotal as 4 times 2, then passes that 8 to add_fee.
Trả về kết quả; in ra thông báo
returnkết thúc lời gọi hiện tại và trả lại một đối tượng cho người gọi. Một hàm đạt đến cuối mà không córeturnsẽ trả vềNone.printghi dữ liệu đầu ra. Nó cũng trả vềNone, nên việc in một phép tính bên trong hàm sẽ không làm cho phép tính đó trở thành kết quả được trả về.
def show_fee(amount):
print(amount + 3)
value = show_fee(8)
print(value)
Điều này sẽ in 11, sau đó là None trên các dòng riêng biệt. Nếu người gọi cần số đó, hãy dùng return amount + 3 và để người gọi quyết định xem có in nó hay không.
show_fee prints 11 but has no return statement. What is stored in value?
Độ khó 1/5 · 100 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
Falling off the end of a Python function returns None, regardless of printed output.
Giải nghĩa tên biến trong phạm vi đúng
- Một biến cục bộ thuộc về một lần gọi hàm. Phạm vi (scope) của nó xác định nơi nào tên biến có thể được giải nghĩa; một hàm khác sẽ không tự động truy cập vào các tên biến cục bộ của hàm gọi.
- Gán cho tham số một giá trị nguyên mới sẽ thay đổi liên kết cục bộ của nó. Điều này không gán lại một biến cùng tên trong hàm gọi.
def increase(amount):
amount = amount + 1
return amount
amount = 4
new_amount = increase(amount)
print(amount, new_amount)
Dữ liệu đầu ra là 4 5. Cả hai tên ban đầu đều trỏ đến số nguyên 4; phép gán bên trong hàm đã liên kết lại tên cục bộ của nó. Để cập nhật tên mô-đun, hãy viết amount = increase(amount).
After new_amount = increase(amount), what value does the module's amount still hold?
Độ khó 2/5 · 140 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
Only the function's local name was rebound; the caller did not assign to amount.
Phân rã một phép tính thành các phần có thể kiểm thử
- Phân rã tách một tác vụ lớn thành các công việc nhỏ hơn với hợp đồng rõ ràng. Đối với đơn hàng, hãy tính tổng phụ của từng mặt hàng, cộng phí, sau đó hiển thị số tiền cuối cùng.
- Kiểm thử các phép tính trực tiếp, bao gồm cả số lượng bằng không và nhiều hơn một mặt hàng. Khẳng định rằng đầu vào là số nguyên không âm; việc kiểm tra tính hợp lệ của đầu vào có thể là một hàm riêng.
def item_subtotal(unit_pence, quantity):
return unit_pence * quantity
def order_total(unit_pence, quantity):
return add_fee(item_subtotal(unit_pence, quantity))
order_total(5, 2) trả về 13; order_total(5, 0) trả về 3 theo hợp đồng phí cố định này. Nếu đơn hàng không có mặt hàng nào nên có giá zero, hãy thay đổi cả hợp đồng và cách triển khai.
Under the stated fixed-fee contract, what does order_total(5, 0) return in pence?
Độ khó 2/5 · 140 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
The item subtotal is zero, but add_fee still adds 3. Free empty orders require a different contract.
Giải thích toàn bộ lời gọi trước khi tin vào kết quả
- Theo dõi các biểu thức đối số, sự liên kết tham số, các phép tính cục bộ và các giá trị được trả về. Kiểm tra trạng thái của người gọi sau khi lời gọi và dữ liệu đầu ra riêng biệt.
- Đừng mô tả truyền tham số như việc sao chép mọi đối tượng. Một cấu trúc dữ liệu có thể thay đổi được có thể bị sửa đổi thông qua tham số; sơ đồ đối tượng cho sự biến đổi và aliasing sẽ xuất hiện trong đơn vị 1.5.
Một con số được in ra chính xác không chứng minh kết quả được trả về là chính xác. Hãy sử dụng các kiểm tra trực tiếp như assert order_total(5, 2) == 13, sau đó kiểm tra bất kỳ dữ liệu đầu ra dự kiến nào riêng biệt.
Tài liệu tham khảo ngôn ngữ: Hàm Python và liên kết tên và phạm vi.
Calling a Python function automatically copies every argument object.
Độ khó 1/5 · 100 xu + phần thưởng nhỏ khi hoàn thành lần đầu tiên hôm nay
Parameters are bound to supplied objects. Copying must be requested explicitly when needed.