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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

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