Reputation: 19922
Sorry for long question, but I don't know how to make it shorter.
import time
import functools
def pause(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
time.sleep(1)
return f(*args, **kwargs)
return wrapper
@pause
def func(x, y):
"""desc"""
return x + y
print func(1, 2)
help(func)
Output:
3
Help on function func in module __main__:
func(*args, **kwargs)
desc
It's "classical" implementation - a lot of articles contain it.
-breaks function signature (can be solved by nonstandard module decorator)
-you must use functools for saving name and doc string of function (not very big problem, but slightly more code and magic)
+you can modify function args (not always necessary)
+-? Anything else?
import time
def pause(f):
time.sleep(1)
return f
@pause
def func(x, y):
return x + y
print func(1, 2)
help(func)
Output:
3
Help on function func in module __main__:
func(x, y)
desc
? Why it implementation rarely used in articles and examples? What have I missed?
-you can't modify function args
+not breaks function signature
+less code
+-? Anything else?
import time
class pause(object):
def __init__(self, f):
self.f = f
def __call__(self, *args, **kwargs):
time.sleep(1)
return self.f(*args, **kwargs)
@pause
def func(x, y):
"""desc"""
return x + y
print func(1, 2)
help(func)
Output:
3
Help on pause in module __main__ object:
class pause(__builtin__.object)
| Methods defined here:
|
| __call__(self, *args, **kwargs)
|
| __init__(self, f)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
IMHO, ugly.
import time
class pause(object):
def __call__(self, f):
time.sleep(1)
return f
@pause()
def func(x, y):
"""desc"""
return x + y
print func(1, 2)
help(func)
Output:
3
Help on function func in module __main__:
func(x, y)
desc
-you can't modify function args
-nonstandard syntax for decorator use
+not breaks function signature
+-less code (but more than implementation 2 :) )
+-? Anything else?
import time
import functools
def pause(t):
def wrapper(f):
@functools.wraps(f)
def tmp(*args, **kwargs):
time.sleep(t)
return f(*args, **kwargs)
return tmp
return wrapper
@pause(1)
def func(x, y):
"""desc"""
return x + y
print func(1, 2)
help(func)
Output:
3
Help on function func in module __main__:
func(*args, **kwargs)
desc
It's "classical" implementation - a lot of articles contain it.
-breaks function signature
-nested is worse than flat
-you must use functools for saving name and doc string of function
+you can modify function args
+-? Anything else?
import time
def pause(t):
def wrapper(f):
time.sleep(t)
return f
return wrapper
@pause(1)
def func(x, y):
"""desc"""
return x + y
print func(1, 2)
help(func)
Output:
3
Help on function func in module __main__:
func(x, y)
desc
? Why it implementation rarely used in articles and examples? What have I missed?
-you can't modify function args
+not breaks function signature
+less code
+-? Anything else?
import time
class pause(object):
def __init__(self, darg):
self.darg = darg
def __call__(self, f):
time.sleep(self.darg)
return f
@pause(1)
def func(x, y):
"""desc"""
return x + y
print func(1, 2)
help(func)
Output:
3
Help on function func in module __main__:
func(x, y)
desc
-you can't modify function args
+not breaks function signature
+-less code (but more than implementation 2 :) )
IMHO+ little clearer than nested functions
+-? Anything else?
Upvotes: 2
Views: 322
Reputation: 7892
It sure is good that the implementations 1.2 & 2.2 are "less common than" 1.1 and 2.1, because they do different things. In fact, I wouldn't call them "decorators", because they don't really wrap ("decorate") the function. Instead, they only perform their action once, at the moment the decorated function is parsed. That is, their action (sleep in your case) is performed at function definition time, not at function invocation time.
Try invoking your decorated functions several times and you will see the difference.
Upvotes: 2