python学习22之函数式编程

''''''
'''
1.高阶函数:将函数作为参数传递到另一个函数中,作为这个函数的参数,这样的方式叫高阶函数
(1)map:两个参数,一个是函数,一个是iterator,将函数依次作用于Iterator中的每一个元素,结果返回一个Iterator
'''
#高阶函数举例
a=abs(-10) #abs()是python内置的取绝对值的函数
print(a)
f=abs #将函数abs本身赋值给变量f,也可以理解为将函数abs的函数名更改为f,这样就可以调用f来取代abs的功能
b=f(-10)
print(b)
#10
def add(x,y,f):
return f(x)+f(y)
s=add(-5,6,abs)
print(s)
#当我们调用add(-5, 6, abs)时,参数x,y和f分别接收-5,6和abs,根据函数定义,我们可以推导计算过程为:f(x) + f(y) ==> abs(-5) + abs(6) ==>11

#map
def f(x):
return x*x
L=map(f,[1,2,3,4,5,6])
print(L)
#<map object at 0x00000173F1012358> map()传入的第一个参数是f,即函数对象本身。由于结果L是一个Iterator(map),Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
print(list(L))
#[1, 4, 9, 16, 25, 36]

L1=list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(L1)
#['1', '2', '3', '4', '5', '6', '7', '8', '9']

'''
(2)reduce函数:它把一个函数作用在一个序列[x1, x2, x3, ...]上,
这个函数必须接收两个参数,比如参数函数f作用是乘积操作,reduce会把结果继续和序列的下一个元素做f乘积计算,其效果就是:
  reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
注意使用时先导包:from functools import reduce
'''
from functools import reduce
#应用:对一个数列(1到100的列表)求和
def add(x,y):
return x+y
L2=[]
for i in range(1,101):
L2.append(i)
sum=reduce(add,L2)
print(sum)

def normalize(LST):
# def lower(s):
# return s.lower() #全部小写函数 upper()全部大写函数

def capitalize(s):
return s.capitalize() #首字母大写函数,其余小写

return map(capitalize,LST)
L=['adam', 'LISA', 'barT']

r=normalize(L)
print(list(r))

'''
(3)filter:Python内建的filter()函数用于过滤序列。
filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

'''
def odd(i):
return i%2 != 0
li=[]
for i in range(1,101):
li.append(i)
li2=list(filter(odd,li))
print(li2)

#应用:用filter求素数
def _odd_iter(): #创建一个从3开始的初始序列
n = 1
while True:
n = n + 2
yield n

'''
yield:
作用:首先起到return的作用,函数结束,返回结果
其次起到生成器的作用:在Python中,这种一边循环一边计算的机制,称为生成器:generator。
最后带yield的函数才是真正的迭代器。
'''
g = (x * x for x in range(10))
#g就是一个生成器,我们想要得到g的每一个值,可以通过next()函数获得generator的下一个返回值:
print(next(g))
print(next(g))
print('*'*50)
#generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
#如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
#generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
#可以直接作用于for循环的对象统称为可迭代对象:Iterable.可以使用isinstance()判断一个对象是否是Iterable对象:
#而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
#可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
def _not_divisible(n):
return lambda x: x % n > 0 #筛选函数
def primes():
yield 2
it = _odd_iter() # 初始序列
while True:
n = next(it) # 返回序列的第一个数
yield n
it = filter(_not_divisible(n), it) # 构造新序列
# 打印100以内的素数:
for n in primes():
if n < 100:
print(n)
else:
break
'''
(4)sorted():
'''
#升序排列
L=[11,-15,22,9,35,-1,-5,79]
print(sorted(L))
#降序排列
print(sorted(L,reverse=True))
#可以当做高阶函数,传入函数为参
print(sorted(L,key=abs)) #按照绝对值大小去比较
#假设我们用一组tuple表示学生名字和成绩,请用sorted()对上述列表分别按名字排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[0]
print(sorted(L,key=by_name))
#再按成绩从高到低排序
def by_score(t):
return t[1]
print(sorted(L,key=by_score))
'''
2.返回函数——闭包
在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,
这种称为“闭包(Closure)”的程序结构拥有极大的威力。
'''
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
f=lazy_sum(1,2,3,4,5,6)
print(f)
print(f())
'''
<function lazy_sum.<locals>.sum at 0x0000020C2F455730>
21
'''
#利用闭包返回一个计数器函数,每次调用它返回递增整数。
def createCounter():
m = 0
def counter():
nonlocal m
m += 1
return m
return counter
cnt=createCounter()
print(cnt())
print(cnt())
print(cnt())
'''
global关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,
而nonlocal关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误

global关键字可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,global修饰后也可以直接使用,
而nonlocal关键字只能用于嵌套函数中,并且外层函数中定义了相应的局部变量,否则会发生错误
'''
'''
3.匿名函数
4.装饰器:在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
5.偏函数:functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
'''