一、高阶函数
e1. map
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
map接受的函数只能有一个参数
- 使用
# 计算平方
def fn(x):
return x * x
def 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把结果继续和序列的下一个元素做累积计算
# 导入reduce
from functools import reduce
def add(x, y):
return x + y
print(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 = 1
while True:
n = n + 2
yield n
# 2. 过滤的函数
def _not_divisable(n_):
return lambda x: x % n_ > 0
# 与上述的lambda结果一样
def _not_divisable_(n_):
def fn(x):
return x % n_ > 0
return fn
# 3. 定义一个返回素数的生成器
def primes():
# 先返回2素数
yield 2
it = _odd_iter() # 初始化序列
while True:
n = next(it) # 返回序列的第一个数
yield n
it = filter(_not_divisable(n), it) # 构造新序列
def main():
# 打印1000以内的素数:
for n in primes():
if n < 1000:
print(n)
else:
break
if __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 + 1
s = -s
return s
nums = [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 = 0
for n in args:
ax = ax + n
return ax
return sum
sum = lazy_sum(*[1, 2, 3])
# sum 的类型为函数
print(type(sum))
# 调用sum才完成求和
print(sum())
闭包(Closure):是引用了自由变量的函数。
注意: 返回函数不要引用任何循环变量,或者后续会发生变化的变量。
练习:
利用闭包返回一个计数器函数,每次调用它返回递增整数:python引用变量的顺序: 当前作用域局部变量->外层作用域变量>当前模块中的全局变量->python内置变量python 对外层作用域变量只能读不能修改nonlocal关键字用来在函数或其他作用域中修改外层(非全局)变量
global关键字则是用于修改为全局变量
def createCounter():
count = 0
def counter():
nonlocal count
count = count + 1
print(id(count))
return count
return counter
# 测试:
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
counterB = 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 == 1
L = 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 wrapper
def now():
print('2015-3-25')
# 自己调用装饰器;
now = log(now)
print(now.__name__) # 现在的函数now.__name__为wrapper
now()
- 使用python有内置的装饰器语法 @来调用
@log # 相当于调用了 now = log(now)
def now():
print('2015-3-25')
- 缺点
- 问题: 使用装饰器 会使原函数的元信息不见了,比如函数的docstring、name、参数列表等信息
- 解决: 在包装函数前加上内置装饰器@functools.wraps(func) 可以把原来的元信息复制到包装函数中
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
print(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 fun
return warpper
# 检测对象text是否可被调用,
# 如果没有调用text,则直接返回warpper对象引用,否则返回decorator对象引用
if callable(text):
return decorator(text)
else:
return decorator