day12 装饰器

作业讲解和昨日回顾

2、动态参数*args  ,**kwargs:位置参数,*args,默认参数,**kwargs

     命名空间和作用域

     作用域链

     函数名是第一类对象的概念

二、新内容:闭包

1、闭包的定义:闭包必须是嵌套函数,内部函数引用外部函数的变量

def f1():
    b=123
    def f2():
        print(b)

 2、例子:用__closure__检测是不是闭包

def fl():
    a=1
    def f2():
        def f3():
            print(a)
        f3()
        print("f3:",f3.__closure__)
    f2()
    print("f2:",f2.__closure__)
fl()

# 1
# f3: (<cell at 0x00000000027A85E8: int object at 0x00000000655B60E0>,)
# f2: (<cell at 0x00000000027A85E8: int object at 0x00000000655B60E0>,)

3、外面调用里面的函数,是闭包的常用状态

def f1(b):
    def f2():
        print(b)
    return f2

ff = f1("bbb")
ff()
#bbb
详细步骤:

def f1():
    b=10
    def f2():
        return b
    ret_b=f2()
    return ret_b
ret_b=f1()
print(ret_b)
简写
def f1():    #从内部返回一个值到全局
    b=10
    def f2():
        return b
    return f2()
print(f1())

4、在爬虫中应用闭包

from urllib.request import urlopen
def get_url(url):
    def readl():
        ret=urlopen(url).read()
        print(ret)
    return readl
read_func=get_url("https://i.cnblogs.com/EditPosts.aspx?opt=1")
read_func()

三:装饰器

装饰器的作用:在不改变函数的调用方式的情况下,给函数的前后添加新的功能

1、关于时间:计算运行时间差

import time        #模块
start_time=time.time()
time.sleep(1)
end_time=time.time()
print("======%s======"%(end_time-start_time))

利用闭包计算时间差

import time
def timmer(func):
    def inner():
        start_time=time.time()
        time.sleep(0.1)
        func()
        end_time=time.time()
        print("===%s==="%(end_time-start_time))
    return inner
def func():
    print("dajiahao")
func=timmer(func)
func()
# dajiahao
# ===0.1000056266784668===
 

2、重要模板说明

import time
def timmer(qqxing):     #timmer是装饰器的名字,传入的参数就是被装饰的函数
    def inner():        #在装饰器中需要定义一个内部的函数
        print("调用func之前")
        qqxing()                #被装饰的函数,并且要执行
        print("调用func之后")
    return inner                #将内部函数的名字返回

def func():
    print("dajiahao")
    
func=timmer(func)
func()

3、装饰器是闭包的典型应用

   语法糖的应用

import time
def timmer(qqxing):     #timmer是装饰器的名字,传入的参数就是被装饰的函数
    def inner():        #在装饰器中需要定义一个内部的函数
        print("调用func之前")
        qqxing()                #被装饰的函数,并且要执行
        print("调用func之后")
    return inner                #将内部函数的名字返回

@timmer           #语法糖 func=timmer(func)
def func():
    print("dajiahao")

func()
#调用func之前
#dajiahao
#调用func之后

4、完整的装饰器例子

import time
def timmer(qqxing):     #timmer是装饰器的名字,传入的参数就是被装饰的函数
    def inner(name):        #在装饰器中需要定义一个内部的函数
        print("调用func之前")
        qqxing(name)                #被装饰的函数,并且要执行
        print("调用func之后")
    return inner                #将内部函数的名字返回

@timmer           #语法糖 func=timmer(func)
def func(name):
    print("%s你好"%(name))

func("虫虫")
# 调用func之前
# 虫虫你好
# 调用func之后

5、装饰器的固定结构

# 装饰器的固定结构
def wrapper(func):               #timmer 是装饰器的名字,传入的参数就是被装饰的函数
    def inner(*args,**kwargs):      #在装饰器中需要定义一个内部函数
        """被装饰函数之前添加的代码"""
        ret=func(*args,**kwargs)    #被装饰器的函数,并且要执行
        # """被装饰函数之后添加的代码"""
        return ret
    return inner                    #将内部函数的名字返回

四、装饰器的开放封闭原则

概念:开放封闭原则

开放:  对扩展是开放的

封闭:对修改是封闭的

装饰器:开放封闭原则

1、例题:利用装饰器设置登录一次的程序

flag=False
def login(func):
    def inner(*args,**kwargs):
        global  flag
        if flag==False:
            username=input("用户名:")
            password=input("密码:")
            if username=="alex" and password=="someboday":
                print("登录成功")
                flag=True
        if flag==True:
            ret=func(*args,**kwargs)
            return ret
    return inner
@login
def art():
    print("欢迎来到文章页")
@login
def dar():
    print("欢迎来到日志页")
art()
dar()

记录日志:

def log(func):
    def inner(*args,**kwargs):
        print("你要调用%s函数了"%func.__name__)
        ret=func(*args,**kwargs)
        return  ret
    return inner
@log
def f1():
    print("f1")
@log
def f2():
    print("f2")
f1()
f2()
原文地址:https://www.cnblogs.com/number1994/p/7941399.html