04-Python的函数3

## 匿名函数

- 基于lambda演算得一种编程模式。

- 语法:lambda 参数1,参数2,..... : 表达式

  - 程序中只有函数,只有一个表达式,不接 return

  - 函数可以作为参数和返回值

stm = lambda x,y: 100*x+y
# 和函数调用一样
stm(89,100)  # 输出9000

## 闭包  

- 概念:
  - 在一个函数在内部定义函数(函数嵌套),并且内层的函数应用外层函数的参数或者局部变量,
    - 并且把内部函数被当作返回值的时候,相关参数和变量保存在返回的函数中,这种结果叫做闭包
  - 专业的解释:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。

- 案例:

# 1.简单的闭包案例
def Fun1():
    a = 5
    def Fun2():
        print(a)  # 调用函数Fun1的变量a
    return Fun2  # 内部函数作为返回值

f = Fun1()  # 执行Fun1函数,将返回结果 Fun2 赋值给f
f()   # 执行Fun2()函数,
# 执行结果为5

  nonlocal语句  

# 2.修改外部变量,使用 nonlocal 语句

# 2.1没有使用nonlocal
def Fun1():
    a = 5         # Fun1函数的本地变量
    def Fun2():
        a = 100   
        print(a)
    print(a)  # a = 5,Fun1函数的本地变量
    Fun2()    # a = 100
    print(a)  # a = 5,Fun1函数的本地变量
    return Fun2  

f1 = Fun1()  # 执行Fun1函数

print("---"*10)
# 2.2使用nonlocal
def Fun3():
    a = 5         # Fun3函数的本地变量
    def Fun4():
        nonlocal a  # 声明a是Fun3函数的本地变量
        a = 100     # 修改变量a
        print(a)    
        
    print(a)  # a = 5,Fun3函数的本地变量
    Fun4()    # a = 100
    print(a)   # a = 100, a被修改了 
     
    return Fun4  

f2 = Fun3()  # 执行Fun3函数
# 结果
5
100
5
------------------------------
5
100
100

  注意:返回闭包时,不能引用任何循环变量

# 3.闭包的注意事项

# 3.1不理想的情况
def count():
    fs = []    # 创建空列表,用于放置函数
    for i in range(1,4):
        # 每次遍历的时候,只是路过,知道f存在,不执行f里面的内容。
        def f():
            # print(i) # 结果是3,每次遍历时,i在这里只是标识符。
            return i*i
        fs.append(f)   # 把函数f追加到fs里面
    #print(fs)  #得到的结果是一个有三个函数的列表,地址不一样
    """[<function count.<locals>.f at 0x000002082D5956A8>, 
        <function count.<locals>.f at 0x000002082DA972F0>, 
        <function count.<locals>.f at 0x000002082DA970D0>]
    """
    return fs

f1,f2,f3 = count() # 把count()的返回值一一赋值个f1,f2,f3
# 相当于 ff=count(),   ff[0]=f1,ff[1]=f2,ff[2]=f3
print(f1(),f2(),f3())  # 执行结果:9 9 9

# 程序执行过程:
    # 1.定义count函数->执行count()函数,并把count()的返回值一一赋值个f1,f2,f3 
    # 2.执行conut()的过程:创建fs->遍历操作(忽略f函数,修改fs)->返回fs
    # 3.打印f1,f2,f3的内容,就是分别执行存在fs里面的三个函数。
    # 4.此时count已经执行一遍,调用函数f时,i的值已经时3了
    
# 注意:返回闭包时,不能引用任何循环变量
# 3.2解决方案
def count2():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) 
    return fs

f1,f2,f3 = count2()
print(f1(),f2(),f3())
# 执行结果1 4 9

## 装饰器 

- python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,

- 使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。

- 一旦被定义了,可以重复使用。装饰器在函数之前执行而且是立即执行。

- 案例推导:

# 1.简单的装饰器(无参数)
# 在不修改原来函数Fun1()的前提下增加功能
def Fun2(func):
    def inner():
        print("这是增加的功能")
        func()  # 执行传进来的函数
    return inner

@ Fun2  # 相当于 Fun1 = Fun2(Fun1)
def Fun1():
    print("这是要执行的功能")
    
Fun1()
# 结果
这是增加的功能
这是要执行的功能

 

# 2.装饰器的叠加
# 顺序是从上往下执行
def Fun2(func):
    def inner():
        print("这是增加的功能111")
        func()  # 执行传进来的函数
    return inner

def Fun3(func):
    def inner():
        print("这是增加的功能222")
        func()  
    return inner

@ Fun2  # 相当于 Fun1 = Fun2(Fun1) #括号的Fun1=Fun3(Fun1)
@ Fun3 # 相当于 Fun1 = Fun3(Fun1)
def Fun1():
    print("这是要执行的功能")
Fun1()

# 结果
这是增加的功能111
这是增加的功能222
这是要执行的功能

  

# 2.传入参数的装饰器
# 2.1传入少数参数
def Fun2(func):
    def inner(a,b):
        print("这是增加的功能")
        func(a,b)   
    return inner

@ Fun2  # 相当于 Fun1 = Fun2(Fun1)
def Fun1(a,b):
    print("这是要执行的功能")
    print(a,b)
    
Fun1(5,6)
# 结果
这是增加的功能
这是要执行的功能
5 6

  

# 2.2传入多个参数参数(包括关键字参数)
def Fun2(func):
    def inner(*args, **kwargs):
        print("这是增加的功能")
        print(args, kwargs)
        func(*args, *kwargs)   
    return inner

@ Fun2  # 相当于 Fun1 = Fun2(Fun1)
def Fun1(*args, **kwargs):
    print(*args, **kwargs)
    
Fun1(5,6,7,anem="sss")

# 结果
这是增加的功能
(5, 6, 7) {'anem': 'sss'}
5 6 7 anem

  

 

posted @ 2019-07-18 21:06  xiaoou7  阅读(205)  评论(0编辑  收藏  举报