day12:装饰器的进阶

1,三元运算符:变量 = 条件返回True的结果 if 条件 else 条件返回false的结果;必须要有结果;必须要有if和else,只能是简单的情况。

2,传参包起来,星号打散

def outer(*args):
    print(args)
    print(*args)

outer(1,2,3,4) #==> outer(*(1,2,3,4)) *打散,传参的时候,默认包起来包成一个元祖,拿出来用的时候,加*号打散

outer(*[1,2,3,4])

3,print为何可以接收各种参数,因为默认里面参数加了*args,内置函数是用C语言写的

4,昨天作业一

# 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
# 要求登录成功一次,后续的函数都无需再输入用户名和密码

# 自己的版本
FLAG = False
def wrapper(func):
    def inner(*args,**kwargs):
        global FLAG
        if FLAG == False:  # not FLAG
            usrname = input("please input username:")
            li = []
            with open("file.txt",encoding="utf-8") as f1:
                for line in f1:
                    li.append(line.strip())
            if li[0] == usrname :
                pwd = input("please input password:")
                if li[1] == pwd:
                    print("登录成功")
                    FLAG = True
                else:
                    FLAG = False
                    print("登录失败")
                    return
            else:
                FLAG = False
                print("登录失败")
                return

        ret = func(*args,**kwargs)
        return ret
    return inner


@wrapper
def func():
    print("in func")

@wrapper
def func1():
    print("in func1")

@wrapper
def func2():
    print("in func2")

func()
func1()
func2()

# 可以看到这儿只认证了一次 运行结果: please input username:lisa please input password:
123 登录成功 in func in func1 in func2
1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
# 要求登录成功一次,后续的函数都无需再输入用户名和密码

# 老师的版本
# FLAG = False
# def login(func):
#     def inner(*args,**kwargs):
#         global FLAG
#         '''登录程序'''
#         if FLAG:
#             ret = func(*args, **kwargs)  # func是被装饰的函数
#             return ret
#         else:
#             username = input('username : ')
#             password = input('password : ')
#             if username == 'boss_gold' and password == '22222':
#                 FLAG = True
#                 ret = func(*args,**kwargs)      #func是被装饰的函数
#                 return ret
#             else:
#                 print('登录失败')
#     return inner
#
# @login
# def shoplist_add():
#     print('增加一件物品')
#
# @login
# def shoplist_del():
#     print('删除一件物品')
#
# shoplist_add()
# shoplist_del()

5,昨天作业二:

# 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
# 自己的版本
def wrapper(func):
    def inner(*args,**kwargs):
        funcname = func.__name__
        with open("func_call_record.txt","a+",encoding="utf-8") as f1:
            f1.write(funcname+"
")
        ret = func(*args,**kwargs)
        return ret
    return inner


@wrapper
def func():
    pass

@wrapper
def func1():
    pass

@wrapper
def func2():
    pass

func1()
func2()
func()
func1()
# 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
# 老师的版本
def log(func):
    def inner(*args,**kwargs):
        with open('log','a',encoding='utf-8') as f:
            f.write(func.__name__+'
')
        ret = func(*args,**kwargs)
        return ret
    return inner

@log
def shoplist_add():
    print('增加一件物品')

@log
def shoplist_del():
    print('删除一件物品')

shoplist_add()
shoplist_del()
shoplist_del()
shoplist_del()
shoplist_del()
shoplist_del()

6,昨天作业三:

# 进阶作业(选做):
# 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
# 2.为题目1编写装饰器,实现缓存网页内容的功能:
# 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

#  老师的版本
from urllib.request import urlopen
import os

def cache(func):
    def inner(*args,**kwargs):
        if os.path.getsize("web_cache.txt"):
            with open("web_cache.txt","rb") as f:
                return f.read()
        ret = func(*args,**kwargs)
        with open("web_cache.txt",'wb') as f:
            f.write(b"******"+ret)
        return ret

    return inner


@cache
def get_code(url):
    code =urlopen(url).read()
    return code

code = get_code('http://www.baidu.com')  # 路径要给全
print(code)
code = get_code('http://www.baidu.com')  # 路径要给全
print(code)
code = get_code('http://www.baidu.com')  # 路径要给全
print(code)

7,被装饰之后,保留原函数的各种属性

def wrapper(f):
    def inner(*args,**kwargs):
        '''
        我是inner函数
        :return:
        '''
        ret = f(*args,**kwargs)
        return ret
    return inner

@wrapper
def func():
    '''
    我是被修饰的函数func
    :return:
    '''

    pass

print(func.__name__)
print(func.__doc__)

运行结果:
inner

        我是inner函数
        :return:
        

8,从上一步看出,打印出来的信息都是和inner相关的,这并不是我想要的,我想要的是被修饰函数相关的,怎么办呢?

from functools import wraps


def wrapper(f):
    @wraps(f)
    def inner(*args,**kwargs):
        '''
        我是inner函数
        :return:
        '''
        ret = f(*args,**kwargs)
        return ret
    return inner

@wrapper
def func():
    '''
    我是被修饰的函数func
    :return:
    '''

    pass

print(func.__name__)
print(func.__doc__)

# 看出来代码哪里变化了吗?
 运行结果:
func

    我是被修饰的函数func
    :return:

9,带参数的装饰器,其实是又加了一层,三层其实是最多的了,作用就一个,传递进去一个或者多个参数,然后返回内层函数。

import time

FLAG = False
def timer_off(flag):
    def timer(f):
        def inner():
            if flag:
                starttime = time.time()
                ret = f()
                endtime = time.time()
                duration = endtime - starttime
                print(duration)
                return ret
            else:
                ret = f()
                return ret
        return inner
    return timer

FLAG = True
@timer_off(FLAG)   #timer_off(FLAG) ==timer   @time == func=timer(func) 也就是inner
def func():
    time.sleep(0.1)
    print("i am func")

func()

10,老师推荐了两本书:《Python核心编程》第二版和《流畅的Python》 先看第一本,第二本比较讲的比较深

11,多个装饰器装饰一个函数,弄清楚是谁装饰了谁,执行顺序

def wrapper1(f):
    def inner1():
        print("before inner1")
        ret = f()
        print("after inner1")
        return ret
    return inner1


def wrapper2(f):
    def inner2():
        print("before inner2")
        ret = f()
        print("after inner2")
        return ret
    return inner2

@wrapper2
@wrapper1
def func():
    print("i am func")

func()
运行结果:
before inner2
before inner1
i am func
after inner1
after inner2
def wrapper1(f):
    def inner1():
        print("before inner1")
        ret = f()
        print("after inner1")
        return ret
    return inner1


def wrapper2(f):
    def inner2():
        print("before inner2")
        ret = f()
        print("after inner2")
        return ret
    return inner2

@wrapper1
@wrapper2
def func():
    print("i am func")

func()
运行结果:
before inner1
before inner2
i am func
after inner2
after inner
原文地址:https://www.cnblogs.com/lisa-blog/p/10081008.html