一、高阶函数
e1. map
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
map接受的函数只能有一个参数
- 使用
# 计算平方def fn(x):return x * xdef power(list_):return list(map(fn, list_))print(power([1, 4, 5, 6]))# 输出[1, 16, 25, 36]
2. reduce
reduce() :reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算
# 导入reducefrom functools import reducedef add(x, y):return x + yprint(reduce(add, [1, 3, 5, 7, 9]))# 输出25
3. filter
过滤序列; filter()接收一个函数和一个序列, 然后根据返回值是True还是False决定保留还是丢弃该元素。
# 使用filter求素数'''# 素数: 质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。# 求素数的方法: 埃氏筛法# 筛选步骤:(1)先把1删除(现今数学界1既不是质数也不是合数)(2)读取队列中当前最小的数2,然后把2的倍数删去(3)读取队列中当前最小的数3,然后把3的倍数删去(4)读取队列中当前最小的数5,然后把5的倍数删去(5)如上所述直到需求的范围内所有的数均删除或读取'''# 实现算法# 1. 构造一个生成器来生成奇数序列def _odd_iter():n = 1while True:n = n + 2yield n# 2. 过滤的函数def _not_divisable(n_):return lambda x: x % n_ > 0# 与上述的lambda结果一样def _not_divisable_(n_):def fn(x):return x % n_ > 0return fn# 3. 定义一个返回素数的生成器def primes():# 先返回2素数yield 2it = _odd_iter() # 初始化序列while True:n = next(it) # 返回序列的第一个数yield nit = filter(_not_divisable(n), it) # 构造新序列def main():# 打印1000以内的素数:for n in primes():if n < 1000:print(n)else:breakif __name__ == '__main__':main()
4. sorted
函数定义: sorted(iterable, *, key=None, reverse=False)
第一个参数iterable 可迭代的对象;
- 后面为key/value参数对
第二个参数 key定义排序关键字函数
第三个参数为 reverse 是否把序列反转
- 调用排序
# 对list进行排序list_ = [1, 42, 0, 9, 4, 3, 82]print(sorted(list_))# 只要是 iterable 可迭代的对象就可调用sorted进行排序# 如dict, 但默认只对key排序dict_ = {"a": 1, "b": 3, "c": 1}print(sorted(dict_))
- 自定义排序的key函数
这个key关键字参数的值应该是一个接收单一参数的函数,并且该函数返回一个关键字用来比较排序
list_ = ['a', 'Z', 'b', 'C']# 按照ASCII的大小比较的,由于'Z' < 'a',结果,大写字母Z会排在小写字母a的前面。但忽略大小进行比较print(sorted(list_, key=str.lower))# 输出结果 ['a', 'b', 'C', 'Z']# 变为负数def negative(s):# 变负数的方法# s = ~s + 1s = -sreturn snums = [1, 5, 3, 7, 2]print("变为负数再比较 结果为:", sorted(nums, key=negative))# [7, 5, 3, 2, 1]
- 可以在排序后反转序列
new_list = sorted(list_, key=str.lower, reverse=True)print(new_list)# 输出结果 ['Z', 'C', 'b', 'a']
二、返回函数
函数作为返回值
- 把函数作为返回值
如懒加载进行求和
def lazy_sum(*args):def sum():ax = 0for n in args:ax = ax + nreturn axreturn sumsum = lazy_sum(*[1, 2, 3])# sum 的类型为函数print(type(sum))# 调用sum才完成求和print(sum())
闭包(Closure):是引用了自由变量的函数。
注意: 返回函数不要引用任何循环变量,或者后续会发生变化的变量。
练习:
利用闭包返回一个计数器函数,每次调用它返回递增整数:python引用变量的顺序: 当前作用域局部变量->外层作用域变量>当前模块中的全局变量->python内置变量python 对外层作用域变量只能读不能修改nonlocal关键字用来在函数或其他作用域中修改外层(非全局)变量
global关键字则是用于修改为全局变量
def createCounter():count = 0def counter():nonlocal countcount = count + 1print(id(count))return countreturn counter# 测试:counterA = createCounter()print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5counterB = createCounter()list_ = [counterB(), counterB(), counterB(), counterB()]print(list_)if list_ == [1, 2, 3, 4]:print('测试通过!')else:print('测试失败!')
三、匿名函数
lambda x: x * x
关键字lambda表示匿名函数,冒号前面的x表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
- 练习
# 练习:def is_odd(n):return n % 2 == 1L = list(filter(is_odd, range(1, 20)))# 改造为匿名函数L = list(filter(lambda x: x % 2 == 1, range(1, 20)))print(L)
四、装饰器
装饰器
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。
OOP的装饰模式需要通过继承和组合来实现,
而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。
Python的decorator可以用函数实现,也可以用类实现。
- 定义一个装饰器
def log(func):def wrapper(*args, **kw):print('call %s():' % func.__name__)return func(*args, **kw)return wrapperdef now():print('2015-3-25')# 自己调用装饰器;now = log(now)print(now.__name__) # 现在的函数now.__name__为wrappernow()
- 使用python有内置的装饰器语法 @来调用
@log # 相当于调用了 now = log(now)def now():print('2015-3-25')
- 缺点
- 问题: 使用装饰器 会使原函数的元信息不见了,比如函数的docstring、name、参数列表等信息
- 解决: 在包装函数前加上内置装饰器@functools.wraps(func) 可以把原来的元信息复制到包装函数中
import functoolsdef log(func):@functools.wraps(func)def wrapper(*args, **kw):print('call %s():' % func.__name__)return func(*args, **kw)return wrapperprint(now.__name__) # 使用@functools.wraps(func)后,函数的now.__name__为now
- 带参数的装饰器
# 带参数的装饰器,只要再包一层函数来保存def log(text):# 最外层函数来传递参数def decorator(fn):# 这里才装饰函数@functools.wraps(fn)def warpper(*args, **kwargs):print("call %s , log text : %s " % (fn.__name__, text))fun = fn(*args, **kwargs)return funreturn warpper# 检测对象text是否可被调用,# 如果没有调用text,则直接返回warpper对象引用,否则返回decorator对象引用if callable(text):return decorator(text)else:return decorator
