修饰符
函数是一种对象
在 Python
中,函数是也是一种对象。
In [1]:
- def foo(x):
- print x
- print(type(foo))
- <type 'function'>
查看函数拥有的方法:
In [2]:
- dir(foo)
Out[2]:
- ['__call__',
- '__class__',
- '__closure__',
- '__code__',
- '__defaults__',
- '__delattr__',
- '__dict__',
- '__doc__',
- '__format__',
- '__get__',
- '__getattribute__',
- '__globals__',
- '__hash__',
- '__init__',
- '__module__',
- '__name__',
- '__new__',
- '__reduce__',
- '__reduce_ex__',
- '__repr__',
- '__setattr__',
- '__sizeof__',
- '__str__',
- '__subclasshook__',
- 'func_closure',
- 'func_code',
- 'func_defaults',
- 'func_dict',
- 'func_doc',
- 'func_globals',
- 'func_name']
在这些方法中,call
是最重要的一种方法:
In [3]:
- foo.__call__(42)
- 42
相当于:
In [4]:
- foo(42)
- 42
因为函数是对象,所以函数可以作为参数传入另一个函数:
In [5]:
- def bar(f, x):
- x += 1
- f(x)
In [6]:
- bar(foo, 4)
- 5
修饰符
修饰符是这样的一种函数,它接受一个函数作为输入,通常输出也是一个函数:
In [7]:
- def dec(f):
- print 'I am decorating function', id(f)
- return f
将 len
函数作为参数传入这个修饰符函数:
In [8]:
- declen = dec(len)
- I am decorating function 33716168
使用这个新生成的函数:
In [9]:
- declen([10,20,30])
Out[9]:
- 3
上面的例子中,我们仅仅返回了函数的本身,也可以利用这个函数生成一个新的函数,看一个新的例子:
In [10]:
- def loud(f):
- def new_func(*args, **kw):
- print 'calling with', args, kw
- rtn = f(*args, **kw)
- print 'return value is', rtn
- return rtn
- return new_func
In [11]:
- loudlen = loud(len)
In [12]:
- loudlen([10, 20, 30])
- calling with ([10, 20, 30],) {}
- return value is 3
Out[12]:
- 3
用 @ 来使用修饰符
Python
使用 @
符号来将某个函数替换为修饰符之后的函数:
例如这个函数:
In [13]:
- def foo(x):
- print x
- foo = dec(foo)
- I am decorating function 64021672
可以替换为:
In [14]:
- @dec
- def foo(x):
- print x
- I am decorating function 64021112
事实上,如果修饰符返回的是一个函数,那么可以链式的使用修饰符:
- @dec1
- @dec2
- def foo(x):
- print x
使用修饰符 loud
来定义这个函数:
In [15]:
- @loud
- def foo(x):
- print x
In [16]:
- foo(42)
- calling with (42,) {}
- 42
- return value is None
例子
定义两个修饰器函数,一个将原来的函数值加一,另一个乘二:
In [17]:
- def plus_one(f):
- def new_func(x):
- return f(x) + 1
- return new_func
- def times_two(f):
- def new_func(x):
- return f(x) * 2
- return new_func
定义函数,先乘二再加一:
In [18]:
- @plus_one
- @times_two
- def foo(x):
- return int(x)
In [19]:
- foo(13)
Out[19]:
- 27
修饰器工厂
decorators factories
是返回修饰器的函数,例如:
In [20]:
- def super_dec(x, y, z):
- def dec(f):
- def new_func(*args, **kw):
- print x + y + z
- return f(*args, **kw)
- return new_func
- return dec
它的作用在于产生一个可以接受参数的修饰器,例如我们想将 loud
输出的内容写入一个文件去,可以这样做:
In [21]:
- def super_loud(filename):
- fp = open(filename, 'w')
- def loud(f):
- def new_func(*args, **kw):
- fp.write('calling with' + str(args) + str(kw))
- # 确保内容被写入
- fp.flush()
- fp.close()
- rtn = f(*args, **kw)
- return rtn
- return new_func
- return loud
可以这样使用这个修饰器工厂:
In [22]:
- @super_loud('test.txt')
- def foo(x):
- print x
调用 foo
就会在文件中写入内容:
In [23]:
- foo(12)
- 12
查看文件内容:
In [24]:
- with open('test.txt') as fp:
- print fp.read()
- calling with(12,){}
In [25]:
- import os
- os.remove('test.txt')