python教程21-闭包的概念、计算代码执行时长、装饰器的使用和详解及高级使用

Python教程_小白入门2020/10/28

学习目标
在这里插入图片描述

P129 闭包的基本概念
#  函数的嵌套
# author by zhangjiong

def outer(x):
    m = 100
    print("我是outer函数")

    def inner():
        print("我是inner函数")

    if x > 18:
        inner()

    return 'hello'

# 函数内部定义的变量不能在函数外部使用
# print(m)        # name 'm' is not defined
# inner()         # 函数内部定义的东西不能在外部使用

outer(21)
# 我是outer函数
# 我是inner函数

outer(12)
# 我是outer函数

闭包的相关概念

#  闭包的基本概念
# @author :zhangjiong
def outer():
    x = 10  # 在外部函数里定义了一个变量x,是一个局部变量

    def inner():
        # 在内部函数如何修改外部函数的局部变量nonlocal
        # 想在内部函数中修改外部函数的局部变量,而不是在内部函数中额外定义一个变量,就需要用到nonloca
        nonlocal x  # 此时,这里的x不再是新增的变量,而是外部的局部变量
        x = 20
        y = x + 1
        print("inner里的y", y)

    return inner
    

# 如果在一个内部函数里,对外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包
# 比如在此例中,inner()函数就是闭包,要注意的是,inner()函数返回的是inner而不是inner()
# 返回的值是函数
outer()()      # inner里的y 21
# 当outer函数里只有一个函数,使用两个括号就可以直接调用

P 130 计算代码的执行时长
#  计算一段代码的执行时间
# @author :zhangjiong
# 在代码运行之前,获取下时间
# 在代码执行之后,再获取下时间
# time模块是可以获取当前的时间
# 时间戳是从1970-01-01 00.00.00 UTC到 现在的秒数

import time

start = time.time()  # time模块里的time方法,可以获取当前电脑时间戳
print("start=", start)
# start= 1603849646.9062228
x = 1
for i in range(1, 20001):
    x += i

print(x)

end = time.time()
print("代码执行时间为{}秒".format(end - start))

代码执行时间优化,使用函数调用来计算代码执行时间

#  计算一段代码的执行时间优化
# @author :zhangjiong
import time


def cal_time(fn):
    start = time.time()
    fn()
    end = time.time()
    print("代码执行的时间为{}".format(end - start))


def demo():
    x = 0
    for i in range(1, 100000000):
        x += i
    print(x)


# cal_time(demo())        # 注意,不能加括号加括号就会报错
# 写demo()就是代表传入的是demo()计算后的结果
# 写demo就是代表传入的是demo函数
cal_time(demo)


# 4999999950000000
# 代码执行的时间为6.806422472000122


def foo():
    print("hello")
    time.sleep(3)
    print("world")

cal_time(foo)
# hello
# world
# 代码执行的时间为3.0001254081726074
P131 装饰器的基本使用
#  装饰器的使用
# @author :zhangjiong
import time


def cal_time(fn):
    print("我是外部函数cal_time,我被调用了")
    print("fn={}".format(fn))
    def inner():
        start = time.time()
        fn()
        end = time.time()
        print("代码耗时", end - start)
    return inner

# 修饰器是在定义的函数上边加@
# 装饰器的执行流程:
# 第一件事:调用cal_time,只要写了@cal_time会直接调用这个函数
# 第二件事:把被装饰的函数传递给fn,此时inner函数是没有被调用的
@cal_time
def demo():
    x = 0
    for i in range(1, 100000000):
        x += i
    print(x)

# 我是外部函数cal_time,我被调用了
# fn=<function demo at 0x000001930B51B5E0>


# 第三件事:当再次调用demo函数时,此时的demo函数不再是上边的demo
# 而是变成了cal_time函数的返回值,也就是inner函数
# 装饰后的demo=<function cal_time.<locals>.inner at 0x0000022CA1C4A700>
print("装饰后的demo={}".format(demo))
# fn指向的是以前的demo,而后边的demo指向的是inner函数

P132 装饰器详解
#  装饰器详解
# @author :zhangjiong
import time


def cal_time():
    print("我是外部函数cal_time,我被调用了")
    print("fn={}".format(fn))

    def inner():
        start = time.time()
        s = fn(m)
        end = time.time()
        print("代码耗时", end - start)
        return s

    return inner


@cal_time
def demo0():
    x = 0
    for i in range(1, 100000):
        x += i
    return x

z = demo0()
print(z)

# 我是外部函数cal_time,我被调用了
# fn=<function demo at 0x000001F20CEDB5E0>
# 代码耗时 0.00840306282043457
# 4999950000

#  装饰器详解
# @author :zhangjiong
import time


def cal_time(fn):
    print("我是外部函数cal_time,我被调用了")
    print("fn={}".format(fn))

    def inner(m):
        start = time.time()
        s = fn(m)
        end = time.time()
        print("代码耗时", end - start)
        return s

    return inner

@cal_time
def demo1(m):
    x = 0
    for i in range(1, m):
        x += i
    return x


aaa = demo1(1000000)  # demo1不再是曾经的demo1,而是变成了inner()
print(aaa)


# 我是外部函数cal_time,我被调用了
# fn=<function demo1 at 0x000001E0C33CB5E0>
# 代码耗时 0.07489585876464844
# 499999500000
#  装饰器详解
# @author :zhangjiong
import time


def cal_time(fn):
    print("我是外部函数cal_time,我被调用了")
    print("fn={}".format(fn))

    def inner(m):
        start = time.time()
        s = fn(m)
        end = time.time()
        # print("代码耗时", end - start)
        return s, end - start

    return inner


@cal_time
def demo1(m):
    x = 0
    for i in range(1, m):
        x += i
    return x


aaa, bbb = demo1(1000000)  # demo1不再是曾经的demo1,而是变成了inner()
print(aaa)
print(bbb)

# 我是外部函数cal_time,我被调用了
# fn=<function demo1 at 0x000001EB7D7CB5E0>
# 499999500000
# 0.07241535186767578
#  装饰器详解
# @author :zhangjiong
import time


def cal_time(fn):
    print("我是外部函数cal_time,我被调用了")

    def inner(m, *args, **kwargs):
        start = time.time()
        s = fn(m)
        end = time.time()
        return s, args,kwargs

    return inner


@cal_time
def demo1(m):
    x = 0
    for i in range(1, m):
        x += i
    return x

# 要记住,后边的demo1不再是原来的demo1,所以原来的demo1只有一个参数,而到后边的demo1可以有多个参数,因为他们不是同一个,所以参数可以不一样
# 这也是python修饰器强大的一点
# 原来的demo1是和fn()是一伙的,后来的demo1是和inner一伙的

aaa = demo1(100, 'hello', l=500)  # demo1不再是曾经的demo1,而是变成了inner()
print("aaa的值是:",aaa)

# 我是外部函数cal_time,我被调用了
# fn=<function demo1 at 0x000001B7A74BB5E0>
# aaa的值是: (4950, ('hello',), {'l': 500})


P133 装饰器的高级使用
#  装饰器的高级使用
# @author :zhangjiong

# 产品经理:提需求  /  改需求
# 开放封闭原则,已经写好的代码能不要改就不要改
# 装饰器的高级使用:在不采编原有函数的基础上,为函数增添函数,增加功能

def can_play(fn):
    def inner(x, y,*args,**kwargs):
        if args[0]<=22:
            fn(x, y)
        else:
            print("太晚了,抓紧睡")
    return inner


@can_play
def play_game(name, game):
    print("{}正在玩{}".format(name, game))


play_game("张三", "王者荣耀",18)
play_game("李四", "绝地求生",23)
# 张三在玩王者荣耀
# 太晚了,抓紧睡

#  装饰器的高级使用
# @author :zhangjiong

# 产品经理:提需求  /  改需求
# 开放封闭原则,已经写好的代码能不要改就不要改
# 装饰器的高级使用:在不采编原有函数的基础上,为函数增添函数,增加功能

def can_play(fn):
    def inner(x, y, *args, **kwargs):
        if kwargs["clock"] >= 22:
            fn(x, y)
        else:
            print("太晚了,抓紧睡")
    return inner


@can_play
def play_game(name, game):
    print("{}正在玩{}".format(name, game))

play_game("李四", "绝地求生", clock = 23)

# 李四正在玩绝地求生
#  装饰器的高级使用
# @author :zhangjiong

# 产品经理:提需求  /  改需求
# 如果超过22点不让玩游戏,如果不告诉时间,默认不让玩游戏
# 开放封闭原则,已经写好的代码能不要改就不要改
# 装饰器的高级使用:在不采编原有函数的基础上,为函数增添函数,增加功能

def can_play(fn):
    def inner(x, y, *args, **kwargs):
        clock = kwargs.get("clock", 23)
        if clock <= 22:
            fn(x, y)
        else:
            print("太晚了,抓紧睡")

    return inner


@can_play
def play_game(name, game):
    print("{}正在玩{}".format(name, game))


play_game("李四", "绝地求生", m="hello", n='world')

# 太晚了,抓紧睡
# 使用kwargs.get("clock", 23)方法来给clock一个默认值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值