python-闭包与装饰器

闭包

  • 这是我的一个函数,需要为其添加许多新的功能,假如里面有几百行代码,但需要在不改变其原有的代码条件下进行。
def my_func():
    print('this is my func ...')
  • 那么现在想到的就是使用一个嵌套函数,传入一个函数对象给外函数,外函数返回内函数的调用, 然后传入函数对象给内函数,然后调用该函数,于是完成了不改变原有函数的条件下,添加了新的功能。
def func_outer(func):
    print('this is outer func ...')

    def func_inner(*arg, **kwargs):
    	# 可以在内函数中添加新的功能
        print('this is inner func')
        return func()
    
    return func_inner

f = func_outer(my_func)
f()
  • 可以看到运行顺序如下:
this is outer func ...
this is inner func
this is my func ...

装饰器

  • 但是实际开发的过程中,代码都这样写的话,会显得代码有些冗余,这个时候就可以使用到装饰器这么一个东西,使用起来也十分的简单,如下:
def func_outer(func):
    print('this is outer func ...')

    def func_inner(*arg, **kwargs):
        print('this is inner func')
        return func()
    
    return func_inner


@func_outer
def my_func():
    print('this is my func ...')

# my_func()
  • 结果如下,没有调用my_func函数时,func_outer便自动调用了,当调用my_func时func_inner就会自动调用,@即语法糖,将两个函数进行关联
D:\user\80005354\桌面\stupy>D:/python/python.exe d:/user/80005354/桌面/stupy/1-装饰器.py
this is outer func ...
  • 同时,还可以为装饰器添加参数,即在在装饰器上再封装一个装饰器用来传递参数,只需要将内层的函数对象再次返回即可
def func_oouter(name):

    def func_outer(func):
        print('this is outer func ...')
		
        def func_inner(*arg, **kwargs):
	        print('my name is ', name)
            print('this is inner func')
            return func()
        
        return func_inner

    return func_outer

@func_oouter(name='bruin')
def my_func():
    print('this is my func ...')

my_func()
  • 结果如下:
D:\user\80005354\桌面\stupy>D:/python/python.exe d:/user/80005354/桌面/stupy/1-装饰器.py
this is outer func ...
my name is  bruin
this is inner func
this is my func ...

使用类装饰器

  • 假如有一个people这个方法,也可以将people做为静态方法写入类中,但此时需要不改变people方法的同时,添加一个speak的功能。如果想让一个类使用装饰器,就得让其实现call方法能被调用,先看看普通调用方式
class Speak(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *arg, **kwargs):
        self.speak()
        return self.func(*arg, **kwargs)
        
    def speak(self):
        print('I can speak now!')

	
def people(*arg, **kwargs):
    print(kwargs['name'], 'is dance ~ ~')


speak = Speak(people)
speak(name='jack')

type(people), isinstance(people, Speak)

# 结果如下:
I can speak now!
jack is dance ~ ~
(function, False)
  • 当我们使用装饰器时
@Speak
def people(*arg, **kwargs):
    print(kwargs['name'], 'is dance ~ ~')

p = people(name='jack')

type(people), isinstance(people, Speak)

# 结果如下:
I can speak now!
jack is dance ~ ~
(__main__.Speak, True)

可以看到在使用装饰器之后,people已经不是原来的那个people了,此时我们可以使用functools.wraps方法保留people原有的属性。

functools.wraps

import functools

class Speak(object):
    def __init__(self, *args, **kwargs):
        print(args)

    def __call__(self, func):
       
        @functools.wraps(func)
        def inner_wraps(*arg, **kwargs):
            self.speak()
            return func(*arg, **kwargs)
        
        return inner_wraps
    
    def speak(self):
        print('I can speak now!')

@Speak(1,2)
def people(*arg, **kwargs):
    print(kwargs['name'], 'is dance ~ ~')


people(name='jack')

type(people), isinstance(people, Speak)


# 结果如下
(1, 2)
I can speak now!
jack is dance ~ ~
(function, False)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值