关于python的装饰器

在廖大的装饰器这一章节的task,遇到了这样的问题

请编写一个decorator,能在函数调用的前后打印出'begin call''end call'的日志。

再思考一下能否写出一个@log的decorator,使它既支持:

@log
def f():
    pass
又支持:

@log('execute')
def f():
    pass

一开始我是这样写的:

import functools

def log(text = ''): #我希望用一个默认参数来解决 @log 的情况
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log
def now():
    print("---now----")
now()

@log('exec')
def now():
    print("---now----")
now()

然后build后的信息:

Traceback (most recent call last):
  File "F:\py\testttt.py", line 34, in <module>
    now()
TypeError: decorator() missing 1 required positional argument: 'func'`

原因分析:
由于 log(text)的返回值是一个函数 decorator(func), 装饰器的写法

@log
def now():

等价于

now = log(now

所以 now 被当作 text的实参传入, 而decorator(func)的形参func并无对应的形参,所以提示decorator()缺少一个位置参数
于是,若采用如下写法:

@log()
def now():
    print("---now----")
now()

结果:
 now():         #前面有一个空格
---now----

当然这样与task的要求不符合了

也就是说,我必须要在log(text)中判断传进来的text到底是函数类型还是其他的类型(字符串,整型等),而不能一劳永逸,因为它log()是一个三层的嵌套函数,参数的对应位置是会造成影响的

改进后如下

import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            if isinstance(text,(str, int, float)):
                print('%s %s():' % (text, func.__name__))
                return func(*args, **kw)
            else:
                print("begin call %s()" % func.__name__)
                func(*args, **kw)
                print("end call %s()" % func.__name__)
        return wrapper
    if isinstance(text,(str, int, float)):
        return decorator
    else:
        return decorator(text) #若text是函数类型的参数,则将它再次传        
                               #入decorator(func) 作为func的实参


@log
def f():
    print("---here1----")
f()
print("")
@log('exec')
def f():
    print("---here2----")
f()
结果:
begin call f()
---here1----
end call f()

exec f():
---here2----
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值