[Python-ideas] Decorators for variables
Steven D'Aprano
steve at pearwood.info
Sun Apr 3 00:19:22 EDT 2016
On Fri, Apr 01, 2016 at 07:49:41PM +0200, Matthias welp wrote:
> > > tldr
> > Check out how Django dealt with this. And SQLAlchemy
> > Do their solutions satisfy
>
> The thing I'm missing in those solutions is how it isn't chainable. If I
> would want something that uses access logging (like what Django and
> SQLAlchemy are doing), and some 'mixin' for that variable to prevent cycle
> protection, then that would be hard. The only other way is using function
> composition, and that can lead to statements that are too long to read
> comfortably.
I'm not sure how function composition is harder to read than decorator
syntax:
@logging
@require(int)
@ensure(str)
@validate
@spam
@eggs
x = 999
versus:
x = logging(
require(int)(
ensure(str)(
validate(
spam(
eggs(
999
))))))
is not that different. Sure, you have a few extra brackets, but you have
fewer @ symbols. And if you're going to do that sort of thing a lot, you
just need a couple of helper functions:
def compose(f, g):
# Return a new function which applies f(g(args)).
def composed(*args, **kw):
return f(g(*args, **kwargs))
return composed
def helper(use_logging=False, requires=None, ensures=None,
use_validate=False, use_spam=False, use_eggs=False):
funcs = []
if use_logging:
funcs.append(logging)
if requires:
funcs.append(require(requires))
if ensures:
funcs.append(ensure(ensures))
if use_validate:
funcs.append(validate)
# likewise for spam and eggs
if not funcs:
# Identity function returns whatever it is given.
return lambda arg: arg
else:
f = funcs[0]
for g in funcs[1:]:
f = compose(g)
return f
all_validation = helper(True, int, str, True, True, True)
x = all_validation(999)
--
Steve
More information about the Python-ideas
mailing list