Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)

Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)

一,装饰器

 装饰器:本质就是函数,功能是为其它的函数动态添加附加的功能

原则:对修改关闭对扩展开放

1.不修改被修饰函数的源代码

2.不修改被修改函数的调用方式

 装饰器实现的知识储备:高阶函数,函数嵌套,函数闭包

## 高阶函数

# 高阶函数的定义:

1:函数接收的参数是一个参数名

2:函数的返回值是一个函数名

3:满足上述的任意一个条件,都可以称为高阶函数

一,函数接收的参数是一个参数名

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

def test(func):
    print(func)     # <function order at 0x000002AD351AD378>
    func()          # 我是函数order

test(order)         # 函数的实参是一个函数名,所以接收的参数是一个函数名

二,函数的返回值是一个参数名

# 下方程序不合格,函数会重复执行两次(order函数执行两次)
import time
def order():
    time.sleep(4)
    print("我是函数order")

def test(func):
    start_time = time.time()
    func()          # 我是函数order
    stop_time = time.time()
    print("函数 %s 的执行是将为%s " %(func,(stop_time - start_time)))
    return func     # 返回值为函数名

test_order = test(order)
test_order()        # 相当于执行函数 order

# 输出结果
我是函数order
函数 <function order at 0x0000029DBEA298C8> 的执行是将为4.035168170928955 
我是函数order

## 函数嵌套

## 函数闭包 

## 装饰器的架子

def timmer(func):
    def wrapper():
        print(func)
        func()
    return wrapper

 # 下方的程序解决了重复执行函数问题

# 下方程序的问题是:对所要计算执行时间的函数都得加上 test = timmer(test)

import time
def timmer(func):
    def wrapper():
        start_time = time.time()
        func()    # 运行的为test函数
        stop_time = time.time()
        print("程序运行的时间%s"%(start_time-stop_time))
    return wrapper


def test():
    time.sleep(3)
    print("test函数执行完毕")

test = timmer(test)    # 返回函数wrapper地址
test()    # 执行的时wrapper

# 结果
test函数执行完毕
程序运行的时间-3.000077962875366

## 语法糖

# @timmer 相当于 test = timmer(test)

# 当哪个函数需要加上装饰器,则在函数的上方加上@xxxx 语法糖

import time
def timmer(func):
    def wrapper():
        start_time = time.time()
        func()    # 运行的为test函数
        stop_time = time.time()
        print("程序运行的时间%s"%(start_time-stop_time))
    return wrapper

@timmer
def test():
    time.sleep(3)
    print("test函数执行完毕")

test()    # 执行的是wrapper

 

# 当被装饰的函数的参数变化时,装饰器的参数也得变化

import time
def timmer(func):
    def wrapper(name,age):
        start_time = time.time()
        func(name,age)    # 运行的为test函数
        stop_time = time.time()
        print("程序运行的时间%s"%(start_time-stop_time))
        print(name,age)
    return wrapper

@timmer
def test(name,age):
    time.sleep(3)
    print("test函数执行完毕")
test("henry",18)

@timmer
def test2(name,age,addr):
    time.sleep(3)
    print("test2函数执行完毕")
test2("heihei","16","China")
# 程序报错:当被装饰的函数有三个实参时,装饰器中也得有对应的形参

 

# 使用 *args,**kwargs解决,当被装饰的函数的参数变化时,装饰器的参数也得变化的问题

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)    # 运行的为test函数
        stop_time = time.time()
        print("程序运行的时间%s"%(start_time-stop_time))
        print(*args,**kwargs)
    return wrapper

@timmer
def test(name,age):
    time.sleep(3)
    print("test函数执行完毕")
test("henry",18)

@timmer
def test2(name,age,addr):
    time.sleep(3)
    print("test2函数执行完毕")
test2("heihei","16","China")    # 程序不在报错

# 输出
test函数执行完毕
程序运行的时间-3.000153064727783
henry 18
test2函数执行完毕
程序运行的时间-3.0007944107055664
heihei 16 China

 

## 浅浅了解*args与**kwargs

*args:将多个实参放入一个元组中,可以传多个参数

**kwargs:按照关键字传值,将多余的值以字典的形式传递

## *agrs

Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)
Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)

##  将实参与形参对应的按位置传值,多出来的给grgs
# 示例1
def test(a,*args):
    print(a)
    print(args)

test(1,2,3,4,5,6,7)
# 输出
1
(2, 3, 4, 5, 6, 7)

--------------------------------------------------------------

# 示例2(位置参数,默认参数,*args)
def test(a,b = 1 ,*args):
    print(a)
    print(b)
    print(args)

test(1,2,3,4,5,6,7)    # 1给了a,b=1的值被重置为2,其余的给了args
# 输出
1
2
(3, 4, 5, 6, 7)

-------------------------------------------------------------

# 示例3(位置参数,*args,默认参数)
def test(a,*args,b = 1 ):
    print(a)
    print(b)
    print(args)
test(1,2,3,4,5,6,7)
# 输出
1
1
(2, 3, 4, 5, 6, 7)

示例代码

 

 

 

## **kwargs(形参中按关键字传值,多余的以自定的形式传递)

Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)
Python_基础_(装饰器,*args,**kwargs,高阶函数,函数闭包,函数嵌套)

# 示例1 将所有的值给了args
def test(*args,**kwargs):
    print(args)
    print(kwargs)
test(1,2,3,4,5)
# 输出
(1, 2, 3, 4, 5)
{}

---------------------------------------------------------

# 示例2
def test1(a,**kwargs):
    print(a)
    print(kwargs)
test1(1,b=2,c=3,d=4)
# 输出    将1给了a,将其余的以字典的形式给了Kwargs
1
{
     'b': 2, 'c': 3, 'd': 4}

-------------------------------------------------------

# 示例3
def test3(a,*args,**kwargs):
    print(a)
    print(args)
    print(kwargs)
test3(1,2,3,4,5,b=6,c=7)
# 输出
1
(2, 3, 4, 5)
{
     'b': 6, 'c': 7}

-----------------------------------------------------

# 错误示例
def test4(z,**kwargs,*args):
    print(z)
    print(kwargs)
    print(args)
test4(1,y=2,3,4,5)
# 报错 SyntaxError: invalid syntax

示例代码

小小补充:

num_l = [1,2,3,4,5,6,7,8]
a,*b,c = num_l
print(a)
print(b)
print(c)
# 输出
1
[2, 3, 4, 5, 6, 7]
8

注:
普通调换两个数
a = 1
b = 2
c = a
a = b
b = a

Python中的一一对应
a,b = b,a

## 携带参数的装饰器

import time
def timmer_test(file_type="aaa"):
    def timmer(func):
        def wrapper(*args,**kwargs):
            if file_type == "aaa":# 执行不同的功能
                print("携带的参数为aaa")
            elif file_type == "bbb":
                print("携带的参数为bbb")
            start_time = time.time()
            res = func(*args,**kwargs)    # 运行的为test函数
            stop_time = time.time()
            print("程序运行的时间%s"%(start_time-stop_time))
            return res
        return wrapper
    return timmer


@timmer_test(file_type="aaa")    # timmer = timmer_test(file_type="aaa") 最终的结果还是@timmer,已经附加一个file_type
def test1():
    time.sleep(3)
    print("test函数执行完毕")

@timmer_test(file_type="bbb")   # 携带不同的参数 执行不同的功能
def test2():
    time.sleep(2)
    print("test函数执行完毕")

test1()
test2()
# 输出
携带的参数为aaa
test函数执行完毕
程序运行的时间-3.0003297328948975
携带的参数为bbb
test函数执行完毕
程序运行的时间-2.00068998336792

 

转载于:https://www.cnblogs.com/Doaoao/p/10134718.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101252.html原文链接:https://javaforall.net

(0)
上一篇 2021年6月18日 下午6:00
下一篇 2021年6月18日 下午7:00


相关推荐

  • ModifyStyle, ModifyStyleEx

    ModifyStyle, ModifyStyleEx1.wtl中的CListViewCtrl调用ModifyStyle,ModifyStyleEx,不起作用,改成_listCtrl.SetExtendedListViewStyle(_listCtrl.GetExtendedListViewStyle()|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES,0);参照http://www.cppblo

    2022年7月19日
    19
  • 项目范围管理计划模板[通俗易懂]

    项目范围管理计划模板[通俗易懂]XX项目项目范围管理计划     文档编号:文档信息:文档名称:文档类别:工程类密   级:内部基准:版本信息:1.0建立日期:创建人:批准人:批准日期: 保管人:存放位置:配置库编辑软件:MicrosoftOffice2007中文版     文档修订记录

    2025年11月30日
    6
  • JavaFX横幅类游戏开发 教训 游戏贴图

    JavaFX横幅类游戏开发 教训 游戏贴图

    2022年1月3日
    49
  • DuiLib简介

    DuiLib简介duilib 库是一款轻量级的 C 界面开发库 遵循开源 BSD 协议 可以免费用于商业项目 由杭州月牙儿网络技术有限公司开发 duilib 库的源码下载地址 https github com duilib duilib 传统 MFC 界面库有如下问题 1 不美观 2 界面细节处理不好 3 使用硬编码 4 开发效率低下 5 生成程序体

    2026年3月19日
    2
  • oracle数据库运维服务

    oracle数据库运维服务oracle 数据库运维服务 360oracle 技术服务中心可提供以下运维服务数据库容灾服务数据灾备系统式保障数据安全的重要手段之一 OracleDataGu 通过使用称为 standbydatab 的数据库来防止出现数据的灾难 它通过将 prinarydatab 数据库的重做日志传到并应用到 standbydatab 数据库来使 standby

    2026年3月17日
    1
  • MVC三层架构的实现

    MVC三层架构的实现在MVC设计模式中认为,任何软件都可以分为三部分组成:1.控制程序流转的控制器Controller2.封装数据处理数据的模型Model3.负责展示数据的视图View在MVC设计思想中要求符合MVC设计思想的软件应该保证MVC这三部分相互独立,互不干扰,每一部分只负责自己擅长的部分。即某一个模块发生变化,应该尽量做到不影响其他两个模块,这样有利于后期的扩展和维护,代码也可复用…

    2022年6月25日
    38

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号