关注我不迷路,您的点赞+收藏,就是我坚持的动力!
引言:为什么函数如此重要
在前端开发中,我们习惯将UI拆分为可复用的组件。
在Python中,函数就是我们的“逻辑组件” — 它们封装特定功能,可以在不同地方重复使用,让代码更模块化、更易维护。
文章目录
一、Python函数基础
函数是一段可以重复使用的代码块,它接收输入(参数),执行特定任务,然后返回结果。
关键字为def,代表定义一个函数。
函数的基本结构如下:
def 函数名(参数):
# 函数体(执行具体操作)
return 返回值
1.1 函数参数
函数的参数简单分为:
1)必须参数:调用时必须提供
2)默认参数:可以不提供,使用默认值
必须参数分为:
I. 位置参数:按照参数的位置依次传递的参数。
def describe_pet(animal_type, pet_name):
print(f"I have a {animal_type} named {pet_name}.")
# 示例
describe_pet("cat", "大白猫") # I have a cat named 大白猫.
II. 关键字参数:通过参数名指定传递的参数,可以不按照顺序传递。
def describe_pet(pet_name="Whiskers", animal_type="cat"):
print(f"I have a {animal_type} named {pet_name}.")
# 示例
describe_pet(pet_name= "大白猫") #I have a cat named 大白猫.
III. 可变参数:
*args:可变位置参数,可以接收任意数量的位置参数,存储为一个元组。
**kwargs:可变关键字参数,可以接收任意数量的关键字参数,存储为一个字典
# 可变参数 *args
def make_pizza(*toppings):
print("Making pizza with:")
for topping in toppings:
print(f"- {topping}")
make_pizza("pepperoni", "cheese", "mushrooms")
'''
Making pizza with:
- pepperoni
- cheese
- mushrooms
'''
# 关键字可变参数 **kwargs
def build_profile(first, last, **user_info):
profile = {'first_name': first, 'last_name': last}
profile.update(user_info)
return profile
# 示例
rest = build_profile('albert', 'einstein', location='princeton', field='physics')
print(rest)
# {'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
默认参数,即参数存在默认值,且为可选项,传递与否不影响
def make_shirt(size="L", message="I love Python"):
print(f"Size: {size}, Message: {message}")
# 示例
make_shirt() # Size: L, Message: I love Python
make_shirt("M", "I don't know") # Size: M, Message: I don't know
make_shirt(message="HAHAHA") # Size: L, Message: HAHAHA
2.2 函数返回值
在Python中,函数使用return语句返回值,如果没有return语句,函数默认返回None。
返回值可以是任意类型,包括数字、字符串、列表、字典、甚至是函数或类实例。
1)返回数字
def add(a, b)
return a+b
2)返回多个值:实际返回的是元组
def get_point(a = 10, b = 10):
x = a
y = b
return x, y
# 示例
point = get_point(10, 20)
print(point) #(10, 20)
x_val, y_val = get_point(10, 20) # x_val:10, y_val: 20
print(x_val) # 10
print(y_val) # 20
3)返回函数:闭包
def multiplier(factor):
def multiply(x):
return x * factor
return multiply
# 示例
double = multiplier(2)
print(double(5)) # 输出: 10
二、匿名函数:lambda
lambda函数是一种小型匿名函数。是一种简洁的定义单行函数的方式,可以接受任意数量的参数,但只能有一个表达式。
通常用于定义简单的、不会重复使用的函数,复杂函数请使用def定义常规函数。
2.1 基本语法:
# Lambda函数定义
lambda 参数1, 参数2..., 参数N: 表达式
# 示例
# 普通函数:计算长方形面积
def 计算面积(长, 宽):
return 长 * 宽
# Lambda版本
面积计算器 = lambda 长, 宽: 长 * 宽
print(f"面积: {面积计算器(5, 3)}") # 输出:面积: 15
2.2 常见使用场景
1)场景1:简单数学运算
add = lambda a, b: a + b # 加法
is_even = lambda x: x % 2 == 0 # 偶数
2)场景2:配合map进行数据处理流水线处理
users = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30},
{"name": "Charlie", "age": 20}
]
# 获取用户年龄列表
ages = map(lambda user: user["age"], users) # map object
print(list(ages)) # [25, 30, 20]
3)场景3:配合sort进行排序‘
users = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30},
{"name": "Charlie", "age": 20}
]
# 根据年龄排序
users.sort(key=lambda user: user["age"])
print(users)
# [{'name': 'Charlie', 'age': 20}, {'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]
4)场景4:条件表达式
grade_eval = lambda score: "优" if score >= 90 else "良" if score >= 60 else "不及格"
score = 80
print(grade_eval(score)) # 良
三、高阶函数:Python的函数式编程武器
高阶函数是指可以接收函数作为参数 或 返回函数作为结果的函数。
常用高阶函数如下
3.1 map():数据转换
map()函数,接收一个函数和一个或多个可迭代对象作为参数,然后将传入的函数依次作用到可迭代对象的每个元素上,并返回一个map对象(迭代器)。
map() 的核心思想是 “映射”,把一个函数应用到序列的每个元素上,生成一个新的map对象。
为了看到map()的结果,我们通常将它转换为列表或其他可迭代对象。
# 使用语法
map(function, iterable1, ...iterableN)
# 示例
# 基础用法:转换列表
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
# 结果:[1, 4, 9, 16, 25]
# 实际应用:数据清洗
prices = ["$10.99", "$23.50", "$7.25", "invalid"]
clean_prices_map = map(lambda p: float(p.replace("$", "")) if p.startswith("$") else None, prices)
clean_prices = list(clean_prices_map)
# 结果:[10.99, 23.5, 7.25, None]
3.2 filter():数据筛选
filter函数用于从序列中筛选出满足指定条件的元素。它遍历序列中的每个元素,只保留那些通过"测试"的元素,过滤掉不符合条件的元素。
filter() 的核心思想是 “过滤” 或 “筛选”,拥有惰性求值的策略,仅在实际请求元素时才进行计算,可节省内存。
# 使用语法
filter(function, iterable)
# 示例
# 基础用法:筛选偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
# 结果:[2, 4, 6, 8, 10]
# 实际应用:过滤无效数据
data = [
{"id": 1, "active": True},
{"id": 2, "active": False},
{"id": 3, "active": True},
{"id": 4, "active": False}
]
active_users = list(filter(lambda user: user["active"], data))
# 结果:[{"id": 1, "active": True}, {"id": 3, "active": True}]
3.3 reduce():数据聚合
reduce()函数,用于对序列中的元素进行累积运算。它通过一个接收两个参数的函数,先对序列的前两个元素进行操作,然后将结果与下一个元素继续操作,如此累积下去,最终将整个序列缩减为单个值。
reduce() 的核心思想是 “归约” 或 “累积”。
Python 3 中,reduce() 已移到 functools 模块,需要导入使用。
# 语法 initializer为初始值,可选
reduce(function, iterable[, initializer])
# 示例
from functools import reduce
# 计算累加
numbers = [1, 2, 3, 4, 5]
sum_result = reduce(lambda acc, curr: acc + curr, numbers, 0)
# 结果:15
# 计算乘积
product = reduce(lambda acc, curr: acc * curr, numbers, 1)
# 结果:120
# 查找最大值
max_value = reduce(lambda a, b: a if a > b else b, numbers)
# 结果:5
3.4 sorted():灵活排序工具
sorted() 用于对任何可迭代对象进行排序,返回一个新的已排序列表,而不会修改原始数据。
sorted() 使用 Timsort 算法(一种混合排序算法):接收可迭代对象并创建其元素的列表副本,根据 key 参数提取比较键,按照指定的顺序(升序或降序)对元素进行排序,返回包含排序后元素的新列表。
# 语法
sorted(iterable, key=None, reverse=False)
# key 排序条件
# reverse 排序方向,默认升序 false
# 自定义排序规则
students = [
{"name": "Alice", "grade": 85, "age": 20},
{"name": "Bob", "grade": 92, "age": 22},
{"name": "Charlie", "grade": 78, "age": 19}
]
# 按成绩降序,年龄升序排序
sorted_students = sorted(
students,
key=lambda s: (-s["grade"], s["age"])
)
四、函数常见使用场景
场景1:数据处理管道
假定一个电商价格处理场景,要筛选出有效的价格,并进行折扣处理,最后统计信息。经历数据过滤 -> 数据转换 -> 数据聚合的完整流程。
# 电商价格处理流程
def process_prices(prices):
# 1. 过滤负数和零
valid_prices = filter(lambda p: p > 0, prices)
# 2. 应用折扣
discounted = map(lambda p: p * 0.9, valid_prices)
# 3. 计算统计信息
stats = {
'count': 0,
'total': 0,
'max': float('-inf'),
'min': float('inf')
}
def update_stats(acc, price):
acc['count'] += 1
acc['total'] += price
acc['max'] = max(acc['max'], price)
acc['min'] = min(acc['min'], price)
return acc
return reduce(update_stats, discounted, stats)
# 使用示例
prices = [100, 200, -50, 150, 0, 300]
result = process_prices(prices)
print(result) # {'count': 4, 'total': 675.0, 'max': 270.0, 'min': 90.0}
场景2:配置化行为
假定一个支付处理系统中的场景应用,每种支付方式有不同的手续费计算规则。
使用策略模式,通过lambda表达式来实现不同的支付策略,展示了使用函数式编程实现灵活、可扩展的算法选择机制。
# 策略模式:根据不同条件选择不同算法
# 创建支付处理器
def create_payment_processor(strategy_type):
strategies = {
'credit_card': lambda amount: f"信用卡支付 ${amount},手续费 ${amount * 0.03:.2f}",
'paypal': lambda amount: f"PayPal支付 ${amount},手续费 ${amount * 0.02:.2f}",
'alipay': lambda amount: f"支付宝支付 ${amount},手续费 ${amount * 0.01:.2f}"
}
return strategies.get(strategy_type, lambda amount: f"未知支付方式: ${amount}")
# 使用示例
processor = create_payment_processor('alipay')
print(processor(100)) # 支付宝支付 $100,手续费 $1.00
场景3:事件驱动架构
假定要实现一个简单的事件总线系统,用于处理事件的发布和订阅。
我们创建了一个EventBus类,它有两个主要方法:subscribe(订阅事件)和emit(触发事件)。
这个系统允许多个处理函数订阅同一个事件类型,当事件被触发时,所有订阅了该事件的处理函数都会被调用。
# 简单的事件总线系统
class EventBus:
def __init__(self):
self.handlers = {}
# 订阅事件 - 普通函数
def subscribe(self, event_type, handler):
if event_type not in self.handlers:
self.handlers[event_type] = []
self.handlers[event_type].append(handler)
# 触发事件 - 普通函数
def emit(self, event_type, *args, **kwargs):
if event_type in self.handlers:
for handler in self.handlers[event_type]:
handler(*args, **kwargs)
# 使用示例
bus = EventBus()
# 订阅事件
bus.subscribe('user_login', lambda user: print(f"日志: {user} 登录了"))
bus.subscribe('user_login', lambda user: print(f"欢迎 {user}!"))
bus.subscribe('user_logout', lambda user: print(f"再见 {user}!"))
# 触发事件
bus.emit('user_login', 'Alice')
# 输出:
# 日志: Alice 登录了
# 欢迎 Alice!
五、常见高频面试题
问题1:实现函数柯里化
要求:将多参数函数转换为一系列单参数函数。
A:柯里化是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
柯里化的工作原理:
1)定义一个内部函数 curried,它接受任意数量的参数(*args)。
2)检查已经传入的参数数量(len(args))是否大于等于原始函数(func)所需要的参数数量(func.code.co_argcount)。
2.1)如果是,则说明参数已经足够,直接调用原始函数并返回结果。
2.2)如果参数不够,则返回一个新的函数,这个函数接受更多的参数(*more_args),然后递归调用 curried,并将之前的参数和新的参数合并。
def curry(func):
def curried(*args):
if len(args) >= func.__code__.co_argcount:
return func(*args)
return lambda *more_args: curried(*(args + more_args))
return curried
# 使用示例
@curry
def add_three(a, b, c):
return a + b + c
# 多种调用方式
print(add_three(1, 2, 3)) # 6
print(add_three(1)(2)(3)) # 6
print(add_three(1, 2)(3)) # 6
问题2:实现compose函数(函数组合)
要求:实现函数组合,将多个函数组合成一个新函数。
A:compose函数接受任意数量的函数作为参数,然后返回一个新的函数,这个新的函数会按照从右向左的顺序依次应用这些函数。
def compose(*funcs):
# 处理边界情况
if not funcs:
return lambda x: x
# 仅一个函数,返回函数本身
if len(funcs) == 1:
return funcs[0]
# 创建组合函数
def composed(arg):
result = arg
# 从右向左执行
for func in reversed(funcs):
result = func(result)
return result
return composed
# 使用示例
def add_one(x):
return x + 1
def double(x):
return x * 2
def square(x):
return x ** 2
# 组合函数:先加1,再平方,再翻倍
transform = compose(double, square, add_one)
print(transform(2)) # 18: (2+1)^2 * 2
六、总结
核心要点回顾
· 函数是Python的一等公民:可以赋值、传递、返回
· lambda是简洁的匿名函数:适合简单操作和函数式编程
· 高阶函数提升代码表达能力:map、filter、reduce、sorted等
· 函数式编程思维:关注"做什么"而不是"怎么做"
编码建议
· 对于复杂的、可重用的功能,使用普通函数。
· 对于简单的、一次性的操作,考虑使用匿名函数,但要注意可读性。
· 尽量使用内置函数来完成常见任务,提高效率和代码简洁性。
下一期预告
下一篇我们将深入学习Python高级特性之装饰器的原理和应用。
装饰器是 Python 中一个强大且优雅的特性,它允许我们以简洁的方式增强函数或类的功能。
掌握装饰器对于编写高质量的 Python 代码和理解高级 Python 代码库至关重要
如果觉得有帮助,请关注+点赞+收藏,这是对我最大的鼓励!
如有问题,请评论区留言
2829

被折叠的 条评论
为什么被折叠?



