首页 > Python修饰器的问题

Python修饰器的问题

我是一个刚开始学习python的新手,在学习python2.7,根据廖雪峰的教程在学习的,在修饰器这一段遇到了一个小问题,希望大家能够帮忙解答!谢谢!

求解释下面这段代码的运行结果?
运行的结果希望是
321 Call my_name()
JHB

但实际运行结果只有一个
JHB

def log(text):
    def print_log(func):
        #@functools.wraps(func)
        def wrapper(*args, **kw):
            print '%s Call %s():'%(text,func.__name__)
            return func(*args, **kw)
        return wrapper
    return print_log

#@log('Hello')
def my_name():
    print 'JHB'

log('321')(my_name())

如果你的目的是使用装饰器,那你上面的问题有两点:
1、#@log('Hello')需要去除前面的'#'符号,才能使装饰器对你的my_name函数生效;
2、完成第一步后,你最后的一行的调用方式错了,直接调用my_name()应该就能达到你想要的效果了,
装饰器与被装饰的函数之间的关系及调用顺序都是python帮你完成了


改成这样就可以了:

log('321')(my_name)()

我们一层一层来看,log('321')返回一个函数(也就是print_log),这个函数的参数是个函数类型,但是你传进去的my_name()的返回值是None类型


执行log(text)函数最终会返回一个print_log函数,所以你的调用:log('321')(my_name())等同于print_log(my_name())
my_name() 最终只会打印出'JHB'并返回 None,并不会返回一个 func,因此传入print_log的参数并非一个函数,而是None,所以 print_log 函数实际上无法执行。
正确的做法是,首先需要将 log('321')(my_name()) 改为 log('321')(my_name),其等同于print_log(my_name),该函数执行结果会返回wrapper函数,需要注意 wrapperwrapper() 是不同的,前者是函数的标识符,后者则是调用该函数,所以如果需要执行wrapper,还需要增加个(),因此,最终要把你的写法改成:

log('321')(my_name)()

执行结果:

[py27] C:\Users\...\Desktop>python a.py
321 Call my_name():
JHB
【热门文章】
【热门文章】