初识函数--装饰器

  • 闭包:在嵌套函数中,变量即不在全局,也不在内层函数中,而且必须是内层函数对外层函数的变量的引用
  • 开放封闭原则:对功能扩展是开放的,对源码的修改是封闭的...在不修改源码及调用方式的前提下,对功能进行额外地扩展就是开放封闭原则
  • 装饰器

1. 标准版装饰器

def wrapper(func):
    def inner(*args,**kwargs):
        # 执行原函数之前的操作...
        ret = func()
        # 执行原函数之后的操作...
        return ret
    return inner

2. 标准版装饰器的例子 ---- 模拟博客园登录的装饰器

  • 功能:已经登录的账号可以无障碍访问其他页面,没有登录的账号要访问其他页面时自动跳转到登录页面
login_status = {
    'username':None,
    'flag':False,
}

def auth(func):
    def inner(*args,**kwargs):
        if login_status['flag']:
            ret = func(*args,**kwargs)
            return ret
        username = input('请输入用户名:').strip()
        password = input('请输入密码:').strip()
        if username == 'baoyuan' and password == 'bangbangde':
            login_status['flag'] = True
            ret = func(*args,**kwargs)
            return ret
    return inner

@auth
def diary():
    print('欢迎访问日记页面')


def auth(x):
    def auth1(func):
        def inner(*args,**kwargs):
            if dic_flag['flag']:
                ret = func()
                return ret
            if x == 'wechat':
                username = input('name')
                password = input('pwd')
                if username == 'asd' and password == '123':
                    ret = func()
                    return ret
            if x == 'QQ':
                username = input('name')
                password = input('pwd')
                if username == 'asd' and password == '123':
                    ret = func()
                    return ret
        return inner
    return auth1

@auth('wechat')  
def jitter():
    print('记录美好生活')

@auth('qq')
def pipefish():
    print('期待你的内涵神评论')

3 最简单的装饰器

def auth(func):
    def inner(*args, **kwargs):
        ret = func(*args, **kwargs)
        return ret
    return inner

# @auth
def index():
    print('Index')

print(index)
print(index.__name__)

这里print(index)运行有两种情况:

  • 不加装饰器:<function index at 0x000001F7575F52F0>
  • 加上装饰器:<function auth..inner at 0x000002266E7D5950>

print(index.__name__)时也有两种情况:

  • 不加装饰器:index
  • 加上装饰器:inner

总结:加上装饰器之后,其实执行的是inner()函数,只不过这里的inner()函数没做任何操作而已。

4 @functools.wraps(func)

下面想要在加上装饰器之后print(index.__name__)时,还是打印自己的函数名,具体操作如下:

import functools

def auth(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        ret = func(*args, **kwargs)
        return ret
    return inner

@auth
def index():
    print('Index')

print(index.__name__)

注意:

  • 这里print(index.__name__)的本质还是inner,但是加上@functools.wraps(func)装饰器后,inner()函数会带上index()函数上的一些内容,比如函数名。
  • 相当于:把原函数的原信息封装到闭包中。
原文地址:https://www.cnblogs.com/richard_A/p/11938948.html