之前就对装饰器一知半解,看教程到协程部分,更晕了。我要提的问题是:
两层结构的装饰器,作用只是为了包函数的参数吗?
比如样例
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
如果函数没有参数,或者说装饰器不需要使用到函数的参数,那么按照下面这样写有什么问题:
def log(func):
print('call func: %s' %func.__name__)
return func
@log
def fn(a,b):
print(a + b)
fn(1,2)
1
HelloAmadeus 2018-06-06 20:43:53 +08:00 via Android 1
你把装饰器当普通函数用一下,你就明白了。装饰器和普通函数唯一的区别就是装饰器函数会在导入时运行,你实际运行被装饰器装饰的函数是装饰器返回的函数。至于装饰器作用,就是一个语法糖,想怎么用就怎么用,你秉持一个理念,函数可以作为函数的参数,那装饰器在你眼里就是一个普通函数了,普通函数能做什么,装饰器就能做什么。想找一些灵感,可以看看 Python cook book 的装饰器章节
|
2
ipwx 2018-06-06 20:45:46 +08:00 via iPhone
你这代码没问题。另,还可以有三层的
|
3
Kilerd 2018-06-06 20:45:46 +08:00
|
4
HelloAmadeus 2018-06-06 20:46:03 +08:00 via Android
你这样用,下次运行 fn,就不会显示 log 了
|
5
chroming 2018-06-06 20:57:29 +08:00
你的写法并没有改变 fn,装饰器的作用是将原函数名指向一个新函数,你这样包了一层仍然是原函数
|
6
enenaaa 2018-06-06 21:00:22 +08:00
第 2 个例子中 wrapper 不能少。
装饰器就是专门返回 wrapper 的。 |
7
Bramblex2 2018-06-06 21:22:44 +08:00
你需要了解一个基本概念——“高阶函数”,然后一切问题就迎刃而解了
|
8
jatsz 2018-06-06 21:28:53 +08:00 3
1,你这样没毛病。
2,你这样写,比如在函数执行完成后加 log 了,比如你想记录一个函数执行时间的装饰器,你这样写就不行了,而示例中就可以。 3,还有更复杂的是装饰器本身有参数。 以前写过装饰器的文章: https://www.imzjy.com/blog/2012-05-23-python-decorator 4.2 就是三层嵌套的,用来解决装饰器本身有参数的情况。 |
9
Eyon OP @HelloAmadeus
>你实际运行被装饰器装饰的函数是装饰器返回的函数。 @chroming >装饰器的作用是将原函数名指向一个新函数,你这样包了一层仍然是原函数 谢谢! 那么,也就是说可以理解成装饰器返回新函数,而这个新函数返回的是老函数? 比如: ``` def log(func): def wraped_func(*args,**kw): print('do sth...') return func(*args,**kw) return wraped_func @log def fn(a,b): print(a + b) fn(1,2) ``` |
10
neoblackcap 2018-06-07 00:11:27 +08:00
@Eyon 你若是要深挖这个,也可以搜索高级函数以及柯里化(currying)
|
11
gleymonkey 2018-06-07 00:20:08 +08:00
函数作为参数,函数作为返回值。
|
12
nasmatic 2018-06-07 01:34:55 +08:00
你如果这么写没有返回 wrapper:
def log(func): print('call func: %s' %func.__name__) return func 那么假设你装饰一个无参函数,比如这样定义的: def fn(): print('call func: %s' %func.__name__) |
13
nasmatic 2018-06-07 01:36:21 +08:00
你如果这么写没有返回 wrapper:
def log(func): print('call func: %s' %func.__name__) return func 那么假设你装饰一个无参函数,比如这样定义的: def fn(): print "hello" 你最后想执行函数时用 fn()这种形式肯定报错 |
14
ech0x 2018-06-07 05:53:02 +08:00 via iPhone
主要你对函数是一等公民这个概念没有理清,你试着写几个函数,它的参数是函数并且返回值也是函数就明白了。
|
15
dengshuang 2018-06-07 07:44:14 +08:00
5 楼和 6 楼都说的不错,装饰器是要返回一个新的函数的。
你自己的写法,也能在执行时显示结果,但是不能调用它,这和解释器有关了。。。 装饰器是要返回一个新的函数的 装饰器是要返回一个新的函数的 装饰器是要返回一个新的函数的 |
16
whoami9894 2018-06-07 08:04:46 +08:00 via Android
装饰器是一个闭包函数写成 @形式的语法糖
|
18
qwertyegg 2018-06-07 12:55:07 +08:00
@Bramblex2 一个函数的函数为什么要取这么奇怪的名字,我看廖雪峰老师的教程里面也用这个名字。明明已经存在现有的一个命名:泛函
|