![](https://secure.gravatar.com/avatar/047f2332cde3730f1ed661eebb0c5686.jpg?s=120&d=mm&r=g)
2011/8/6 Carl Matthew Johnson <cmjohnson.mailinglist@gmail.com>:
On Aug 6, 2011, at 12:53 PM, Devin Jeanpierre wrote:
My favorite declarative-namedtuple hack is http://code.activestate.com/recipes/500261-named-tuples/#c16
Devin
For non-link followers:
def _namedtuple(func): return namedtuple(func.__name__, func.__code__.co_varnames)
@_namedtuple def Point(x,y): pass
That is very clever, but it kind of illustrates my point about needing a new keyword. When you see "def" don't you naturally think, "OK, what comes out of this will be a function named Point." But what comes out of this is not a function. It's a namedtuple, which is quite different…
I'm not sure I find that much of an objection. There are plenty of situations where decorators are used to seriously pervert the type of the defined name. Plus, what's a function? A class can be called as well. What's the difference?
A similar case can be made about
@sort_list_with_keyfunc(my_list) def result(item): ... return normalized_item
It's a neat way of getting out of writing the keyfunc before the sort, but it's a bad practice because you're def-ing a sorted list, not a function.
In this specific case I agree it's just confusing. (The difference is that 'Point' above still can be called with x and y arguments, returning a Point object.)
Also a Ruby-like each can be done through abuse of decorators
@each(my_list) def squared_list(item): return item ** 2
Neat but it breaks the reader's expectations. (Also, a list comprehension is shorter.)
Not to mention faster. The main reason why the argument against these doesn't provide an argument against @_namedtuple is that they don't create a callable thing at all. -- --Guido van Rossum (python.org/~guido)