您的位置:首页 > 编程语言 > Python开发

PythonDay08(进阶)---函数式编程(二):匿名函数、装饰器详细介绍、偏函数

2019-03-04 14:51 459 查看
版权声明:https://blog.csdn.net/qq_43546676 https://blog.csdn.net/qq_43546676/article/details/88081609

Python之函数式编程(二)

1.返回函数

(1)一个函数可以返回一个计算结果,也可以返回一个函数。

(2)返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。

2.匿名函数

(1)关键字

lambda
表示匿名函数,匿名函数主要用来简化代码和避免函数名冲突。
说明:关键字
lambda
表示匿名函数,冒号前面的
x
表示函数参数。匿名函数有个限制,就是只能有一个表达式,不用写
return
,返回值就是该表达式的结果。
eg:

def f(x):
return x * x
#以上等价于
lambda x: x * x

(2)可以把匿名函数赋值给一个变量,再利用变量来调用该函数.
eg:

f = lambda x: x * x
f(5)

结果:

25

(3)可以把匿名函数作为返回值返回
eg:

def build(x, y):
return lambda: x * x + y * y

注意:整个匿名函数才可以赋值给遍量,而不是lambda

3.装饰器

说明:使用装饰器是为了不更改原来函数的定义的情况下,对该函数的功能进行扩展。这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
语法:先定义一个装饰器函数,假设为

outer()
,然后在所要装饰的函数的定义前一行加上
@ + 装饰函数名字
,这里为
@outer

知识补充:函数是一个对象,函数对象可以赋值给一个变量,所以,通过变量也能调用该函数。但是,函数对象有一个
__name__
属性,可以拿到函数的名字,就是拿到该变量现在所指向的函数对象的名字。
eg:

def a():        #定义该函数,做了两件事,1.函数名为a永远不会变 2.定义了一个变量a,并且a指向该函数
pass
len = abs           #len变量指向abs()函数
print(len(-30))     #指向函数的变量可以调用其所指向的函数对象
abs = a             #变量abs指向a()函数
print(len.__name__) #__name__属性可以获得该变量所指向的函数的函数名
print(abs.__name__)

结果:

30
abs
a

(1)装饰函数为内嵌函数(用的很多,基本上用这种模式)
eg:

def outer(func):
def inner():
print('参数func所指向的函数为{}'.format(func.__name__))
print('欢迎进入数据库!')
func()
print('断开数据库,再见!')
print('参数func所指向的函数为{}'.format(func.__name__))
return
return inner

@outer
def myfunc():
print('正在处理数据')

myfunc()

结果:

参数func所指向的函数为myfunc
欢迎进入数据库!
正在处理数据
断开数据库,再见!
参数func所指向的函数为myfunc

解释一下,装饰器的运行过程:
①把

myfunc
作为参数,传入装饰函数
outer()
中,此时,
myfunc
func
同时指向
func()
函数
②执行
outer()
函数。执行
outer()
函数时,遇到函数
inner()
,先将
inner()
函数,读入内存中(不执行,函数是被调用的时候才执行),返回函数
inner()

③此时,
myfunc
=
inner
,也就是,
myfunc、inner
同时指向
inner()
函数
myfunc()
语句,
myfunc
指向的是
inner()
函数,所以,该语句是调用
inner()
函数
注意:内嵌函数可以调用内嵌该函数的“外部变量”,所以,这里,inner()函数中可以用func变量.
(2)装饰函数不为内嵌函数(用的很少,基本不用)
eg:

def outer(func):
print('参数func所指向的函数为{}'.format(func.__name__))
print('欢迎进入数据库!')
func()
print('断开数据库,再见!')
print('参数func所指向的函数为{}'.format(func.__name__))
return func

@outer
def myfunc():
print('正在处理数据')

myfunc()

结果:

参数func所指向的函数为myfunc
欢迎进入数据库!
正在处理数据
断开数据库,再见!
参数func所指向的函数为myfunc正在处理数据

逻辑有点不对,我只是想表面这样是可以实现的。
(3)对带参数的函数进行装饰
eg:

def outer(func):
def inter(name, thing):
print('欢迎进入数据库!')
func(name, thing)
print('断开数据库,再见!')
return
return inter

@outer
def myfunc(name, thing):
print('{}正在使用数据库处理{}'.format(name, thing))
myfunc('wang', 'web')

结果:

欢迎进入数据库!
wang正在使用数据库处理web
断开数据库,再见!

(4)对参数数量不确定的函数进行装饰
eg:
def outer(func):
def inter(*args, **kw):
return func(*args, **kw)
return inter

@outer
def myfunc(*args, **kw):
print(args)
print(kw)
return args[0]

a = myfunc(1, 2, 3, city='Beijing')
print(a)

结果:

(1, 2, 3)
{'city': 'Beijing'}
1

(5)让装饰器带参数
说明:就是先执行带参数的装饰函数,将返回值所指向的函数再装饰函数
eg:

def tt(name):
print('我是{}'.format(name))
def outer(func):
def inter(*args, **kw):
return func(*args, **kw)
return inter
return outer     #注意这里应该返回装饰器

@tt('wanghao')
def myfunc(*args, **kw):
print(args)
print(kw)
return args[0]

a = myfunc(1, 2, 3, city='Beijing')
print(a)

结果:

我是wanghao
(1, 2, 3)
{'city': 'Beijing'}
1

解释:
①先执行函数

tt()
:执行
print('我是{}'.format(name))
语句,然后,读取函数
outer()
到内存中,返回
outer

②用
@outer
来装饰函数
myfunc()

(6)多个装饰器装饰同一个函数
说明:装饰器是从下往上执行的,(先贴近函数的装饰器先执行)
eg:

def decorator_a(func):
print('Get in decorator_a')
def inner_a(*args, **kwargs):
print('Get in inner_a')
return func(*args, **kwargs)
return inner_a

def decorator_b(func):
print('Get in decorator_b')
def inner_b(*args, **kwargs):
print('Get in inner_b')
return func(*args, **kwargs)
return inner_b

@decorator_b
@decorator_a
def f(x):
print('Get in f')
return x * 2

f(1)

结果:

Get in decorator_a
Get in decorator_b
Get in inner_b
Get in inner_a
Get in f

解释:依次执行

decorator_a()
,
decorator_b()
,
inner_b()
,
inner_a()
,有点先从下到上,再从上到下的感觉。(实际执行过程只有从下到上,是指针的传递让我们感觉后面又从上到下)
再举一个例子:
eg:

def outer1(func):
def inter1(name, thing):
print('您好!')
print('正在连接数据库')
func(name, thing)
return inter1

def outer2(func):
def inter2(name, thing):
func(name, thing)
print('正在断开数据库')
print('再见!')
return
return inter2

@outer2
@outer1
def f(name, thing):
print('{}正在做{}'.format(name, thing))
f('wanghao', 'shi')

结果:

您好!
正在连接数据库
wanghao正在做shi
正在断开数据库
再见!

多个装饰器的参考连接

4.偏函数

说明:当函数的参数个数太多,需要简化时,使用

functools.partial
可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,即修改函数的默认值,从而在调用时更简单。
eg:

import functools

#int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:
print(int('1000'))
int2 = functools.partial(int, base = 2)
print(int2('1000'))

#结果:
1000
8
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: