Python 函数完全指南:参数、返回值与高级用法
·
# Python 函数完全指南:参数、返回值与高级用法
函数是代码复用的基础。学了函数才知道,Python 写得漂亮的人是怎么把代码组织得那么优雅的。这篇文章把我踩过的坑和实战经验全部分享出来。
函数是什么
简单说,函数就是把一段可以重复使用的代码打包起来,给它起个名字,以后想用就直接调用。
# 定义函数
def greet():
print("你好!")
# 调用函数
greet() # 输出: 你好!
函数参数详解
位置参数
按顺序传递,顺序很重要:
def introduce(name, age, city):
print(f"我叫{name},今年{age}岁,来自{city}")
introduce("张三", 25, "北京")
# 我叫张三,今年25岁,来自北京
# 顺序错了,结果就错了
introduce("北京", 25, "张三") # 不对!
关键字参数
指定参数名传递,顺序无所谓:
introduce(age=25, city="北京", name="张三")
# 我叫张三,今年25岁,来自北京
默认参数
给参数设置默认值:
def greet(name, greeting="你好"):
print(f"{greeting},{name}!")
greet("张三") # 你好,张三!
greet("李四", "早上好") # 早上好,李四!
# 默认参数要放最后
# def wrong(a=1, b): # 错误!
# def correct(a, b=2): # 正确!
可变参数 *args
不知道会传几个参数时用 *args:
def sum_all(*numbers):
total = 0
for n in numbers:
total += n
return total
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20)) # 30
print(sum_all()) # 0
# args 是元组
def print_args(*args):
print(type(args)) # <class 'tuple'>
for arg in args:
print(arg)
关键字参数 **kwargs
传递任意数量的关键字参数:
def print_info(**info):
print(type(info)) # <class 'dict'>
for key, value in info.items():
print(f"{key}: {value}")
print_info(name="张三", age=25, city="北京")
# name: 张三
# age: 25
# city: 北京
# 结合使用
def func(*args, **kwargs):
print("位置参数:", args)
print("关键字参数:", kwargs)
func(1, 2, 3, name="张三", age=25)
# 位置参数: (1, 2, 3)
# 关键字参数: {'name': '张三', 'age': 25}
返回值
基本返回
def add(a, b):
return a + b
result = add(3, 5)
print(result) # 8
# 没有 return 返回 None
def no_return():
print("只打印不返回")
print(no_return()) # None
多返回值
Python 函数可以返回多个值(实际是元组):
def divide(a, b):
quotient = a // b
remainder = a % b
return quotient, remainder
q, r = divide(10, 3)
print(f"商: {q}, 余数: {r}") # 商: 3, 余数: 1
# 也可以接收为元组
result = divide(10, 3)
print(result) # (3, 1)
Lambda 表达式
lambda 是匿名函数,适合简单函数:
# 普通函数
def square(x):
return x ** 2
# lambda 版本
square = lambda x: x ** 2
print(square(5)) # 25
# 结合内置函数使用
numbers = [5, 2, 8, 1, 9]
# sorted 配合 lambda 按绝对值排序
sorted_nums = sorted(numbers, key=lambda x: -x) # 降序
print(sorted_nums) # [9, 8, 5, 2, 1]
# map 配合 lambda
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # [10, 4, 16, 2, 18]
# filter 配合 lambda
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 8]
装饰器
装饰器可以在不修改原函数的情况下,给函数添加新功能:
入门装饰器
# 定义装饰器
def my_decorator(func):
def wrapper():
print("调用函数之前")
func()
print("调用函数之后")
return wrapper
# 使用装饰器
@my_decorator
def say_hello():
print("你好!")
say_hello()
# 调用函数之前
# 你好!
# 调用函数之后
# 相当于:
# say_hello = my_decorator(say_hello)
带参数的装饰器
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(times=3)
def greet(name):
print(f"你好,{name}!")
greet("张三")
# 你好,张三!
# 你好,张三!
# 你好,张三!
functools.wraps
保留原函数的信息:
import functools
def my_decorator(func):
@functools.wraps(func) # 保留原函数信息
def wrapper(*args, **kwargs):
print("开始")
return func(*args, **kwargs)
return wrapper
@my_decorator
def add(a, b):
"""返回两数之和"""
return a + b
print(add.__name__) # add(而不是 wrapper)
print(add.__doc__) # 返回两数之和(保留了原函数的文档)
实战案例
案例1:计时器
import time
import functools
def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 执行耗时: {end - start:.2f}秒")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
print("执行完成")
slow_function()
# 执行完成
# slow_function 执行耗时: 1.00秒
案例2:参数验证
def validate(**rules):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for param, condition in rules.items():
if param in kwargs:
value = kwargs[param]
if 'min' in condition and value < condition['min']:
raise ValueError(f"{param} 不能小于 {condition['min']}")
if 'max' in condition and value > condition['max']:
raise ValueError(f"{param} 不能大于 {condition['max']}")
if 'type' in condition and not isinstance(value, condition['type']):
raise TypeError(f"{param} 必须是 {condition['type']}")
return func(*args, **kwargs)
return wrapper
return decorator
@validate(age={'min': 0, 'max': 150, 'type': int}, name={'type': str})
def register(name, age):
print(f"注册成功: {name}, {age}岁")
register(name="张三", age=25) # 正常
register(name="李四", age=-5) # ValueError: age 不能小于 0
案例3:缓存装饰器
def cache(func):
cache_dict = {}
@functools.wraps(func)
def wrapper(*args):
if args in cache_dict:
print(f"命中缓存: {args}")
return cache_dict[args]
result = func(*args)
cache_dict[args] = result
return result
return wrapper
@cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10)) # 55(计算)
print(fibonacci(10)) # 命中缓存:55(直接从缓存取)
我踩过的坑
坑1:默认参数用可变对象
# 错误!默认参数是可变对象会被共享
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2](不是 [2]!)
print(add_item(3)) # [1, 2, 3]
# 正确做法
def add_item_correct(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item_correct(1)) # [1]
print(add_item_correct(2)) # [2]
print(add_item_correct(3)) # [3]
坑2:lambda 中的变量作用域
# lambda 中的变量是延迟绑定的
funcs = [lambda x: x + i for i in range(3)]
print([f(0) for f in funcs]) # [3, 3, 3](不是你期望的 [0, 1, 2]!)
# 正确做法:立即绑定参数
funcs = [lambda x, i=i: x + i for i in range(3)]
print([f(0) for f in funcs]) # [0, 1, 2]
坑3:装饰器顺序
@decorator1
@decorator2
def func():
pass
# 相当于:func = decorator1(decorator2(func))
# 所以执行顺序是:func -> decorator2 -> decorator1
写在最后
函数是 Python 编程的灵魂。掌握好参数传递、返回值、lambda 和装饰器,你的代码会变得简洁又优雅。
我的经验是:好的函数应该做一件事,而且做好这件事。
有帮助的话点个赞,有问题评论区见!
更多推荐



所有评论(0)