P
Peter Otten
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
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