目录
1. 默认参数值:让函数更加灵活
2. 关键字参数:清晰的调用方式
3. *args:拥抱不确定数量的位置参数
4. **kwargs:处理不确定数量的关键字参数
5. 参数解包:简化多参数的传递
6. 命名关键字参数:限制关键字参数
7. 局部变量与全局变量:理解作用域
8. 高级:装饰器(@decorator)
9. Lambda函数:简洁的匿名函数
10. Python 3.8+: 用:=操作符(walrus operator)简化逻辑
实践与优化小贴士
实践技巧
11. 缓存结果:functools.lru_cache
12. 参数类型注解:提升代码的可读性和工具支持
13. 递归优化:防止栈溢出
14. 避免全局变量,使用闭包或类
15. 性能优化:理解函数调用开销
结语
今天我们要一起探索的是Python函数参数的那些不为人知的高级玩法!对于Python初学者来说,掌握这些技巧不仅能让代码变得更加优雅,还能在性能优化上大显身手。准备好,让我们一步步揭开它们的神秘面纱。
1. 默认参数值:让函数更加灵活
默认参数值是Python的一大亮点,它允许函数调用时某些参数可以省略,提高函数的易用性。
def greet(name="匿名"):
print(f"你好,{name}!")
greet() # 输出:你好,匿名!
greet("小明") # 输出:你好,小明!
注意:默认参数值必须放在参数列表的末尾哦!
2. 关键字参数:清晰的调用方式
关键字参数允许你在调用函数时明确指定参数的名称,这在参数较多时非常有用。
def introduce(name, age):
print(f"我叫{name},今年{age}岁。")
introduce(age=25, name="张三") # 明确指定参数
3. *args:拥抱不确定数量的位置参数
当你不知道会有多少个参数传给函数时,*args就派上用场了,它收集所有多余的非关键字参数为一个元组。
def show_names(*names):
for name in names:
print(name)
show_names("Alice", "Bob", "Charlie") # 依次打印名字
4. **kwargs:处理不确定数量的关键字参数
类似地,**kwargs用于收集关键字参数,将它们组织成字典。
def display_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
display_info(name="李四", age=30) # 打印键值对
5. 参数解包:简化多参数的传递
当你有一个列表或字典,想要作为参数传递给函数时,* 和 ** 来帮忙。
nums = [1, 2, 3]
print(sum(*nums)) # 直接解包传递
info = {"name": "王五", "age": 28}
display_info(**info) # 字典解包
6. 命名关键字参数:限制关键字参数
通过在参数列表中放置星号(*),你可以强制之后的参数必须以关键字形式传递。
def example(a, b, *, c, d):
print(a, b, c, d)
example(1, 2, c=3, d=4) # 正确
example(1, 2, 3, 4) # 错误,c和d必须是关键字参数
7. 局部变量与全局变量:理解作用域
在函数内部定义的变量默认是局部变量,但如果使用global
关键字,可以将其声明为全局变量。
x = "外面的世界"
def change_x():
global x
x = "函数内部的改变"
change_x()
print(x) # 输出:函数内部的改变
8. 高级:装饰器(@decorator)
装饰器是一种高级用法,用于修改或增强函数的行为,无需直接修改函数代码。
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
def say_hello():
print("Hello!")
say_hello() # 观察装饰器的效果
9. Lambda函数:简洁的匿名函数
对于简单的函数需求,lambda表达式提供了一种更紧凑的定义方式。
double = lambda x: x * 2
print(double(5)) # 输出:10
10. Python 3.8+: 用:=操作符(walrus operator)简化逻辑
这个新特性允许在条件语句或循环中直接赋值并测试。
while (line := file.readline()) != '':
process(line)
实践与优化小贴士
-
使用默认参数时,避免将可变对象(如列表)作为默认值,以防意外的副作用。
-
在设计函数时,考虑参数的顺序和类型,以提高代码的可读性和健壮性。
-
装饰器可以用于性能监控、日志记录等,但过度使用会使代码难以理解。
-
熟练运用这些参数技巧,能让你的代码既简洁又强大。
实践技巧
11. 缓存结果:functools.lru_cache
在处理重复计算或者昂贵的函数调用时,使用lru_cache
可以显著提高效率。
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(30)) # 只计算一次,后续调用直接返回缓存结果
12. 参数类型注解:提升代码的可读性和工具支持
Python 3.5+ 引入了类型注解,虽然不会直接影响程序运行,但对于代码的维护和IDE的智能提示非常有帮助。
def greet(name: str) -> str:
return f"Hello, {name}!"
print(greet("World")) # IDE能识别类型,减少错误
13. 递归优化:防止栈溢出
递归函数虽然优雅,但需小心栈溢出。可以通过增加递归深度限制或转换为迭代解决。
def factorial(n, acc=1):
if n == 1:
return acc
else:
return factorial(n-1, acc*n) # 递归优化,减少调用次数
print(factorial(10)) # 更安全的递归
14. 避免全局变量,使用闭包或类
全局变量可能导致代码难以理解和维护。闭包或类可以封装状态,保持函数的纯净性。
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
click = counter()
print(click(), click()) # 使用闭包模拟状态
15. 性能优化:理解函数调用开销
Python中的函数调用是有一定开销的。在追求极致性能的场景下,考虑使用列表推导式、生成器表达式替代循环,或者利用Cython等工具编译关键部分。
# 列表推导式比循环快
squares = [i**2 for i in range(1000)]
结语
以上就是Python函数参数进阶用法的一些精选技巧,以及代码优化的实践建议。
好了,今天的分享就到这里了,我们下期见。