[Python-ideas] Python Decorator Improvement Idea
Brian Allen Vanderburg II
brianvanderburg2 at aim.com
Fri Jun 15 23:54:42 EDT 2018
Just a small idea that could possibly be useful for python decorators.
An idea I had is that it could be possible for a decorator function to
declare a parameter which, when the function is called as a decorator,
the runtime can fill in various information in the parameters for the
decorator to use. Some of the information would be available in all
contexts, while other information may only be available in certain
contexts.The parameter's value cannot be explicitly specified, defaults
to Null except when called as a decorator, and can only be specified
once in the function's parameter list.
Called as a decorator implies:
@decorator
def decorated():
pass
These are not called as a decorator. The first item's return value
would be called as a decorator, thus if it has a decorator parameter, it
would be used.
@decorator(...)
def decorated():
pass
def decorated():
pass
decorated = decorator(decorated)
Any declared callable (function, class instance with __call__, etc) can
have an explicitly declared parameter called a decorator information
parameter. The syntax could be as follows. "info" is just a name I've
chosen and could be any legal name.
def decorator(..., @info):
pass
def wrapper(..., @info):
def decorator(obj, @info):
...
return obj
if info:
called directly as decorator, do something
else:
return decorator
Rules:
1. It is not possible for the parameter's value to be directly
specified. You can't call fn(info=...)
2. The parameters value is Null except in the cases where it is invoked
(the callable called a a decorator). If used in a partial, the
decorator parameter would be Null. etc.
Information that could be contained in the parameters for all contexts:
Variable name
Module object declared in
Module globals (useful for @export/@public style decorators)
Etc
Using the decorator in a class context, pass the class object. While
the class object hasn't been fully created yet, this could allow
accessing attributes of the class (like a registry or such)
def decorator(fn, @info):
if hasattr(info, "class_obj"):
registry = info.class_obj.__dict__.setdefault("_registry", [])
registry.append(fn)
return fn
class MyClass(Base):
# Add "method" to the MyClass._registry list
@decorator
def method(...):
pass
def call_all(cls):
for method in self._registry:
method(self)
This could also make it possible to use decorators on assignments.
Information could be passed to the decorator by the runtime:
script_vars = {}
def expose(obj, @info):
script_vars[info.name] = obj
return obj
def load(filename):
# load script and compile
exec(code, script_vars)
@expose
def script_function(...):
pass
# This will call the decorator passing in 200 as the object, as well as info.name as the variable being assigned.
@expose
SCRIPT_CONSTANT = 200
# If stacked, only the first would be used as info.name, in this case SCRIPT_CONSTANT2
@expose
SCRIPT_CONSTANT2 = A_VAR = 300
def default(obj, @info):
if info.name in info.ctx.vars:
return info.ctx.vars[info.name]
if info.name in info.globals:
return info.globals[info.name]
return obj
@default
X = 12
@default
X = 34
print(X) # print 12 since during the second call, X existed and it's value was returned instead of 34, and was assigned to X
The two potential benefits I see from this are:
1. The runtime can pass certain information to the decorator, some
information in all contexts, and some information in specific contexts
such as when decorating a class member, decorating a function defined
within another function, etc
2. It would be possible to decorate values directly, as the runtime can
pass relevant information such as the variables name
This was just an idea I had that may have some use.
Thanks,
Brian Vanderburg II
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180615/2048ba77/attachment-0001.sig>
More information about the Python-ideas
mailing list