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

导读:本篇文章讲解 PythonDay08(进阶)—函数式编程(二):匿名函数、装饰器详细介绍、偏函数,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

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.闭包

闭包,顾名思义,就是一个封闭的包裹,里面包裹着自由变量,就像在类里面定义的属性值一样,自由变量的可见范围随同包裹,哪里可以访问到这个包裹,哪里就可以访问到这个自由变量。

闭包首先要定义一个嵌套函数,并且外面的函数返回内部函数的函数名,见下面例子:

def nth_power(exponent):
    def exponent_of(base):
        return base ** exponent
    return exponent_of # 返回值是 exponent_of 函数

square = nth_power(2)
cube = square(3)
print(cube) # 9

这里的 square就是一个闭包,闭包本质上是一个函数,它有两部分组成,内部函数和外部函数与内部函数之间的变量。这里为exponent_of函数和变量 exponent。闭包使得这些变量的值始终保存在内存中。

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()中,此时,myfuncfunc同时指向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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/84817.html

(0)
小半的头像小半

相关推荐

极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!