python学习笔记

今日内容概要

  • 闭包函数简介
  • 闭包函数的实际应用
  • 装饰器简介
  • 装饰器推导流程(重要)
  • 装饰器功能完善
  • 装饰器统一使用模板(通用)
  • 装饰器语法糖

今日内容详细

闭包函数简介

闭包函数:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的函数名。这样就构成了一个闭包。

def func(username):
    # username = 'jason'
    def index():
        print(username)
    return index
# 思考如何在全局调用index
res = func()
print(res)
res()

func('jason')  # username = 'jason'

闭包函数实际应用

1.读取函数内部的变量

2.让函数内部的局部变量始终保持在内存中

一般来说,函数内部的局部变量在这个函数运行完以后,就会被Python的垃圾回收机制从内存中清除掉。如果希望这个局部变量能够长久的保存在内存中,可以用闭包来实现这个功能。

装饰器简介

装饰器不是一个全新知识 而是由我们前两天所讲的函数知识整合到一起的产物

1.装饰器的本质
在不改变被装饰对象原来的'调用方式'和'内部代码'的情况下给被装饰对象添加新的功能

 eg:
def func():
    print(123)
func()  # 每次执行之前需要校验用户身份

2.装饰器的原则
对修改封闭 对扩展开放
3.知识储备

import time
print(time.time())  # 1656987566.7260265
'''时间戳(秒数):当前距离1970年1月1日0时0分0秒所经历的秒数'''
# 实际应用>>>:统计代码的运行时间
start_time = time.time()  #  100
for i in range(100000):
    print(i)
end_time = time.time()
print('for循环的执行时间是:%s'%(end_time - start_time))
time.sleep(3)
'''让程序原地等待三秒'''
print('睡醒了 还是很懵逼')

装饰器前期推导

import time
def index():
    time.sleep(3)
    print('from index')
'''统计index函数的执行时间'''
start_time = time.time()  # 在调用index函数之前获取一下时间戳
index()  # 调用index函数
end_time = time.time()
print(end_time - start_time)

缺陷:
如果有多个index需要统计时间 则需要重复编写代码
解决措施:
封装成函数

def get_time():
    start_time = time.time()  # 在调用index函数之前获取一下时间戳
     index()  # 调用index函数
     end_time = time.time()
     print('函数的执行时间是:',end_time - start_time)

缺陷:
如果有多个不同的函数需要统计时间 那么上述的解决措施不够完善
解决措施:
给函数体添加形参(动态传参)

def home():
    time.sleep(5)
    print('from home')

def get_time(xxx):
    start_time = time.time()  # 在调用index函数之前获取一下时间戳
    xxx(*args,**kwargs)  # 调用index函数
    end_time = time.time()
    print('函数的执行时间是:',end_time - start_time)
 get_time(index)
 get_time(home)

缺陷:
不同形参个数的函数无法兼容统计
解决措施:
*args **kwargs
但是在我们目前的代码中无法实现(暂且忽略)

def func1(a):
    time.sleep(1)
    print('from func1')
get_time(func1)

缺陷:
改变了原来的调用方式
解决措施:
装饰器推导流程

装饰器各种版本

import time

"""针对有参无参函数如何兼容"""
def outer(xxx):
    def get_time(*args, **kwargs):
        start_time = time.time()  # 在调用index函数之前获取一下时间戳
        res = xxx(*args, **kwargs)  # 调用index函数
        end_time = time.time()
        print('函数的执行时间是:', end_time - start_time)
        return res
    return get_time

def home():
    time.sleep(2)
    print('from home')
    return '执行home函数之后的返回值'

def index(name):
    time.sleep(1)
    print('from index')
    return '执行index函数之后的返回值'

home = outer(home)
xxx = home()
print(xxx)


index = outer(index)
res = index('jason')
print(res)

装饰器的固定模板

from functools import wraps  # 装饰器修复计数
def outer(func_name):
    @wraps(func_name)  # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner

import time
def home():
    time.sleep(1)
    print('from home')
    return 'home返回值'


home = outer(home)
res = home()
print(res)
"""
执行home函数之前需要添加校验用户身份的功能
"""


# 装饰器语法糖
import time

@outer  #  home = outer(真正的函数名home)
def home():
    '''我是home函数 我要热死了!!!'''
    time.sleep(1)
    print('from home')
    return 'home返回值'

help(home)
print(home)
home()

def index():
    '我是index函数 我的功能很强大'
    pass

# help(index)

作业

1.编写一个用户认证装饰器
基本要求
执行每个函数的时候必须先校验身份 eg: jason

def outer(func_name):
    def inner(*args, **kwargs):
        '''登录程序'''
        username = input('username:').strip()
        password = input('password:').strip()
        if username == 'jason' and password == '123':
            res = func_name(*args, **kwargs)
            return res
        else:
            print('登录失败')
    return inner

@outer
def func_name(*args, **kwargs):
    print('欢迎你jason')

func_name()

拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
函数:register login transfer withdraw
提示:全局变量 记录当前用户是否认证

user_login = False
def outer(func_name):
    def inner(*args,**kwargs):
        '''登录程序'''
        global user_login   # 将user_login变量设置成全局变量
        if user_login:
            ret = func_name(*args, **kwargs)
            return ret
        else:
            username = input('username:').strip()
            password = input('password:').strip()
            if username == 'jason' and password == '123':
                user_login = True
                ret = func_name(*args, **kwargs)
                return ret
            else:
                print('登录失败')
    return inner

@outer
def func_name_1(*args, **kwargs):
    print('欢迎你jason')

@outer
def func_name_2(*args, **kwargs):
    print('没有验证')

func_name_1()
func_name_2()
posted @   空白o  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示