from
inspect
import
getmembers, getargspec
from
functools
import
wraps
def
wraps_decorator(f):
@wraps
(f)
def
wraps_wrapper(
*
args,
*
*
kwargs):
return
f(
*
args,
*
*
kwargs)
return
wraps_wrapper
class
SomeClass(
object
):
@wraps_decorator
def
method(
self
,
x, y):
pass
obj
=
SomeClass()
for
name, func
in
getmembers(obj, predicate
=
inspect.ismethod):
print
"Member Name: %s"
%
name
print
"Func Name: %s"
%
func.func_name
print
"Args: %s"
%
getargspec(func)[
0
]
class
myDecorator(
object
):
def
__init__(
self
,
fn):
print
"inside myDecorator.__init__()"
self
.fn
=
fn
def
__call__(
self
):
self
.fn()
print
"inside myDecorator.__call__()"
@myDecorator
def
aFunction():
print
"inside aFunction()"
print
"Finished decorating aFunction()"
aFunction()
你會發現,即使是你你用了functools的wraps,你在用getargspec時,參數也不見了。
要修正這一問,我們還得用Python的反射來解決,下面是相關的代碼:
1
2
3
4
5
6
7
8
9
10
11
12
|
def get_true_argspec(method): argspec =
inspect.getargspec(method) args =
argspec[ 0 ] if args
and args[ 0 ] = = 'self' : return argspec if hasattr (method, '__func__' ): method =
method.__func__ if not
hasattr (method,
'func_closure' ) or
method.func_closure is
None : raise Exception( "No closure for method." ) method =
method.func_closure[ 0 ].cell_contents return get_true_argspec(method) |
當然,我相信大多數人的程序都不會去getargspec。所以,用functools的wraps應該夠用了。
class
MyApp():
def
__init__(
self
):
self
.func_map
=
{}
def
register(
self
, name):
def
func_wrapper(func):
self
.func_map[name]
=
func
return
func
return
func_wrapper
def
call_method(
self
, name
=
None
):
func
=
self
.func_map.get(name,
None
)
if
func
is
None
:
raise
Exception(
"No function registered against - "
+
str
(name))
return
func()
app
=
MyApp()
@app
.register(
'/'
)
def
main_page_func():
return
"This is the main page."
@app
.register(
'/next_page'
)
def
next_page_func():
return
"This is the next page."
print
app.call_method(
'/'
)
print
app.call_method(
'/next_page'
)