python函数式编程

照着廖雪峰的网站做笔记
高阶函数Higher-order function
变量可以指向函数,函数的参数能接收变量,若一个函数接收另一个函数作为参数,这种函数称之为高阶函数。
以下的介绍要注意,函数作为参数传递的时候只有函数的名字这个变量,不能加括号,自然不能在括号内加上参数名,加了括号就执行了,所以不能加括号!!
map
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。(注意:iterable就行,不一定是iterator,但是使用map函数的返回值就一定是iterator)

def f(x):
     return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
list(r)

结果(r是个iterator,要用list()函数把他计算出来)

[1, 4, 9, 16, 25, 36, 49, 64, 81]

用法:map(func_name,interable)
reduce
reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
用之前要from functools import reduce

def sum(a,b):
	return a+b
c=reduce(sum,[1,2,3,4,5])
print(c)#结果是15,也可以写成:
c=reduce(lambda x,y:x+y,[1,2,3,4,5])
print(c)#结果还是15

filter
用于设定条件,过滤序列。跟map一样,filter接收2个参数。一个是函数名字,一个是序列,返回结果是一个iterator。
用法:filter(func_name.iterable)
其中func_name函数返回值应该为true or false,这个函数分别作用于序列的每一个,若返回true,留着;若返回false,舍弃,最后生成一个iterator(不做计算,调用的时候再计算)。

def a(x):
    return x%2!=0
b=filter(a,[1,2,3,4,5,6,7,8,9])
print((list(b)))
#结果:
[1, 3, 5, 7, 9]

sorted
python内置的,可以直接用sorted(序列),此外sorted()也是一个高阶函数,可以接受一个key(key是个函数名字,这个函数分别作用于序列的每一项,然后把处理后的结果排序)

print(sorted([36, 5, -12, 9, -21], key=abs))#结果为:
[5, 9, -12, -21, 36]

函数作为返回值
python中函数当然可以作为另一个函数的返回值返回,一开始我觉得这理所当然,但是为什么要这么做呢?直接把这个函数的功能写在里面就行了嘛。后来看了装饰器的部分才理解,函数作为返回值的目的就是:
把功能先定义好,但是不执行,调用的时候再执行。
但是于一般的函数有点区别:一般函数只要输入固定,返回值就一定是一样的,但是函数作为返回值的话,输入一样的参数,返回的函数虽然功能一样,但是却不是一个函数,地址也不一样,分别调用2个函数互相不影响。

def sum(x,y):
    def sum2():
        return x+y
    return sum2
a=sum(2,3)
b=sum(2,3)
print(a)
print(b)
print(a())
print(b())

结果:

<function sum.<locals>.sum2 at 0x00000232A7505288>
<function sum.<locals>.sum2 at 0x00000232A7505318>
5
5

闭包closure
上面sum2函数中用了x,y,但是它们没有在sum2中定义,也没有作为sum2函数的参数,而是用了外层sum函数的参数。这种用了外层函数参数和外层函数局部变量的函数,就是内部的这个函数,叫做闭包。
闭包每次运行是能够记住引用的外部作用域的变量的值。
闭包不能引用循环变量和后续可能会变化的变量。

匿名函数
用法lambda a,b,c : a+b*clambda接着是函数参数,接着是冒号,再接着是一个表达式,这个匿名函数的返回值就是表达式的值。
记住lambda是一个函数,也是一个对象,跟普通函数一样的用法
如:a=lambda x : x*x或者a=(lambda x : x*x)(3)
前者返回的是一个函数对象,后者直接执行了,结果是9。

装饰器decorator
这部分看起来好理解,但是真正搞懂还是用了点时间,练习了几个例子。装饰器的目的是不动原来的函数,在这个函数的前后做一些操作,比如在前后加日志,把结果平方一下等等。
装饰器是一个函数,是一个把另一个函数作为参数,然后返回另一个函数变量的一个函数
格式是这样的:

def decorator(func):
	def wrapper(*args,**kws):
		statements...
		func(*args,**kws)
		statements...
	return wrapper
@decorator
def sum(x,y):
	return x+y

理解步骤如下:

  1. 装饰器是一个函数,参数是个函数,返回值是另一个函数,于是就有decorator(func)这个函数,返回值是另一个函数wrapper
  2. 下面我们定义将要被返回的这个函数,叫它wrapper吧,它的参数是(*args,**kws),因为内部执行你传入的那个func函数的时候要用。你返回的就是wrapper函数,调用的时候实际上就是wrapper(x,y),这样把x,y传进去,内部的func函数才能执行。
  3. 这个wrapper函数怎么定义就随便你了,可以先打印一行日志再执行func函数,然后没有返回值;也可以执行了func函数以后,返回func结果的平方。
    @decorator放在def sum(x,y):这个地方,相当于:
    sum=decorator(sum)
    所以decorator的参数必须为func。而wrapper函数的参数看实际情况,我认为写成(*args,**kws)这种形式只是为了方便,这样不管要装饰的函数有什么参数都可以传进去,如果没有参数你当然也可以不写。

如果装饰器本身也需要传入参数,比如日志内容啥的,怎么办?就再刚刚上面的外部,再加一个函数,这个刚加的函数就是接收参数用的。

def log(name)
	def decorator(func):
		def wrapper(*args,**kws):
			print(name)
			func(*args,**kws)
			statements...
		return wrapper
	return decorator
@log('john')
def sum(x,y):
	return x+y

这就相当于:sum=log('john')(sum)。里面该啥样还是啥样。
为了保持装饰前后函数的__name__等属性不变,所以加入@functools.wraps(func)

from functools import wraps
def decorator(func):
	@wraps(func)
	def wrapper(*args,**kws):
		statements...
		func(*args,**kws)
		statements...
	return wrapper

举例说明,下面写了4个装饰器:

def log1(func):#只是加了一个打印一行字的功能
    @wraps(func)
    def wrapper(*args,**kwargs):
        print('working...')
        return func(*args,**kwargs)#func加了括号,在返回这执行了
    return wrapper

def log2(name):#装饰器带了参数,所以外边加了一层
    def decorator(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            print(name)
            print('working...')
            return func(*args,**kwargs)
        return wrapper
    return decorator

def log3(name):#试试对函数结果做平方处理的装饰器
    def decotator2(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            print(name)
            print('working...')
            a=func(*args,**kwargs)
            return a*a
        return wrapper
    return decotator2

def log4(func):#只要返回wrapper函数就行,wrapper不一定有返回值
    @wraps(func)
    def wrapper(*args,**kwargs):
        print('working...')
        a=func(*args,**kwargs)#不一定非要在返回那里执行,在中间执行也可以
        print(a)
        print('done')
    return wrapper

分别装饰一个求和函数,看结果:

@log1
def sum(x,y):
    return x+y

a=sum(2,3)
print(a)
print(sum.__name__)#结果: working   5    sum
@log2('john')
def sum(x,y):
    return x+y

a=sum(2,3)
print(a)
print(sum.__name__)#结果:john working  5  sum
@log3('john')
def sum(x,y):
    return x+y

a=sum(2,3)
print(a)
print(sum.__name__)#结果:john working  25  sum
@log4
def sum(x,y):
    return x+y

# a=sum(2,3)
# print(a)
sum(2,3)
print(sum.__name__)#结果:working  5  done  sum

**偏函数 partial **
函数functools.partial可以创建偏函数,它的第一个参数是一个函数对象,剩下的参数就一一对应着传入那个函数的各个参数。就可以通过指定某些参数的值来创建一个固定部分参数值的新函数。用起来更方便。
如,创建一个100除以一个数的函数

from functools import partial
def devide(x,y):
    return x/y
a=partial(devide,100)
print(a(2))
#结果:50.0

如果:

def devide(x,y):
    return x/y
a=partial(devide,100,50)
print(a())
#结果为2.0

如果原函数有关键字参数,可以直接指定关键字参数的值。

from functools import partial
def cal(x,y,sum=False,mul=False):
    if sum==True:
        return x+y
    if mul==True:
        return x*y
a=partial(cal,mul=True)
print(a(4,5))
#结果为20

partial这个函数后面的参数一定要注意顺序。
map,reduce,partial等等这些把函数作为参数传入的时候,只需要传入函数的名字!!不用带括号和参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值