装饰器

def outer(func):
    def inner():
        print('before')
        func()
        print('after')
    return inner

@outer
def f1():
    print('f1')

功能:

1.自动执行outer()函数,并把outer函数下面的函数名作为参数传递给outer函数

2.将outer函数的返回值重新赋值给f1

以上代码执行过后:

1.f1不在指向原来的f1函数,而是执行inner函数

2.func执指向原来的f1函数

也就是说函数被装饰器装饰之后,被装饰的函数名引用指向装饰器函数的内层函数即inner()

  • 一.装饰器流程之返回值
def outer(func):
    def inner():
        print('before')
        ret = func() # 接收原来f1函数的返回值
        print('after')
        return ret # 将函数之返回
    return inner

@outer
def f1():
    return 'f1'

f1()
  • 二.装饰器流程之参数
def outer(func):
    def inner(a,b): # 加参数
        print('before')
        ret = func(a,b)  # 加参数
        print('after')
        return ret  # 将函数之返回

    return inner


@outer
def f1(a, b):
    return a + b

f1(1,2)
  • 三.装饰器流程之多参数
def outer(func):
    def inner(*args,**kwargs): # 加参数
        print('before')
        ret = func(*args,**kwargs)  # 加参数
        print('after')
        return ret  # 将函数之返回

    return inner


@outer
def f1(a, b):
    return a + b

f1(1,2)
  • 装饰器带参数
"""
装饰器不带参数时,直接返回的是一个函数 inner
装饰器带参数之后,第一个外层函数接收参数,并返回一个装饰器  outer
"""


def outer_args(args):  # args 接收装饰器的参数
    def outer(func):   # func 接收需要装饰的函数
        #  扩展函数功能
        def inner_admin_user():
            print('before', 'admin')
            result = func()
            print('after', 'admin')
            return result

        #  扩展函数功能
        def inner_commons_user():
            print('before', 'commons')
            result = func()
            print('after', 'commons')
            return result

        # 根据装饰器的参数返回不同的装饰之后的函数
        if args == 'admin':
            return inner_admin_user
        else:
            return inner_commons_user

    # 返回装饰器
    return outer


@outer_args('admin')
def f1():
    print('F1')
    return 'f1'
ret = f1()
print(ret)


@outer_args('select')
def f2():
    print('F2')
    return 'f2'

res = f2()
print(res)
  • 使用类做装饰器
"""
使用类作为装饰器:
    1. 需要定义__call__(self, func) 用以接收被装饰的函数名参数
    2. 在类中在定义一个方法,扩展功能
    3. self.func = func  把被装饰的函数名封装到对象中
    4.  return self.inner  把返回的函数封装到对象中
    5. 如果装饰器需要传入参数,类中需定义__init__(self, args) 用以接收参数
    6. 使用类中装饰器是 @Decorator1() 有个括号

"""


class Decorator1(object):  # 使用类作为装饰器 且装饰器不带参数

    # 一个用于接收基本函数装饰器
    def __call__(self, func):
        print(func)
        self.func = func  # 把被装饰的函数名封装到对象中
        return self.inner  # 把返回的函数封装到对象中

    # 一个用于扩展功能
    def inner(self):
        print('before')
        ret = self.func()
        print('after')
        return ret


class Decorator2(object):  # 装饰器带参数

    def __init__(self, args):
        self.args = args

    def __call__(self, func):
        self.func = func

        if self.args == 'admin':
            return self.inner_admin_user
        else:
            return self.inner_commons_user

    def inner_admin_user(self):
        print('before', 'admin')
        result = self.func()
        print('after', 'admin')
        return result

    def inner_commons_user(self):

        print('before', 'commons')
        result = self.func()
        print('after', 'commons')
        return result


@ Decorator1()
def f1():
    print('f1')
f1()


@Decorator2('admin')
def f2():
    print('f1')
f2()


@Decorator2('commons')
def f2():
    print('f1')
f2()
  • 为类添加装饰器
"""
为类添加装饰器:
    1. outer(cls)  cls为类名
    2. 内层函数需返回对象
    3.为类加装饰器用处在什么地方呢,参数为cls 除了创建对象, 调用类中的方法,还有什么呢
"""


def decorator(args):
    def outer(cls):
        def inner_morning():
            print('早上开始创建对象..')
            obj = cls()
            print('始创建对象结束..')
            return obj  # 需返回对象

        def inner_noon():
            print('中午开始创建对象..')
            obj = cls()
            print('始创建对象结束..')
            return obj
        if args == '12':
            return inner_morning
        else:
            return inner_noon
    return outer


@decorator('13')
class Work(object):
    pass
aa = Work()

  

 

  • 四.装饰器流程练习
UserInfo = {'name': 'alex', 'age': 18, 'sex': '男'}
Login_flag = False
Login_type = None
# 用户登陆查询用户信息,查看信息之前先登陆,进行后台管理,必须是管理员


def check_login(func):
def inner(*args,**kwargs):
if Login_flag is True:
func()
else:
print('请先登陆...')
return inner


def check_type(func):
def inner(*args,**kwargs):
if Login_type == 1:
func()
else:
print('无权限')
return inner


def login(name, pwd):
global Login_flag, Login_type
if name == 'admin':
Login_flag = True
Login_type = 1
elif name == 'alex' and pwd == '123':
Login_flag = True
else:
pass


@check_login
def select():
for li in UserInfo.keys():
print(UserInfo[li])


@check_login
@check_type
def admin():
print('后台管理')

inp = input('1:登陆 2:查看用户,3:后台管理\n>>>')
name = input('UserName:>>>')
pwd = input('PassWord:>>>')
if inp == '1':
login(name, pwd)
elif inp == '2':
select()
elif inp == '3':
# login(name, pwd)
login(name, pwd)
admin()

 

posted @ 2017-01-14 20:37  TianTianLi  阅读(178)  评论(0编辑  收藏  举报