Suppose we have a function that returns the boiling point of water in celsius:
def boiling_point():
return 100
print boiling_point() # returns 100
Suppose we are now at high altitude and the boiling point is now 97 degree. We can wrap the function like this:
def calibrate(f):
def g():
return f() - 3
return g
def boiling_point():
return 100
print boiling_point() # returns 100
boiling_point_calibrated = calibrate(boiling_point)
print boiling_point_calibrated() # returns 97
In fact, we can do better. We can assign the calibrated function back to the original function name. As a result, nothing is changed on the calling side:
def calibrate(f):
def g():
return f() - 3
return g
def boiling_point():
return 100
print boiling_point() # return 100
boiling_point = calibrate(boiling_point)
print boiling_point() # returns 97
When used in this way, the function calibrate() is called a decorator, and there is a shortcut for it:
def calibrate(f):
def g():
return f() - 3
return g
@calibrate
def boiling_point():
return 100
print boiling_point() # returns 97
Even better is for the offset to be configurable. The boiling point is dependent on the altitude after all. What we can do is to create a function which returns a function that decorates a function:
def calibrate_offset(offset):
def calibrate(f):
def g():
return f() - offset
return g
return calibrate
@calibrate_offset(3)
def boiling_point():
return 100
print boiling_point() # returns 97
Finally we can generalize the original function by adding *args and **kwargs to it:
def calibrate_offset(offset):
def calibrate(f):
def g(*args, **kwargs):
return f(*args, **kwargs) - offset
return g
return calibrate
@calibrate_offset(3)
def boiling_point():
return 100
print boiling_point() # returns 97
Lastly, decorator can be nested. What do you think x will be in the following case?
def calibrate_offset(offset):
def calibrate(f):
def g(*args, **kwargs):
return f(*args, **kwargs) - offset
return g
return calibrate
@calibrate_offset(3)
@calibrate_offset(4)
def boiling_point():
return 100
x = boiling_point()
No comments:
Post a Comment