函数#
1. 参数#
形式参数(parameter):定义括号中的参数,用于接收参数用。
默认参数:含有等式的称为。
不要使用可变类型作为参数的默认值
实际参数(arguement):调用括号中的参数,用于传递给函数用。
# 求 x^n
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
print(power(3))
1.1. 可变参数#
参数 |
表示 |
调用 |
---|---|---|
可变参数 |
在参数前面加 |
本质为一个参数 tuple |
关键字参数 |
在参数前面加 |
本质为一个参数 dict |
命名关键字参数 |
在关键字参数前面加 |
可加入缺省值 |
注意:在生成器上使用
*
操作符可能会导致程序跑出内存而崩溃。
# a^2 + b^2 + c^2 + ……
# 计算的对象数目不确定
def calc(*numbers):
return sum(n * n for n in numbers)
# 也可先组装一个 list,再将该 list 传进去
nums = [1, 2, 3]
print(calc(*nums))
1.2. 关键字参数#
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
person('Michael', 30)
# 也可先组装出一个 dict,再把该 dict 传进去:
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra)
1.3. 命名关键字参数#
def person(name, age, *, city, job):
print(name, age, city, job)
person('Jack', 24, city='Beijing', job='Engineer')
2. 作用域#
函数内定义的变量为局部变量,只能通过所属函数调用函数外定义的变量为全局变量,所有函数均可调用。
当局部变量与全局变量名称相同时,优先调用局部变量
全局变量往往使用下划线命名
Python 使⽤由近及远的 LEGB 顺序来查找对象:locals -> enclosing function -> globals -> builtins
|
变量名赋值 |
|
---|---|---|
全局变量 |
值可变类型(list,dict,set) |
值不可变类型(num,str,tuple) |
修改全局变量 |
可通过函数修改、覆盖 |
只能使用 |
def spam():
eggs = 'spam'
def spam_global():
global eggs
eggs = 'spam'
eggs = 'global'
spam()
print(eggs)
spam_global()
print(eggs)
3. 返回值#
3.1. Lambda 表达式#
匿名函数 lambda(arg1, arg2, ...)
能接收多个参数,并返回一个表达式的值。
函数定义
def f(x):
return 2 * x + 1
# 等价于
f = lambda x: 2 * x + 1
函数调用
def calc(a, b, func):
result = func(a, b)
return result
num = calc(1, 2, lambda x, y: x + y)
print(num)
4. 改进#
4.1. 偏函数#
偏函数 functools.partial
把一个函数的某些参数设置默认值,返回一个新的函数,减少工作量。
若处理多国语言编写的文本,在比较或排序之前可能会想使用 unicode.normalize('NFC', s)
处理所有字符串 s
。若经常这么做,可以定义一个 nfc
函数。
import unicodedata, functools
nfc = functools.partial(unicodedata.normalize, 'NFC')
s1 = 'café'
s2 = 'cafe\u0301'
s1, s2 # ('café', 'café')
s1 == s2 # False
nfc(s1) == nfc(s2) # True
4.2. 备忘#
functools.lru_cache
是非常实用的装饰器,它实现了备忘(memoization)功能。这是一
项优化技术,它把耗时的函数的结果保存起来,避免传入相同的参数时重复计算。LRU 是 “Least Recently Used” 的缩写,表明缓存不会无限制增长,一段时间不用的缓存条目会被扔掉。
原浪费时间的地方很明显:fibonacci(1)
调用了 3 次,fibonacci(2)
调用了 2 次。
import functools
@functools.lru_cache()
def fibonacci(n):
return n if n < 2 else fibonacci(n - 2) + fibonacci(n - 1)
if __name__ == '__main__':
print(fibonacci(4))
functools.lru_cache(maxsize=128, typed=False)
可以使用两个可选的参数来配置。maxsize 参数指定存储多少个调用的结果。缓存满了之后,旧的结果会被扔掉,腾出空间。为了得到最佳性能,maxsize 应该设为 2 的幂。typed 参数若设为 True,把不同参数类型得到的结果分开保存。