当前位置: 首页 > news >正文

Python 函数进阶:深入理解参数、装饰器与函数式编程

Python 的成功很大程度上归功于其清晰、简洁且功能强大的语法,而函数在其中扮演了核心角色。从简单的代码封装到复杂的函数式编程范式,理解函数的方方面面是成为一名优秀 Python 开发者的必经之路。本文将深入探讨 Python 函数的几个关键高级特性。

1. 灵活多变的函数参数

Python 的函数参数处理非常灵活,主要支持以下四种类型:

1.1 位置参数

这是最常用的参数类型。调用函数时,实参的顺序和数量必须与形参的定义完全匹配。

def greet(name, greeting):print(f"{greeting}, {name}!")greet("Alice", "Hello")  # 输出: Hello, Alice!
# greet("Hello")        # 错误:缺少一个必需的位置参数

1.2 默认参数

在定义函数时,可以为参数指定一个默认值。调用时如果未传递该参数,则使用默认值。默认参数必须指向不可变对象,否则可能引发意想不到的行为。

def greet(name, greeting="Hello"):print(f"{greeting}, {name}!")greet("Bob")            # 输出: Hello, Bob!
greet("Charlie", "Hi") # 输出: Hi, Charlie!

1.3 可变参数 (*args)

当你不确定要传递多少个位置参数时,可以使用 *args。它会将传入的所有额外位置参数收集到一个元组中。

def add_numbers(*args):total = 0for num in args:total += numreturn totalresult = add_numbers(1, 2, 3, 4, 5)
print(result)  # 输出: 15

1.4 关键字参数 (**kwargs)

用于处理不定数量的关键字参数(如 key=value 形式)。它会将这些参数收集到一个字典中。

def print_user_info(**kwargs):for key, value in kwargs.items():print(f"{key}: {value}")print_user_info(name="Dave", age=30, city="New York")
# 输出:
# name: Dave
# age: 30
# city: New York

混合使用顺序:在定义一个函数时,这四种参数必须遵循严格的顺序:
位置参数 -> 默认参数 -> *args -> **kwargs

def complex_function(a, b=2, *args, **kwargs):print(f"a={a}, b={b}")print(f"args: {args}")print(f"kwargs: {kwargs}")complex_function(1, 3, 4, 5, 6, name='John', age=25)
# 输出:
# a=1, b=3
# args: (4, 5, 6)
# kwargs: {'name': 'John', 'age': 25}

2. 函数也是一种对象:一等函数与高阶函数

在 Python 中,函数是第一类对象。这意味着函数可以:

  • 被赋值给一个变量

  • 作为参数传递给另一个函数

  • 作为另一个函数的返回值

2.1 把函数赋值给变量

def say_hello(name):return f"Hello, {name}!"greet = say_hello  # 将函数对象赋值给变量 greet
print(greet("World"))  # 输出: Hello, World!

2.2 高阶函数

接收函数作为参数,或者返回函数作为结果的函数,被称为高阶函数mapfiltersorted 等都是经典的高阶函数。

# 1. 作为参数
def apply_func(func, data):return [func(item) for item in data]numbers = [1, 2, 3, 4]
squared = apply_func(lambda x: x**2, numbers)
print(squared)  # 输出: [1, 4, 9, 16]# 2. 作为返回值
def get_multiplier(factor):def multiplier(x):return x * factorreturn multiplierdouble = get_multiplier(2)
triple = get_multiplier(3)print(double(5))  # 输出: 10
print(triple(5))  # 输出: 15

2.3 Lambda 匿名函数

lambda 关键字用于创建小巧的匿名函数。它只是一个表达式,函数体比 def 简单的多。

# 语法: lambda arguments: expression
square = lambda x: x ** 2
print(square(5)) # 输出: 25# 常用于高阶函数中作为参数
numbers = [1, 4, 2, 9, 5]
sorted_numbers = sorted(numbers, key=lambda x: -x)
print(sorted_numbers)  # 输出: [9, 5, 4, 2, 1]

3. 迭代器 (Iterator) 与生成器 (Generator)

3.1 迭代器 (Iterator)

迭代器是实现了迭代器协议的对象,该协议包含两个方法:

  • __iter__(): 返回迭代器对象本身。

  • __next__(): 返回容器的下一个元素。如果没有更多元素,则抛出 StopIteration 异常。

列表、元组、字典、集合都是可迭代对象 (Iterable),但不是迭代器。可以使用 iter() 函数将它们转换为迭代器。

my_list = [1, 2, 3]
my_iter = iter(my_list) # 获取迭代器print(next(my_iter)) # 输出: 1
print(next(my_iter)) # 输出: 2
print(next(my_iter)) # 输出: 3
# print(next(my_iter)) # 抛出 StopIteration 异常

3.2 生成器 (Generator)

生成器是一种特殊的迭代器,它延迟计算,按需产生值,而不是一次性在内存中构建整个序列,非常节省内存。

创建生成器有两种主要方法:

方法一:生成器函数 (使用 yield)
使用 yield 关键字代替 return。每次调用 next() 时,函数会从上次 yield 的位置继续执行。

def countdown(n):print("Starting countdown!")while n > 0:yield n  # 产生值 n,并在此暂停n -= 1print("Blastoff!")# 创建生成器对象
cd = countdown(3)
print(next(cd)) # 输出: Starting countdown! 然后输出 3
print(next(cd)) # 输出: 2
print(next(cd)) # 输出: 1
print(next(cd)) # 输出: Blastoff! 然后抛出 StopIteration

方法二:生成器表达式
语法类似列表推导式,但使用圆括号 ()

# 列表推导式 - 立即生成所有数据,耗内存
list_comp = [x*x for x in range(1000000)]# 生成器表达式 - 几乎不占内存,按需生成
gen_exp = (x*x for x in range(1000000))print(next(gen_exp)) # 输出: 0
print(next(gen_exp)) # 输出: 1
# ... 可以用于 for 循环
for num in gen_exp:if num > 25:breakprint(num, end=' ')
# 输出: 4 9 16 25

4. 常用内置函数 (Built-in Functions)

Python 提供了许多高效的内置函数,以下是一些非常常用的:

  • len(s): 返回对象长度。

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

  • type(obj): 返回对象的类型。

  • isinstance(obj, classinfo): 检查对象是否是某个类或其子类的实例。

  • input([prompt]): 从标准输入读取字符串。

  • print(*objects, sep=' ', end='\n'): 打印输出。

  • enumerate(iterable, start=0): 返回一个枚举对象,生成 (index, value) 元组。

  • zip(*iterables): 将多个可迭代对象中对应的元素打包成元组。

  • map(func, iterable, ...): 将函数应用于可迭代对象的每个元素,返回一个迭代器。

  • sorted(iterable, key=None, reverse=False): 返回一个新的排序列表。

5. 闭包 (Closure)

闭包是一个能够访问其外部函数作用域中变量的内部函数,即使外部函数已经执行完毕。

闭包的三个必要条件:

  1. 必须有一个嵌套函数(内部函数)。

  2. 嵌套函数必须引用外部函数中定义的变量。

  3. 外部函数必须返回内部函数。

def outer_func(msg):message = msg  # 外部作用域的变量def inner_func(): # 嵌套函数print(message) # 引用了外部变量 messagereturn inner_func  # 返回内部函数对象my_closure = outer_func("Hello, Closure!")
my_closure()  # 输出: Hello, Closure!
# 此时 outer_func 已执行完,但 inner_func 仍能记住并访问 message 变量

闭包是一种强大的技术,常用于数据隐藏和封装装饰器回调函数等场景。但闭包也有一个缺陷,外部函数的非局部变量一直被内部函数引用,长时间得不到回收,可能会导致内存泄漏,因此使用的优先级就进一步降低了。

6. 装饰器 (Decorator)

装饰器是 Python 中最具特色的功能之一。它本质上是一个接收函数作为参数并返回一个新函数的高阶函数。装饰器可以在不修改原函数代码的情况下,为其增加新的功能(如日志、计时、权限校验等)。

6.1 基本语法与原理

使用 @decorator_name 语法糖放在函数定义前。

def my_decorator(func):    # 接收一个函数作为参数def wrapper():         # 定义一个包装函数print("Something is happening before the function is called.")func()            # 执行原函数print("Something is happening after the function is called.")return wrapper         # 返回包装函数@my_decorator  # 这相当于: say_hello = my_decorator(say_hello)
def say_hello():print("Hello!")say_hello()
# 输出:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.

6.2 处理带参数的函数

为了让装饰器通用,内部的 wrapper 函数应使用 *args 和 **kwargs 来接受任意参数。

def decorator_with_args(func):def wrapper(*args, **kwargs):print("Decorator is working!")result = func(*args, **kwargs)  # 将参数原封不动传给原函数return resultreturn wrapper@decorator_with_args
def greet(name):print(f"Hello, {name}!")greet("World")

6.3 带参数的装饰器

如果要让装饰器本身也能接收参数,就需要再嵌套一层函数。

def repeat(num_times): # 装饰器工厂,接收参数def decorator_repeat(func): # 真正的装饰器def wrapper(*args, **kwargs):for _ in range(num_times):result = func(*args, **kwargs)return result # 通常返回最后一次调用的结果return wrapperreturn decorator_repeat@repeat(num_times=3)
def say_hi():print("Hi!")say_hi()
# 输出:
# Hi!
# Hi!
# Hi!

6.4 类装饰器

除了函数,类也可以作为装饰器,只需实现 __call__ 方法。

class CountCalls:def __init__(self, func):self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs): # 让实例变得可调用self.num_calls += 1print(f"Call {self.num_calls} of {self.func.__name__}")return self.func(*args, **kwargs)@CountCalls
def example():print("This is an example.")example()
example()
print(f"Function was called {example.num_calls} times.")
# 输出:
# Call 1 of example
# This is an example.
# Call 2 of example
# This is an example.
# Function was called 2 times.

总结

Python 的函数远不止是简单的代码块。从灵活的参数处理,到作为一等对象的特性,再到强大的迭代器、生成器和装饰器,它们共同构成了 Python 简洁而强大的表达能力。熟练运用函数能够加快开发工作的效率,也能在一定程度上提高代码的拓展性,是python中非常实用的功能。

http://www.lryc.cn/news/625495.html

相关文章:

  • 服务器Linux防火墙怎样实现访问控制
  • AAA服务器技术
  • 【实时Linux实战系列】基于实时Linux的智能工业机器人开发
  • 通过分布式系统的视角看Kafka
  • Lua学习记录 - 自定义模块管理器
  • 机械设备制造行业物联网智能化升级改造方案
  • 【habitat学习一】Habitat-Lab 配置键文档详解(CONFIG_KEYS.md)
  • 前端多环境变量配置全攻略:开发 / 测试 / 生产自动切换实战
  • APM32芯得 EP.29 | 基于APM32F103的USB键盘与虚拟串口复合设备配置详解
  • 清空 github 仓库的历史提交记录(创建新分支)
  • HUD抬头显示器太阳光模拟器设备用于杂散光测试介绍
  • 第4章 React状态管理基础
  • 【SpringBoot】Dubbo、Zookeeper
  • QT之QWaitCondition降低cpu占用率,从忙等待到高效同步
  • Qt——文件操作
  • Qt原对象系统工作机制
  • 基于 PyTorch 模型训练优化、FastAPI 跨域配置与 Vue 响应式交互的手写数字识别
  • SpreadJS 协同服务器 MongoDB 数据库适配支持
  • JavaSSM框架从入门到精通!第二天(MyBatis(一))!
  • EasyExcel 合并单元格最佳实践:基于注解的自动合并与样式控制
  • AI硬件英伟达选购的建议。
  • SSH 使用密钥登录服务器
  • 服务器无公网ip如何对外提供服务?本地网络只有内网IP,如何能被外网访问?
  • Netty内存池中ChunkList详解
  • 库卡机器人tag焊接保护气体流量控制系统
  • 基于SpringBoot的停车场管理系统【2026最新】
  • 在Ubuntu上安装并使用Vue2的基本教程
  • ComfyUI部署Wan2.2,开放API,文生视频与图生视频
  • Diamond开发经验(1)
  • Unity进阶--C#补充知识点--【C#各版本的新功能新语法】C#1~4与C#5