控制流语句(if、for、while)和函数定义的基本用法及闭包、装饰器、匿名函数
if 语句
当满足条件时,执行代码块。可以有多个 elif
和 else
条件。当然这是可选的。
x = 42
if x < 0:
print('x 是负数')
elif x == 0:
print('x 等于零')
else:
print('x 是正数') # x 是正数
条件关键字
关键字 | 描述 |
---|---|
and | 与 |
or | 或 |
not | 非 |
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
: 生成序列的起始值,默认为0step
: 步长,默认为1
pythonprint(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
: 要测量长度的序列
pythonprint(len("Hello")) # 5 print(len([1, 2, 3])) # 3 print(len(range(5))) # 5
for i in range(5):
print(i) # 0 1 2 3 4
break 和 continue
break
:跳出最近的一层for
或while
循环。continue
:继续执行循环的下一次迭代。
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 循环
在条件为真时重复执行代码块。
i = 0
while i < 5:
print(i) # 0 1 2 3 4
i += 1
pass 语句
当程序不需要执行任何操作时,语法层面要求要有一个语句。可以使用 pass
语句来避免语法错误。
在循环中使用 pass
并不代表会终止循环,只是没有��任何事情
for i in range(10):
pass
while True:
pass # 无限循环
class MyClass:
pass
def my_function():
pass
函数 def
函数是可以重复使用的代码块,用于执行单一、相关的任务。比如打印斐波那契数列 (前两数的和等于下一个数)。
def fib():
a, b = 0, 1
while a < 200:
print(a, end=' ')
a, b = b, a+b
fib()
函数默认的返回值是 None
。可以接受多个参数,也可以返回多个值。
def add(a, b):
return a + b, a - b
print(add(1, 2)) # (3, -1)
函数参数
- 位置参数:按照顺序传递参数,上述
add
函数就是位置参数 - 关键字参数:通过参数名传递参数,可以不按照顺序传递参数
- 默认参数:在函数定义时给参数赋值,调用时可以不传递该参数
- 可变参数:在参数名前加
*
或**
,可以接收任意数量的参数,*
表示元组,**
表示字典
参数的优先级:位置参数 > 关键字参数 > 默认参数 > 可变参数
# 关键字参数
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 中有四种作用域:
- Local(局部作用域): 函数内部的变量
- Enclosing(嵌套作用域): 外层函数的变量
- Global(全局作用域): 模块级别的变量
- Built-in(内置作用域): Python内置的变量/函数
这四种作用域的访问顺序遵循 LEGB 原则: Local -> Enclosing -> Global -> Built-in
# 全局作用域
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
: 在嵌套函数中修改外层函数的变量
counter = 0
def increment():
global counter
counter += 1
increment()
print(counter) # 1
闭包(Closure)
闭包是一个函数返回另一个函数,并且返回的函数可以访问外层函数的变量。这种特性常用于数据封装和装饰器模式。
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变量
实际应用场景
- 数据封装:
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
- 装饰器模式:
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
匿名函数是一种简洁的定义函数的方式,通常用于简单的操作。仅限返回值是一些单行表达式。
add = lambda a, b: a + b
print(add(1, 2)) # 3
笔试题
选择题
以下关于函数作用域的说法,哪个是正确的?
- A. 局部变量可以直接在全局使用
- B. 全局变量在函数内可以直接修改
- C. 使用 global 关键字可以在函数内修改全局变量
- D. nonlocal 关键字用于修改全局变量
下面哪个是有效的闭包函数?
- 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
- A.
以下装饰器的输出结果是什么?
pythondef decorator(func): def wrapper(): print("开始") func() print("结束") return wrapper @decorator def hello(): print("Hello") hello()
- A. 只输出 "Hello"
- B. 输出 "开始" "Hello" "结束"
- C. 输出 "Hello" "开始" "结束"
- D. 什么都不输出
编程题
实现一个计数器装饰器
@counter
,记录被装饰函数的调用次数:python@counter def foo(): print("Hello") foo() # 输出: 调用次数: 1 foo() # 输出: 调用次数: 2
编写一个闭包函数
make_average()
,能够持续计算输入数字的平均值:pythonavg = make_average() print(avg(10)) # 10.0 print(avg(11)) # 10.5 print(avg(12)) # 11.0
问答题
解释以下代码为什么会抛出 UnboundLocalError 异常,如何修复?
pythoncount = 0 def increment(): count += 1 return count print(increment())
闭包和普通函数的区别是什么?请从内存和使用场景两个角度解释。
装饰器的工作原理是什么?为什么在 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 表达式,应该如何写?