Skip to content

控制流语句(if、for、while)和函数定义的基本用法及闭包、装饰器、匿名函数

if 语句

当满足条件时,执行代码块。可以有多个 elifelse 条件。当然这是可选的。

python
x = 42

if x < 0:
    print('x 是负数')
elif x == 0:
    print('x 等于零')
else:
    print('x 是正数')  # x 是正数

条件关键字

关键字描述
and
or
not
python
x = 10
y = 20
z = 30

print(x < y and y < z)  # True
print(x < y or y > z)  # True
print(not x > y)  # True

if not (x > y):
    print('x 小于 y')  # x 小于 y

for 循环

在循环中遍历序列(如列表、元组、字符串)或其他可迭代对象。获取到序列中的每一项内容,可以方便进行处理 (比如 if 判断)。

  • range(stop)range(start, stop[, step]) 函数:生成一个整数序列

    • stop: 生成序列的结束值(不包含)
    • start: 生成序列的起始值,默认为0
    • step: 步长,默认为1
    python
    print(list(range(5)))        # [0, 1, 2, 3, 4]
    print(list(range(2, 5)))     # [2, 3, 4] 
    print(list(range(0, 10, 2))) # [0, 2, 4, 6, 8]
  • len(sequence) 函数:获取序列(字符串、列表、元组等)的长度

    • sequence: 要测量长度的序列
    python
    print(len("Hello"))     # 5
    print(len([1, 2, 3]))   # 3
    print(len(range(5)))    # 5
python
for i in range(5):
    print(i)  # 0 1 2 3 4

break 和 continue

  • break :跳出最近的一层 forwhile 循环。
  • continue :继续执行循环的下一次迭代。
python
for i in range(10):
    if i == 5:
        break  # 跳出循环
    print(i)  # 0 1 2 3 4

for i in range(10):
    if i == 5:
        continue  # 跳过本次循环
    print(i)  # 0 1 2 3 4 6 7 8 9

while 循环

在条件为真时重复执行代码块。

python
i = 0
while i < 5:
    print(i)  # 0 1 2 3 4
    i += 1

pass 语句

当程序不需要执行任何操作时,语法层面要求要有一个语句。可以使用 pass 语句来避免语法错误。

在循环中使用 pass 并不代表会终止循环,只是没有��任何事情

python
for i in range(10):
    pass

while True:
    pass  # 无限循环

class MyClass:
    pass

def my_function():
    pass

函数 def

函数是可以重复使用的代码块,用于执行单一、相关的任务。比如打印斐波那契数列 (前两数的和等于下一个数)。

python
def fib():
    a, b = 0, 1
    while a < 200:
        print(a, end=' ')
        a, b = b, a+b

fib()

函数默认的返回值是 None。可以接受多个参数,也可以返回多个值。

python
def add(a, b):
    return a + b, a - b

print(add(1, 2))  # (3, -1)

函数参数

  • 位置参数:按照顺序传递参数,上述 add 函数就是位置参数
  • 关键字参数:通过参数名传递参数,可以不按照顺序传递参数
  • 默认参数:在函数定义时给参数赋值,调用时可以不传递该参数
  • 可变参数:在参数名前加 ***,可以接收任意数量的参数,* 表示元组,** 表示字典

参数的优先级:位置参数 > 关键字参数 > 默认参数 > 可变参数

python
# 关键字参数
def add(a, b):
    return a + b

print(add(b=3, a=1))  # 4

# 默认参数
def add(a, b=2):
    return a + b

print(add(1))  # 3

# 可变参数
def add(*args):
    return sum(args)

print(add(1, 2, 3, 4))  # 10

def add(**kwargs):
    return sum(kwargs.values())

print(add(a=1, b=2, c=3))  # 6

函数作用域

Python 中有四种作用域:

  1. Local(局部作用域): 函数内部的变量
  2. Enclosing(嵌套作用域): 外层函数的变量
  3. Global(全局作用域): 模块级别的变量
  4. Built-in(内置作用域): Python内置的变量/函数

这四种作用域的访问顺序遵循 LEGB 原则: Local -> Enclosing -> Global -> Built-in

python
# 全局作用域
x = 0  

def outer():
    # 嵌套作用域
    x = 1  
    def inner():
        # 局部作用域
        x = 2  
        print('inner x:', x)  # 2 - 优先访问局部变量
    inner()
    print('outer x:', x)  # 1 - 访问嵌套作用域变量

outer()
print('global x:', x)  # 0 - 访问全局变量

global 和 nonlocal 关键字

  • global: 在函数内部修改全局变量
  • nonlocal: 在嵌套函数中修改外层函数的变量
python
counter = 0

def increment():
    global counter
    counter += 1

increment()
print(counter)  # 1

闭包(Closure)

闭包是一个函数返回另一个函数,并且返回的函数可以访问外层函数的变量。这种特性常用于数据封装和装饰器模式。

python
def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

# 创建两个独立的计数器
counter1 = make_counter()
counter2 = make_counter()

print(counter1())  # 1
print(counter1())  # 2
print(counter2())  # 1 - counter2有自己独立的count变量

实际应用场景

  1. 数据封装:
python
def create_bank_account(initial_balance):
    balance = initial_balance
    
    def deposit(amount):
        nonlocal balance
        balance += amount
        return balance
        
    def withdraw(amount):
        nonlocal balance
        if balance >= amount:
            balance -= amount
            return balance
        return "余额不足"
        
    return {
        "deposit": deposit,
        "withdraw": withdraw
    }

# 创建一个银行账户
account = create_bank_account(1000)
print(account["deposit"](500))   # 1500
print(account["withdraw"](200))  # 1300
  1. 装饰器模式:
python
def logger(func):
    def wrapper(*args, **kwargs):
        print(f"调用函数: {func.__name__}")
        result = func(*args, **kwargs)
        print(f"函数返回: {result}")
        return result
    return wrapper

@logger
def add(a, b):
    return a + b

add(3, 5)  # 输出调用信息并返回8

匿名函数 lambda

匿名函数是一种简洁的定义函数的方式,通常用于简单的操作。仅限返回值是一些单行表达式

python
add = lambda a, b: a + b

print(add(1, 2))  # 3

笔试题

选择题

  1. 以下关于函数作用域的说法,哪个是正确的?

    • A. 局部变量可以直接在全局使用
    • B. 全局变量在函数内可以直接修改
    • C. 使用 global 关键字可以在函数内修改全局变量
    • D. nonlocal 关键字用于修改全局变量
  2. 下面哪个是有效的闭包函数?

    • A.
      python
      def outer(x):
          return x + 1
    • B.
      python
      def outer(x):
          def inner():
              return x + 1
          return inner
    • C.
      python
      def outer():
          x = 1
          return x + 1
    • D.
      python
      x = 1
      def outer():
          return x + 1
  3. 以下装饰器的输出结果是什么?

    python
    def decorator(func):
        def wrapper():
            print("开始")
            func()
            print("结束")
        return wrapper
    
    @decorator
    def hello():
        print("Hello")
    
    hello()
    • A. 只输出 "Hello"
    • B. 输出 "开始" "Hello" "结束"
    • C. 输出 "Hello" "开始" "结束"
    • D. 什么都不输出

编程题

  1. 实现一个计数器装饰器 @counter,记录被装饰函数的调用次数:

    python
    @counter
    def foo():
        print("Hello")
    
    foo()  # 输出: 调用次数: 1
    foo()  # 输出: 调用次数: 2
  2. 编写一个闭包函数 make_average(),能够持续计算输入数字的平均值:

    python
    avg = make_average()
    print(avg(10))  # 10.0
    print(avg(11))  # 10.5
    print(avg(12))  # 11.0

问答题

  1. 解释以下代码为什么会抛出 UnboundLocalError 异常,如何修复?

    python
    count = 0
    def increment():
        count += 1
        return count
    
    print(increment())
  2. 闭包和普通函数的区别是什么?请从内存和使用场景两个角度解释。

  3. 装饰器的工作原理是什么?为什么在 Python 中被广泛使用?

代码阅读题

阅读以下代码,分析输出结果并解释原因:

python
def multiplier(n):
    def multiply(x):
        return x * n
    return multiply

double = multiplier(2)
triple = multiplier(3)

numbers = [1, 2, 3]
print(list(map(double, numbers)))
print(list(map(triple, numbers)))

# 问题:
# 1. double 和 triple 函数是如何保持各自的 n 值的?
# 2. 如果把 multiplier 改写成 lambda 表达式,应该如何写?