一、高阶函数

e1. map

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
map接受的函数只能有一个参数

  • 使用
  1. # 计算平方
  2. def fn(x):
  3. return x * x
  4. def power(list_):
  5. return list(map(fn, list_))
  6. print(power([1, 4, 5, 6]))
  7. # 输出
  8. [1, 16, 25, 36]

2. reduce

reduce() :reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算

  1. # 导入reduce
  2. from functools import reduce
  3. def add(x, y):
  4. return x + y
  5. print(reduce(add, [1, 3, 5, 7, 9]))
  6. # 输出
  7. 25

3. filter

过滤序列; filter()接收一个函数和一个序列, 然后根据返回值是True还是False决定保留还是丢弃该元素。

  1. # 使用filter求素数
  2. '''
  3. # 素数: 质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
  4. # 求素数的方法: 埃氏筛法
  5. # 筛选步骤:
  6. (1)先把1删除(现今数学界1既不是质数也不是合数)
  7. (2)读取队列中当前最小的数2,然后把2的倍数删去
  8. (3)读取队列中当前最小的数3,然后把3的倍数删去
  9. (4)读取队列中当前最小的数5,然后把5的倍数删去
  10. (5)如上所述直到需求的范围内所有的数均删除或读取
  11. '''
  12. # 实现算法
  13. # 1. 构造一个生成器来生成奇数序列
  14. def _odd_iter():
  15. n = 1
  16. while True:
  17. n = n + 2
  18. yield n
  19. # 2. 过滤的函数
  20. def _not_divisable(n_):
  21. return lambda x: x % n_ > 0
  22. # 与上述的lambda结果一样
  23. def _not_divisable_(n_):
  24. def fn(x):
  25. return x % n_ > 0
  26. return fn
  27. # 3. 定义一个返回素数的生成器
  28. def primes():
  29. # 先返回2素数
  30. yield 2
  31. it = _odd_iter() # 初始化序列
  32. while True:
  33. n = next(it) # 返回序列的第一个数
  34. yield n
  35. it = filter(_not_divisable(n), it) # 构造新序列
  36. def main():
  37. # 打印1000以内的素数:
  38. for n in primes():
  39. if n < 1000:
  40. print(n)
  41. else:
  42. break
  43. if __name__ == '__main__':
  44. main()

4. sorted

函数定义: sorted(iterable, *, key=None, reverse=False)
第一个参数iterable 可迭代的对象;

  • 后面为key/value参数对
    第二个参数 key定义排序关键字函数
    第三个参数为 reverse 是否把序列反转
  1. 调用排序
  1. # 对list进行排序
  2. list_ = [1, 42, 0, 9, 4, 3, 82]
  3. print(sorted(list_))
  4. # 只要是 iterable 可迭代的对象就可调用sorted进行排序
  5. # 如dict, 但默认只对key排序
  6. dict_ = {"a": 1, "b": 3, "c": 1}
  7. print(sorted(dict_))
  1. 自定义排序的key函数

这个key关键字参数的值应该是一个接收单一参数的函数,并且该函数返回一个关键字用来比较排序

  1. list_ = ['a', 'Z', 'b', 'C']
  2. # 按照ASCII的大小比较的,由于'Z' < 'a',结果,大写字母Z会排在小写字母a的前面。但忽略大小进行比较
  3. print(sorted(list_, key=str.lower))
  4. # 输出结果 ['a', 'b', 'C', 'Z']
  5. # 变为负数
  6. def negative(s):
  7. # 变负数的方法
  8. # s = ~s + 1
  9. s = -s
  10. return s
  11. nums = [1, 5, 3, 7, 2]
  12. print("变为负数再比较 结果为:", sorted(nums, key=negative))
  13. # [7, 5, 3, 2, 1]
  1. 可以在排序后反转序列
  1. new_list = sorted(list_, key=str.lower, reverse=True)
  2. print(new_list)
  3. # 输出结果 ['Z', 'C', 'b', 'a']

二、返回函数

函数作为返回值

  1. 把函数作为返回值
    如懒加载进行求和
  1. def lazy_sum(*args):
  2. def sum():
  3. ax = 0
  4. for n in args:
  5. ax = ax + n
  6. return ax
  7. return sum
  8. sum = lazy_sum(*[1, 2, 3])
  9. # sum 的类型为函数
  10. print(type(sum))
  11. # 调用sum才完成求和
  12. print(sum())
  1. 闭包(Closure):是引用了自由变量的函数。

  2. 注意: 返回函数不要引用任何循环变量,或者后续会发生变化的变量。

  3. 练习:

利用闭包返回一个计数器函数,每次调用它返回递增整数:python引用变量的顺序: 当前作用域局部变量->外层作用域变量>当前模块中的全局变量->python内置变量python 对外层作用域变量只能读不能修改nonlocal关键字用来在函数或其他作用域中修改外层(非全局)变量
global关键字则是用于修改为全局变量

  1. def createCounter():
  2. count = 0
  3. def counter():
  4. nonlocal count
  5. count = count + 1
  6. print(id(count))
  7. return count
  8. return counter
  9. # 测试:
  10. counterA = createCounter()
  11. print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
  12. counterB = createCounter()
  13. list_ = [counterB(), counterB(), counterB(), counterB()]
  14. print(list_)
  15. if list_ == [1, 2, 3, 4]:
  16. print('测试通过!')
  17. else:
  18. print('测试失败!')

三、匿名函数

lambda x: x * x
关键字lambda表示匿名函数,冒号前面的x表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

  1. 练习
  1. # 练习:
  2. def is_odd(n):
  3. return n % 2 == 1
  4. L = list(filter(is_odd, range(1, 20)))
  5. # 改造为匿名函数
  6. L = list(filter(lambda x: x % 2 == 1, range(1, 20)))
  7. print(L)

四、装饰器

装饰器
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。
OOP的装饰模式需要通过继承和组合来实现,
而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。
Python的decorator可以用函数实现,也可以用类实现。

  1. 定义一个装饰器
  1. def log(func):
  2. def wrapper(*args, **kw):
  3. print('call %s():' % func.__name__)
  4. return func(*args, **kw)
  5. return wrapper
  6. def now():
  7. print('2015-3-25')
  8. # 自己调用装饰器;
  9. now = log(now)
  10. print(now.__name__) # 现在的函数now.__name__为wrapper
  11. now()
  1. 使用python有内置的装饰器语法 @来调用
  1. @log # 相当于调用了 now = log(now)
  2. def now():
  3. print('2015-3-25')
  1. 缺点
  • 问题: 使用装饰器 会使原函数的元信息不见了,比如函数的docstring、name、参数列表等信息
  • 解决: 在包装函数前加上内置装饰器@functools.wraps(func) 可以把原来的元信息复制到包装函数中
  1. import functools
  2. def log(func):
  3. @functools.wraps(func)
  4. def wrapper(*args, **kw):
  5. print('call %s():' % func.__name__)
  6. return func(*args, **kw)
  7. return wrapper
  8. print(now.__name__) # 使用@functools.wraps(func)后,函数的now.__name__为now
  1. 带参数的装饰器
  1. # 带参数的装饰器,只要再包一层函数来保存
  2. def log(text):
  3. # 最外层函数来传递参数
  4. def decorator(fn):
  5. # 这里才装饰函数
  6. @functools.wraps(fn)
  7. def warpper(*args, **kwargs):
  8. print("call %s , log text : %s " % (fn.__name__, text))
  9. fun = fn(*args, **kwargs)
  10. return fun
  11. return warpper
  12. # 检测对象text是否可被调用,
  13. # 如果没有调用text,则直接返回warpper对象引用,否则返回decorator对象引用
  14. if callable(text):
  15. return decorator(text)
  16. else:
  17. return decorator