[Python-ideas] @partials = decorators
Alex Rodrigues
lemiant at hotmail.com
Mon Feb 10 20:44:38 CET 2014
This is a really cool idea. I'm +1. The first time I learned about decorators the way that you pass them arguments was both very non-intuitive and seemed almost like a sneaky hack rather than an intended feature.
# In my opinion this is more intuitive than the old way
def annotate(msg, foo, *arg, **kwargs):
print msg
foo(*arg, **kwargs)
@annotate("Addition")
def func(a, b):
print a + b
#The old way
def annotate(msg):
def deco(foo):
def wrapper(*args, **kwargs):
print msg
foo(*args, **kwargs)
return wrapper
return deco
@annotate("Addition")
def func(a, b):
print a + b
(Ironically I had a really hard time getting the "old" one put together correctly). This also very effectively simplifies a lot of closure cases. There is one thing I don't quite understand, is it necessary to explicitly state that some function is a continuation each time you add arguments? As I understand it, that would mean decorators with arguments have to be called by "@@deco(a, b)".
This would actually help me out in a real world example at this very moment, which is currently really, really hard to do cleanly. I am using iPython notebook and I'm creating two histograms like so:
#data is a pandas Series() objects
data.hist()
data.hist(log=True)
In the notebook these are both reasonably skinny graphs but they stack on top of each other instead of side by side. I looked it up and that can be fixed like so:
fig = plt.figure()
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
data.hist(ax=ax1)
data.hist(ax=ax2, log=True)
This is pretty cumbersome to write out every time so I wanted a function that could just be called on arbitrary histograms like side_by_side(data1.hist(bottom=0.1, log=True), data2.hist(bins=10)). The problem is that I do not have the axes available when I call the function and once I pass the plots to the function they have already been evaluated and there is no way to add arguments retroactively. With the continuation syntax it would be amazingly easier:
def side_by_side(plot1, plot2):
fig = plt.figure()
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
plot1(ax=ax1)
plot2(ax=ax2)
side_by_side(@data.hist(), @data.hist(log=True)) #Technically the first one doesn't need to be a continuation, but whatever.
tldr; I like it and see a decent number of applications. Also I'm wondering if you'd have to chain continuations @@a('arg1')('arg2')('arg3').
- Alex
More information about the Python-ideas
mailing list