装饰器整理

本文深入解析Python装饰器的概念,探讨其工作原理,包括无参、带参、带返回值及装饰器自身带参数的情况,同时阐述了装饰器的实用价值。

什么是装饰器

装饰器(Decorators) 可能是Python中最难掌握的概念之一了,在解释是什么是装饰器之前,我们需要知道,python是一门面向对象的语言,python基本思想就是一切皆对象,数据类型是对象,类是对象,类实例也是对象,所以对于装饰器而言,重要的是函数也是对象!既然对象,就可以进行赋值操作

def func():
    print('执行功能ing')

if __name__ == '__main__':
    func1 = func
    func1()

原来我们定义的函数名是func,但是我们把函数赋值给func1后,也可以通过func1()来调用func函数。
我们也可以把函数当作参数传递给其他函数:

def do_something():
	print('正在完成功能')
def func(f):
	f()
if __name__ == '__main__':
	func(do_somethong)

因为python中函数既可以赋值给其他变量,也可以当作参数传递给其他函数,但是函数也不同于其他变量,函数也有自己的特性,函数内部可以定义函数,可以有返回值:

def func():
	def inner_func():
		print('我是内部函数')
	return inner_fun
if __name__ == '__main__':
	func1 = func()
	func1()

综上所述,发现有几个特性:
1.可以赋值给其他变量;
2.可以作为参数传递给其他函数;
3.可以在内部定义一个函数;
4.可以当作返回值;

从本质上说,装饰器就是一个函数,它也具有我们上面说的几个特性,并且充分利用了这几个特性。装饰器接受一个普通函数作为参数,并在内部定义了一个函数,在这个内部函数中实现了一些功能,并调用传递进来的函数,最后将内部函数作为返回值返回。如果一个函数把这个步骤全走了一遍,我们就可以认为,这个函数是一个装饰器函数,或者说是装饰器

def func(f):
	def inner_func():
		print('{}函数开始运行'.format(f.__name__))
		f()
		print('{}函数运行结束'.format(f.__name__))
	return inner_func

def do_something():
	print('正在完成的功能')

if __name__ == '__main__':
	do_something = func(do_something)
	do_something()

在上面代码中,我们将do_something方法作为参数传递给func函数,在func内部我们定义了一个inner_func方法,并在这个方法中添加了函数开始执行和结束执行的提示,在func方法最后,我们将inner__func作为参数返回,然后我们将func函数的返回值赋值给了do_something,所以,最后一次调用的do_something函数已经不再是最初的do_something函数,而是func函数内部定义的inner__func函数,所以最后执行do_something函数时,会有函数开始执行和结束执行的提示功能,而后面在调用do_something函数时,因为返回值是inner_func单纯的函数名,所以执行do_something时,需要加括号,do_something()。
一般装饰器大多是与’@‘符号结合起来用,@符号所实行的功能就是do_something = func(do_something)这行代码的功能。

def func(f):
	def inner_func():
		print('{}函数开始执行'.format(f.__name__))
		f()
		print('{}函数结束运行'.format(f.__name__))
	return inner_func

@func
def do_something():
	print('正在执行功能')

if __name__ == '__main__':
	do_something()

输出结果:
do_something函数开始执行
正在执行功能
do_something函数结束运行

为什么要用装饰器

1.可以在不对被装饰函数做任何修改的前提下,给被装饰函数附加一些功能。使用@func对do_something函数进行装饰时,我们没有对do_someting函数代码做任何改动,但是被装饰后的do_something函数却多了其他功能。
2.不改变被装饰函数的调用方式。在被装饰前,我们通过do_something()调用这个函数,被装饰后,还是通过do_something调用这个函数。
3.代码更加精简。如果有多个函数需要添加开始运行和结束运行的提示功能,我们只需要在函数前面添加@func就可以了。

import time
def timmer(f):
	def inner_func():
		start_ = time.time()
		f()
		end_ = time.time()
		print('{}函数运行消耗时间为:{}'.format(f.__name__,end_-start_))
	return inner_func

@timmer
def do_something():
	print('函数正在执行')
	time.sleep(1)
if __name__ == '__main__':
	do_something()
	

深入理解装饰器

被装饰的函数带返回值

针对有返回值的函数,装饰器该怎么写呢?

def func(f):
	def inner_func():
		print('{}函数开始执行'.format(f.__name__))
		ret = f()
		print('{}函数结束运行'.format(f.__name__))
		return ret #这里返回值
	return inner_func

@func
def do_something():
	print('正在完成功能')
	return'我是返回值'

if __name__ == '__main__':
	ret = do_something()
	print(ret)

我们知道,被装饰后的do_something函数其实不再时最初的do_something函数,而是装饰器内部定义的inner_func函数,所以,被装饰的函数的返回值只需要通过装饰器内部定义的inner_func函数返回值返回即可。

被装饰函数带参数

对于装饰器,我们要深刻理解一件事:被装饰后的do_something函数已经不再是原来的do_something函数,而是装饰器内部的inner_func函数。 如果被装饰的函数有参数a,我们还是通过do_something(a)的方式传递输出,不过我们调用do_someting实质调用的inner_func函数,那么在定义装饰器时,定义的inner_func函数时也需要接受参数。

def func(f):
	def inner_func(a):
		print('{}函数开始运行'.format(f.__name__))
		ret = f(a)
		print('{}函数结束运行'.format(f.__name__))
		return ret
	return inner_func

@func		
def do_something(a):
 	print('你好',a)
 	return '我是返回值'
 	
if __name__ == '__main__':
	ret = do_something('姚明')
	print(ret)
 	

如果不知道有多少个位置参数,多少个关键字参数时,我们可以用arg和*kwargs

"""
    在不改变原有功能(fun01 fun02)调用与定义情况下,
    为其增加新功能(打印函数执行时间).
"""

import time

def print_execute_time(func):
    def wrapper(*args, **kwargs):
        # 记录调用前的时间
        start_time = time.time()
        result = func(*args, **kwargs)
        # 记录调用后的时间
        execute_time = time.time() - start_time
        print("执行时间是:", execute_time)
        return result

    return wrapper


@print_execute_time
def fun01():
    time.sleep(2)  # 睡眠2秒,用于模拟程序执行的过程
    print("fun01执行完毕喽")


@print_execute_time
def fun02(a):
    time.sleep(1)
    print("fun02执行完毕喽,参数是:", a)

if __name__ == '__main__':
	fun01()
	fun02(100)

装饰器本身带参数

我们上面所写的装饰器都没有参数,或者说只有一个自带的参数,也就是被装饰函数函数名。其实,装饰器也是可以有其他参数的,这样装饰器更加灵活。

def language(lang='中文'):#这里带参数
	def func(f):#嵌套一层
		def inner_func(*args,**kwargs):
			if lang=='中文':
				print('{}函数开始运行'.format(f.__name__))
			else:
				print('The function of {} starts running'.format(f.__name__))
			ret = f(*args,**kwargs)
			if lang=='中文':
				print('{}函数结束运行'.format(f.__name__))
			else:
				print('The function of {} ends running'.format(f.__name__))
			return ret
		return inner_func
	return func

@language('中文')
def do_something(a):
	print('你好',a)
	
@language('English')
def do_something_2(a):
    print('你好,{}!'.format(a))
    
if __name__ == '__main__':
    do_something('姚明')
    print('-------------------------')
    do_something_2('姚明')

装饰器也是可以多层嵌套使用的,也就是说,一个函数可以被多个装饰器所装饰,执行顺序是从下到上的优先顺序加载装饰

import time

print(1)
def func(f):
    print(2)
    def inner_func(*name1, **name2):
        print('{}函数开始运行……'.format(f.__name__))
        f(*name1, **name2)
        print('{}函数结束运行……'.format(f.__name__))
    print(3)
    return inner_func

print(4)
def timmer(f):
    print(5)
    def inner_timmer(*args, **kwargs):
        print('开始计时……')
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        print('开始结束……')
        time_cost = end_time - start_time
        print('{}函数运行时长为:{}秒'.format(f.__name__, time_cost))
    print(6)
    return inner_timmer

print(7)
@func
@timmer
def do_something(name):
    time.sleep(1)
    print('你好,{}!'.format(name))

print(8)
def do_something_2(name):
    time.sleep(1)
    print('你好,{}!'.format(name))


if __name__ == '__main__':
    print(9)
    do_something(name='姚明')
    print('-------------------------')
    func(timmer(do_something_2))(name='姚明')  # 执行效果与上面使用了@符号的do_something一样
内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,涵盖正向与逆向运动学求解、正向动力学控制,并采用拉格朗日-欧拉法推导逆向动力学方程,所有内容均通过Matlab代码实现。同时结合RRT路径规划与B样条优化技术,提升机械臂运动轨迹的合理性与平滑性。文中还涉及多种先进算法与仿真技术的应用,如状态估计中的UKF、AUKF、EKF等滤波方法,以及PINN、INN、CNN-LSTM等神经网络模型在工程问题中的建模与求解,展示了Matlab在机器人控制、智能算法与系统仿真中的强大能力。; 适合人群:具备一定Ma六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)tlab编程基础,从事机器人控制、自动化、智能制造、人工智能等相关领域的科研人员及研究生;熟悉运动学、动力学建模或对神经网络在控制系统中应用感兴趣的工程技术人员。; 使用场景及目标:①实现六自由度机械臂的精确运动学与动力学建模;②利用人工神经网络解决传统解析方法难以处理的非线性控制问题;③结合路径规划与轨迹优化提升机械臂作业效率;④掌握基于Matlab的状态估计、数据融合与智能算法仿真方法; 阅读建议:建议结合提供的Matlab代码进行实践操作,重点理解运动学建模与神经网络控制的设计流程,关注算法实现细节与仿真结果分析,同时参考文中提及的多种优化与估计方法拓展研究思路。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值