decorator with keyword
Peter Otten
__peter__ at web.de
Thu Aug 12 05:17:15 EDT 2004
I'm sure they have been mentioned somewhere but here are some more
advantages of a decorator keyword (I use "transform"):
- The docstring can be moved to the top of the decorator suite.
- Simple attributes that don't affect the function's operation directly can
be written in the "natural" name = value form.
- Though I expect them to be rare like they are in classes today, statements
like if __debug__: decorateForDebugging would be possible.
A docstring and a single decorator - the common case:
transform:
""" Factory for new decorator syntaxes.
Keeps all proposals in a list and will recombine
them at random if called without a spec. """
staticmethod
def makeDecoratorSyntax(spec=None):
raise NotImplementedException()
The same with a pie:
@staticmethod
def makeDecoratorSyntax(spec=None):
""" Factory for new decorator syntaxes.
Keeps all proposals in a list and will recombine
them at random if called without a spec. """
raise NotImplementedException()
I'd say no clear winner here. Now a heavily decorated function:
transform:
"""This method blah, blah.
It supports the following arguments:
- longArgumentOne -- a string giving ...
- longArgumentTwo -- a number giving ...
blah, blah.
"""
author = "BDFL"
status = "experimental"
grammar = "'@' dotted_name [ '(' [arglist] ')' ]"
staticmethod
def longMethodNameForEffect(longArgumentOne=None,
longArgumentTwo=42):
if longArgumentOne is None:
longArgumentOne = setDefault(longArgumentTwo)
for line in longArgumentOne:
if not isBogus(line):
print line
The same with pies:
@funcattrs(author="BDFL", status="experimental",
grammar="'@' dotted_name [ '(' [arglist] ')' ]")
@staticmethod
def longMethodNameForEffect(longArgumentOne=None,
longArgumentTwo=42):
"""This method blah, blah.
It supports the following arguments:
- longArgumentOne -- a string giving ...
- longArgumentTwo -- a number giving ...
blah, blah.
"""
if longArgumentOne is None:
longArgumentOne = setDefault(longArgumentTwo)
for line in longArgumentOne:
if not isBogus(line):
print line
A long docstring can indeed tear apart signature and implementation.
For the sake of completeness, a plain old function:
def filter(cond, seq):
"""filter(function or None, sequence) -> list, tuple, or string
Return those items of sequence for which function(item) is true. If
function is None, return the items that are true. If sequence is a
tuple or string, return the same type, else return a list."""
if cond is None:
cond = bool
return [item for item in seq if cond(item)]
transform:
"""filter(function or None, sequence) -> list, tuple, or string
Return those items of sequence for which function(item) is true. If
function is None, return the items that are true. If sequence is a
tuple or string, return the same type, else return a list."""
def filter(cond, seq):
if cond is None:
cond = bool
return [item for item in seq if cond(item)]
"transform" looks a bit pathetic for a docstring, but otherwise I'd say the
grouping might even be slighly clearer. Note how the function signature is
duplicated in the docstring taken from 2.3's filter() - that helps a lot
for long decoration suites.
The decoration suite would generate a list of (name, value) tuples which are
applied to the function like so
trafos = [("__doc__", "This method..."), ("author", "BDFL"), ..., (None,
staticmethod)]
trafos.reverse()
for name, value in trafos:
if name:
setattr(func, name, value)
else:
func = value(func)
I think I would even prefer something like the above over the current
classdict passed to metaclasses, i. e. ordering information and "unnamed
attributes" could be useful in classes, too.
Peter
More information about the Python-list
mailing list