15036188778

您所在位置: 首页> 学习课程> python培训 | python基础:匿名函数、闭包、装饰器该怎么用?

python培训 | python基础:匿名函数、闭包、装饰器该怎么用?

发布百知教育 来源:学习课程 2019-11-19

一、匿名函数

高级函数回顾:
1.接受一个或多个函数作为参数(在函数中传递函数代码);
2.将函数作为参数返回。
内置函数
filter(),参数中传入可迭代的结构,即filter(function,iterable),可以从序列中过滤出符合条件的元素,保存到一个新的序列中。
参数function:传递函数
参数iterable:需要过滤的序列
返回值:过滤后的新序列。

l = [1,2,3,4,5,6,7,8,9,10]
def tri(n):
    if n % 3 == 0:
        return True
print(list(filter(tri,l)))

打印出[3, 6, 9]

1.匿名函数:

又称lambda表达式。
lambda函数表达式专门用来创建一些简单的函数,是创建函数的另外一种形式。
语法:
lambda 参数列表:返回值

result = lambda a,b:a+b
print(result)

打印

<function <lambda> at 0x0000024C52FF2EE8>

可见,函数没有名字,所以叫匿名函数。
传入参数

result = lambda a,b:a+b
print(result(10,20))

打印30

def fn(a,b):
    return a + b
print(fn(10,20))

效果是一样的,但是更简洁。

l = [1,2,3,4,5,6,7,8,9,10]
tri = lambda i:i%3==0
r = filter(tri,l)
print(list(r))

与上面tri()函数的效果是一致的。
lambda匿名函数俗称语法糖,可以减少代码量和优化程序,减少内存消耗。

2.map()函数:

可以对可迭代对象中的所有元素做指定操作,然后将其添加到一个新的对象返回。
匿名函数一般都是作为参数使用,其他地方一般不用。

l = [1,2,3,4,5,6,7,8,9,10]
r = map(lambda i:i+1,l)
print(list(r))

打印[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

3.sort()方法:

该方法用来对列表中的元素进行排序,直接默认比较列表中元素的大小。
在该方法中可以接受一个关键字参数,即一个函数作为参数。

l = [34,554,67,897,436]
l.sort()
print(l)

打印[34, 67, 436, 554, 897]
同时可传递参数来对字符串长度进行比较。

l = ['ssd','adsd','frfrrffr','frfrsfrfs','rd']
l.sort(key=len)
print(l)

打印['rd', 'ssd', 'adsd', 'frfrrffr', 'frfrsfrfs']
还可以根据类型转换后的值进行比较:

l = ['34',554,'67',897,436]
l.sort(key=int)
print(l)

打印['34', '67', 436, 554, 897]

4.sorted()方法:

返回一个新的列表。

l = ['34',554,'67',897,436]
l2 = sorted(l,key=int)
print(l)
print(l2)

打印

['34'554'67'897436]
['34''67'436554897]

二、闭包

将函数作为返回值返回,也是一种高级函数(俗称闭包)。

def fn():
    #函数内部再定义一个函数
    def inner():
        print('In fn2()')
    #将inner()函数作为返回值返回
    return inner
print(fn())

打印<function fn.<locals>.inner at 0x000001E69ABC2EE8>

def fn():
    #函数内部再定义一个函数
    def inner():
        print('In fn2()')
    #将inner()函数作为返回值返回
    return inner
r = fn()
r()

打印In fn2()
解释:r其实就是fn()返回的函数inner对象,再调用,就会打印,所以这个函数总是能返回fn()函数内部的变量,

def fn():
    a  = 10
    #函数内部再定义一个函数
    def inner():
        print('In fn2()')
        print(a)
    #将inner()函数作为返回值返回
    return inner
r = fn()
r()

打印

In fn2()
10

r是调用fn()后返回的函数,是在fn()内部定义的,并不是全局函数,所以这个函数总是能访问到fn()函数内部的变量。
闭包的好处:
通过闭包可以创建一些只有当前函数可以访问到的对象(可以将一些私有的数据藏到闭包中)。
应用:

nums = []
def average(n):
    nums.append(n)
    return sum(nums)/len(nums)
print(average(10))
print(average(20))
print(average(30))

打印

10.0
15.0
20.0

不好的地方:nums是全局变量,会被任意访问到,可能会出现被修改、覆盖,从而导致本身的nums改变导致错误。
所以形成闭包:

def op_avg():
    nums = []
    def average(n):
        nums.append(n)
        return sum(nums)/len(nums)
    return average
avg = op_avg()
print(avg(10))
print(avg(20))
print(avg(30))

结果与上面相同。
总结:
形成闭包的条件
1.函数嵌套;
2.将内部函数作为返回值返回;
3.内部函数必须使用外部函数的变量。
闭包可以确保数据的安全。

三、装饰器

def add(a,b):
    #求任意两个数的和
    print('Start...')
    r = a + b
    print('End...')
    return r

def multiply(a,b):
    # 求任意两个数的积
    print('Start...')
    r = a * b
    print('End...')
    return r
r = add(1,2)
print(r)

打印

Start...
End...
3

这是添加了提示开始和结束的输出,但是如果函数较多,会出现一些问题:
※如果要修改的函数很多,修改起来很麻烦;
※不方便后期维护;
※会违反开闭原则(OCP)。
开闭原则:在开发的时候,要求可以开发对程序的扩展,但是要关闭对程序的修改。

def fn():
    print('In fn()')

def fn2():
    print('Start...')
    fn()
    print('End...')
fn2()

打印

Start...
In fn()
End...

又如

def add(a,b):
    #求任意两个数的和
    r = a + b
    return r
def new_add(a,b):
    print('Start...')
    r = add(a,b)
    print('End...')
    return r
r = new_add(1,2)
print(r)

打印

Start...
End...
3

很显然,会出现一定问题,每扩展一个函数会定义一个新的函数,很麻烦。

四、装饰器使用

def start_end():
    #用来对其他函数进行扩展,使其他函数可以在执行前打印开始和结束
    #创建一个函数
    def new_func():
        pass
    #返回函数
    return new_func
f = start_end()
f2 = start_end()
print(f)
print(f2)

打印

<function start_end.<locals>.new_func at 0x0000018368DE2EE8>
<function start_end.<locals>.new_func at 0x0000018368DFB1F8>

扩展new_func后

def fn():
    print('In fn()')

def start_end():
    #用来对其他函数进行扩展,使其他函数可以在执行前打印开始和结束
    #创建一个函数
    def new_func():
        print('Start...')
        fn()
        print('End...')
    #返回函数
    return new_func
f = start_end()
f()

打印

Start...
In fn()
End...

但是new_func是死的,变不了,失去了意义,所以可以在函数参数中传入被扩展的函数。

def fn():
    print('In fn()')

def start_end(func):
    #用来对其他函数进行扩展,使其他函数可以在执行前打印开始和结束
    #创建一个函数
    def new_func():
        print('Start...')
        func()
        print('End...')
    #返回函数
    return new_func
f = start_end(fn)
f()

打印

Start...
In fn()
End...

当被扩展的函数有参数时,

def add(a,b):
    #求任意两个数的和
    r = a + b
    return r

def start_end(func):
    #用来对其他函数进行扩展,使其他函数可以在执行前打印开始和结束
    #创建一个函数
    def new_func(a,b):
        print('Start...')
        result = func(a,b)
        print('End...')
        return result
    #返回函数
    return new_func
f = start_end(add)
r = f(1,2)
print(r)

打印

Start...
End...
3

需要对任何函数进行扩展时,

def add(a,b):
    #求任意两个数的和
    r = a + b
    return r

def fn():
    print('In fn()')

def start_end(func):
    #用来对其他函数进行扩展,使其他函数可以在执行前打印开始和结束
    #创建一个函数
    def new_func(*args,**kwargs): #*args接收所有位置参数,**kwargs接收所有关键字参数
        print('Start...')
        result = func(*args,**kwargs)
        print('End...')
        return result
    #返回函数
    return new_func
f = start_end(add)
f2 = start_end(fn)
r = f(1,2)
print(r)
f2()

打印

Start...
End...
3
Start...
In fn()
End... 


python培训班:http://www.baizhiedu.com/python2019



上一篇:python培训班 | python中列表的操作都有哪些?

下一篇:应届生去公司找个Java程序员的职位需要什么技能?

相关推荐

www.baizhiedu.com

有位老师想和您聊一聊

关闭

立即申请