📚 Functions and Procedures in Programming | 编程中的函数与过程
In A-Level programming, understanding the distinction between functions and procedures is fundamental to writing modular, reusable, and efficient code. A function is a named block of code that performs a specific task and always returns a value, while a procedure is similar but does not return a value and is typically called to carry out an action. Both help break down complex problems into manageable units, promote code reuse, and improve readability. This article explores the key concepts of subprograms, parameter passing, scope, recursion, and common pitfalls, preparing you for Edexcel’s programming challenges and beyond.
在 A-Level 编程中,理解函数(function)与过程(procedure)的区别是编写模块化、可复用且高效代码的基础。函数是一个执行特定任务并始终返回值的命名代码块,而过程与之相似但不返回值,通常用来执行某个动作。两者都有助于将复杂问题分解为可管理的单元、促进代码复用并提升可读性。本文将探讨子程序、参数传递、作用域、递归以及常见陷阱等核心概念,助你迎接 Edexcel 编程挑战及更高层次的考试。
1. What are Functions and Procedures? | 什么是函数和过程?
A function is a subprogram that computes a result and returns it to the caller using a return statement. In mathematics, a function maps input values to a single output; in programming, the same principle applies. For example, a function square(x) takes a number and returns its square. A procedure, on the other hand, performs a task like displaying output or modifying a data structure, but does not hand back a value. Some languages call procedures ‘void functions’ or simply use the same syntax with no return statement. In Python, all subprograms defined with def are technically functions, but if they lack an explicit return, they implicitly return None, functioning like procedures.
函数是一个计算某个结果并通过 return 语句将其返回给调用者的子程序。在数学中,函数将输入值映射到单一输出;编程中也遵循同样原则。例如,函数 square(x) 接收一个数字并返回其平方值。而过程则执行诸如显示输出或修改数据结构之类的任务,但不返回值。某些语言将过程称为“void 函数”或简单地使用同一语法且不写 return 语句。在 Python 中,所有用 def 定义的子程序在技术上都是函数,但如果没有显式 return,它们会隐式返回 None,从而起到过程的作用。
2. Defining and Calling Subprograms | 定义与调用子程序
To define a subprogram in Python, you use the def keyword followed by the name and parentheses. The body is indented. Calling is done by writing the name with appropriate arguments. For a function that returns a value, the call can be used in an expression. For a procedure, the call stands alone as a statement. A well-defined subprogram should have a clear purpose, a descriptive name, and, ideally, a docstring. Consider this example: a function add(a, b) returns the sum, while a procedure greet(name) prints a message but returns nothing useful.
在 Python 中,使用 def 关键字加上名称和圆括号来定义子程序。主体需要缩进。调用时只需写上名称并传入合适的实参。对于有返回值的函数,可以将调用放在表达式中;对于过程,调用独立成句。一个良定义的子程序应有明确的目的、描述性的名称,并且最好包含文档字符串。例如,函数 add(a, b) 返回两数之和,而过程 greet(name) 打印一条消息但不返回任何有用的值。
3. Parameters and Arguments | 参数与实参
Parameters are the variables listed inside the parentheses in the subprogram definition; arguments are the actual values passed during a call. Understanding the difference avoids confusion. Parameters act as placeholders and allow subprograms to be generalised. Python supports positional arguments, keyword arguments, and default parameter values. For instance, def power(base, exp=2): uses a default parameter. When calling, you can write power(3, 2) or power(exp=3, base=2). This flexibility is essential for designing reusable code. Formal parameters are local to the subprogram and exist only during its execution.
参数是子程序定义时圆括号内的变量;实参是调用时传入的实际值。理解两者的区别可以避免混淆。参数充当占位符,使子程序具有通用性。Python 支持位置实参、关键字实参以及参数默认值。例如,def power(base, exp=2): 为 exp 设置了默认值。调用时既可以写 power(3, 2),也可以写 power(exp=3, base=2)。这种灵活性对设计可复用代码至关重要。形式参数是子程序内部的局部变量,仅在执行期间存在。
4. Passing by Value vs. Passing by Reference | 值传递与引用传递
Different languages handle argument passing differently. Pass by value means a copy of the data is handed to the subprogram, so modifications do not affect the original variable. Pass by reference means the actual memory location is passed, so changes inside the subprogram affect the original. Python uses a mechanism known as ‘pass by object reference’ or ‘pass by assignment’: immutable objects (e.g., integers, strings) behave like pass by value, while mutable objects (e.g., lists, dictionaries) behave like pass by reference. Thus, a procedure that appends to a list will alter the list globally, but reassigning an integer parameter does not change the external variable.
不同语言处理参数传递的方式各异。按值传递意味着将数据副本交给子程序,因此修改不会影响原变量。按引用传递意味着传递实际的内存地址,子程序内的更改会影响原变量。Python 使用一种称为“按对象引用传递”或“按赋值传递”的机制:不可变对象(如整数、字符串)表现得像按值传递,而可变对象(如列表、字典)则像按引用传递。因此,一个向列表追加元素的过程会全局性地改变该列表,但重新赋值一个整数形参不会改变外部变量。
5. Return Values and Output | 返回值与输出
A function communicates its result to the caller by a return statement. The returned value can be assigned to a variable, used in an expression, or even ignored. A function can return multiple values as a tuple, which can be unpacked. Procedures, in contrast, produce side effects such as printing to the screen, writing to a file, or modifying a global structure, but they do not return a meaningful value (or return None). Relying on return values makes functions predictable and testable. Consider a recursive Fibonacci function that returns the nth term, rather than a procedure that prints the sequence directly.
函数通过 return 语句将计算结果传递给调用者。返回值可以赋给变量、用于表达式,甚至被忽略。一个函数可以以元组形式返回多个值,然后解包。相反,过程产生副作用,如打印到屏幕、写入文件或修改全局结构,但不返回有意义的值(或返回 None)。依赖返回值使函数具有可预测性和可测试性。设想一个返回第 n 项的递归斐波那契函数,而不是一个直接打印数列的过程。
6. Scope of Variables: Local and Global | 变量作用域:局部与全局
Variables defined inside a subprogram are local: they exist only during that subprogram’s execution and cannot be accessed outside. Global variables, defined at the module level, can be read from inside any subprogram, but to modify them you must declare global explicitly in Python. Shadowing occurs when a local variable has the same name as a global one, temporarily hiding it. Encouraging local scope reduces unintended interactions and makes code easier to debug. A strong programmer minimises global variables and passes data through parameters and return values instead.
在子程序内部定义的变量是局部的:它们仅在该子程序执行期间存在,外部无法访问。而在模块层定义的全局变量可以从任何子程序内部读取,但要修改它们必须在 Python 中显式声明 global。当局部变量与全局变量同名时会发生遮盖,从而暂时隐藏全局变量。倡导局部作用域可以减少意外交互,并使代码更易于调试。优秀的程序员会尽量减少全局变量的使用,转而通过参数和返回值传递数据。
7. Side Effects in Procedures | 过程中的副作用
A side effect is any observable change outside the subprogram’s local environment, such as modifying a global list, printing output, or changing a file. While procedures are designed to cause side effects, excessive side effects can make a program hard to reason about. Functional programming paradigms try to eliminate side effects entirely, relying only on return values. In A-Level exams, you should identify when a procedure has side effects and whether they are intentional. For example, a sorting procedure that modifies a list in‑place has a clear side effect, whereas a function that returns a sorted copy without altering the original is side‑effect‑free.
副作用是指子程序局部环境之外发生的任何可观察的变化,例如修改全局列表、打印输出或更改文件。虽然过程本就是为了引发副作用而设计的,但过多的副作用会让程序难以理解。函数式编程范式试图完全消除副作用,仅依赖返回值。在 A-Level 考试中,你应能识别过程何时产生了副作用,以及它们是否是有意的。例如,一个原地排序的过程会修改列表,这就是明确的副作用;而一个返回排序后副本且不改变原列表的函数则没有副作用。
8. Recursion: A Special Function Call | 递归:特殊的函数调用
Recursion is a technique where a function calls itself to solve a smaller instance of the same problem. Every recursive solution must have a base case to stop the recursion and a recursive case that moves toward the base case. Classic examples include factorial, Fibonacci, and tree traversals. Recursion can replace iteration and often leads to elegantly simple code, but it carries the risk of stack overflow if the recursion depth is too large. Python limits recursion depth to around 1000 by default. Understanding the call stack and how local variables are preserved in each frame is essential when tracing recursive calls.
递归是一种函数调用自身以解决同一问题的较小实例的技术。每个递归解法必须有一个基准情形来终止递归,以及一个向基准情形推进的递归情形。经典例子包括阶乘、斐波那契和树的遍历。递归可以替代迭代,常常带来简洁优雅的代码,但如果递归深度太大则有栈溢出风险。Python 默认将递归深度限制在约 1000 层。在追踪递归调用时,理解调用栈以及局部变量如何在每一帧中保存至关重要。
9. Modular Programming and Code Reuse | 模块化编程与代码复用
Functions and procedures are the building blocks of modular programming. By decomposing a large problem into smaller, independent subprograms, you can develop, test, and debug each piece separately. This approach supports teamwork, as different programmers can work on different modules. Libraries and APIs are built on this principle: they provide pre‑written functions that you can call without knowing their internal details. In Python, you can import modules like math and use math.sqrt(). Writing clean, well‑documented subprograms with clear interfaces makes your code reusable in future projects, saving time and reducing errors.
函数和过程是模块化编程的基石。通过将大问题分解成更小、独立的子程序,你可以分别开发、测试和调试每一个部分。这种方法支持团队协作,因为不同程序员可以处理不同模块。库和 API 正是建立在这一原则之上:它们提供预先写好的函数,你无需知道其内部细节即可调用。在 Python 中,你可以导入 math 之类的模块并使用 math.sqrt()。编写清晰、文档良好的子程序并定义明确的接口,能使你的代码在未来的项目中可复用,从而节省时间并减少错误。
10. Common Pitfalls and Debugging | 常见陷阱与调试
Many bugs arise from misunderstanding how parameters are passed or how scope works. A typical mistake is assuming a function can modify a global variable by reassigning a local parameter of the same name without using the global keyword. Another is forgetting to return a value, causing None to propagate silently. Recursive functions may miss a base case or fail to progress toward it, leading to infinite recursion. Using print‑line debugging or a step‑through debugger helps trace execution. In exams, hand‑tracing subprogram calls with a variable table is a reliable way to follow logic and catch errors.
许多错误源于对参数传递方式或作用域机制的理解偏差。一个典型错误是以为函数可以通过重新赋值同名局部参数来修改全局变量,却没有使用 global 关键字。另一个常见错误是忘记返回值,导致 None 静默传播。递归函数可能遗漏基准情形或无法向基准情形推进,从而引发无限递归。使用打印调试或单步调试器有助于追踪执行过程。在考试中,借助变量表手动追踪子程序调用是梳理逻辑并发现错误的可靠方法。
11. Functions in Different Languages (Python and Beyond) | 不同语言中的函数(Python 及更多)
While the core concepts are universal, syntax varies. In Python, functions are first‑class objects; you can assign them to variables, pass them as arguments, and return them from other functions. Languages like Pascal, used in some A‑Level contexts, distinguish between function and procedure keywords explicitly. In Pascal, a function block must contain an assignment to its own name as the return value. Java uses methods inside classes; a void method corresponds to a procedure. Despite syntactic differences, the underlying principles of modularity, parameter passing, and scope remain consistent. Understanding these differences equips you to adapt quickly to new languages.
尽管核心概念是通用的,但语法各异。在 Python 中,函数是一等对象;你可以将其赋值给变量、作为实参传递以及从其他函数返回。像 Pascal 这样的语言在某些 A‑Level 场景中使用,它们明确区分 function 和 procedure 关键字。在 Pascal 中,函数体必须包含向其自身名称的赋值作为返回值。Java 使用类内的方法;void 方法对应于过程。尽管语法差异明显,但模块化、参数传递和作用域的基本原则保持一致。理解这些差异能让你快速适应新语言。
12. Conclusion: Mastering Subprograms for Exam Success | 结语:掌握子程序以迎战考试
Functions and procedures are not merely syntactic constructs; they embody the principles of abstraction, decomposition, and reuse central to computational thinking. For Edexcel A‑Level programming, you must be able to define, call, trace, and debug subprograms confidently, whether they appear in pseudocode, Python, or another specified language. Practise writing functions with clear parameter lists and return statements, and always consider scope and side effects. By internalising these concepts, you will write cleaner programs and solve exam questions with precision. Keep coding, keep tracing, and treat every function as a small, solvable puzzle.
函数和过程不仅是语法结构;它们体现了抽象、分解和复用等计算思维的核心原则。在 Edexcel A‑Level 编程中,你必须能够自信地定义、调用、追踪和调试子程序,无论它们是以伪代码、Python 还是其他指定语言出现。多练习编写具有清晰参数列表和 return 语句的函数,并始终考虑作用域和副作用。通过内化这些概念,你将写出更整洁的程序,并精准地解答考试题目。坚持编码、坚持追踪,把每个函数都当作一个小而可解的谜题。
Published by TutorHao | Programming Revision Series | aleveler.com
更多咨询请联系16621398022(同微信)
屏轩国际教育cambridge primary/secondary checkpoint, cat4, ukiset,ukcat,igcse,alevel,PAT,STEP,MAT, ibdp,ap,ssat,sat,sat2课程辅导,国外大学本科硕士研究生博士课程论文辅导