Python第十课(函数3)

Python第十课(函数3)    >>>转到思维导图>>>转到中二青年

闭包函数

1.定义在函数内部的函数

2.内部函数内部函数引用了外部函数名称空间作用域的名字

只要满足以上两点都叫做闭包函数

def func():
    name = jason'  # 先在内部找name没有再往上层找 有了就停止查找
    def inner():
        print(name)  # 现在内部找name没有再往上层找
    return inner
f = func()  # f获取到的是inner的内存地址
f()  # 相当于执行 inner()
# 函数在定义阶段名字的查找孙旭就已经固定死了,不会因为函数调用位置的变化而变化

 给函数传参的两种方式

1.直接传参

def index(name):
    print(name)

 2.闭包

def outter(name):
    # name = 'jason'
    def index():
        print(name)
    return index

装饰器

器:就是一个工具

装饰:就是给被装饰对象添加新的功能

开放封闭原则:

    开放:对扩展开放

    封闭:对修改封闭

装饰器(可调用对象)必须遵循的两个原则:

    1.不改变被装饰对象的源代码

    2.不改变被装饰对象(可调用对象)调用方法

可调用:callable

def new():
    print('这是原始函数')
 
def outter(func):
    def inner():
        print('这是内部函数,这里可以加新功能')
        func()  # 这里的func是你想调用的最原始的函数的内存地址,加上()直接调用
        print('这是内部函数,这里可以加新功能')
    return inner  # 这里不加括号 返回的是inner函数的内存地址
new = outter(new)  # 括号内的new指向的是最原始的new函数的内存地址,前面的new获取的是outter函数的返回值,返回值我们自定义了返回 inner函数的内存地址
# 总结:前面的new获取的是inner的内存地址,后面括号内的new指向的就是最原始的new的内存地址
new()

扩展:import time

import time
time.time()  获取时间戳(秒)    当前时间距离1970-1-1 00:00:00 所经过的秒数
time.sleep(seconds)  让程序暂定几秒钟

装饰器语法糖

把装饰器赋值给最近的可调用对象

将最近的可调用对象的名字当做参数自动传入装饰器外层函数

书写时两者之间不要空行,应紧紧挨着

# 先写装饰器
def outter(func):
    def inner():
        print('这里可以加新功能')
        func()  # 这里的func是你想调用的最原始的函数的内存地址,加上()直接调用
        print('这里可以加新功能')
    return inner  # 这里不加括号 返回的是inner函数的内存地址
 
@outter  #  new = outter(new) 把装饰器赋值给最近的可调用对象,并将对象名传入。
def new():
    print('这是原始函数')
 
new()

装饰器修复技术

1.返回原来的函数的函数名

2.返回原来的函数的注释

from functools import wraps
def outter(func):
    @ wraps(func)  #  装饰器修复加在最内层函数正上方 
    def inner(*args,**kwargs):  # * **在形参中使用
        # 执行被装饰函数之前你可以做的操作
        res = func(*args,**kwargs)  # * 
        # 执行被装饰函数之后你可以做到操作
        return res
    return inner
@outter
def index(username,*args,**kwargs):
    """index注释"""
    pass
print(index)

无参装饰器

from functools import wraps
def outter(func):
    @wraps(func)  # 加在最内层函数正上方
    def inner(*args,**kwargs):  # *和**在形参中使用
        print('这里可以加新功能')  # 执行被装饰函数之前你可以做的操作
        func(*args,**kwargs)  # 这里的func是你想调用的最原始的函数的内存地址,加上()直接调用, *和**在实参中使用
        print('这里可以加新功能')  # 执行被装饰函数之后你可以做到操作
    return inner  # 这里不加括号 返回的是inner函数的内存地址
@outter  #  new = outter(new) 把装饰器赋值给最近的可调用对象,并将对象名传入。
def new():
    print('这是原始函数')
new()

有参装饰器

from functools import wraps
choice = input('>>>:')
def wrappers(data):
    def outter(func):
        @wraps(func)  # 加在最内层函数正上方
        def inner(*args,**kwargs):
            if data == '1':  # 如果用户输入‘1’那么执行index()
                # 执行被装饰函数之前你可以做的操作
                res = func(*args,**kwargs)  # * **在实参中使用    res接收原始函数的返回值
                # 执行被装饰函数之后你可以做到操作
                return res
            return 999
        return inner
    return outter
@wrappers(choice)  # index = wrappers(index)
def index()
    print('123')
    return  666  # 原始函数的返回值
index()

多个装饰器

1. 装饰的时候 从下往上执行

2. 执行的时候 从上往下执行

def outter1(func1): #func1=wrapper2的内存地址
    print('加载了outter1')
    def wrapper1(*args,**kwargs):
        print('执行了wrapper1')
        res1=func1(*args,**kwargs)
        return res1
    return wrapper1
def outter2(func2): #func2=wrapper3的内存地址
    print('加载了outter2')
    def wrapper2(*args,**kwargs):
        print('执行了wrapper2')
        res2=func2(*args,**kwargs)
        return res2
    return wrapper2
def outter3(func3): # func3=最原始的那个index的内存地址
    print('加载了outter3')
    def wrapper3(*args,**kwargs):
        print('执行了wrapper3')
        res3=func3(*args,**kwargs)
        return res3
    return wrapper3
@outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
@outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
@outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址
def index():
    print('from index')
print('======================================================')
index()
# 1. 加载顺序(outter函数的调用顺序):自下而上
# 2. 执行顺序(wrapper函数的执行顺序):自上而下

END

posted @ 2019-07-12 22:41  宋人杰  阅读(195)  评论(0编辑  收藏  举报