[Python-Dev] Re: PEP 318: Decorators last before colon (original) (raw)
Robert Brewer fumanchu at amor.org
Wed Apr 7 01:50:00 EDT 2004
- Previous message: [Python-Dev] More imformative iterator representations
- Next message: [Python-Dev] Expert floats
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
[Guido van Rossum]
> ...while far from perfect, in > terms of readability setting function attributes in a decorator is so > much better than setting them after the function has been defined, > that I believe we have no choice but to provide it.
[Me]
The more I read statements like this, the more I think of replacing:
def foo(arg1, arg2): pass foo = classmethod(foo) foo.attrA = 3 ...with code like: foo = classmethod() foo.attrA = 3 def foo(arg1, arg2): pass Why would such additional features not be standard attributes of function objects? 8 All in all, I'd prefer that function decorators and attributes use simple, known techniques like assignment and callables (as shown above), than become monolithic, crystallized all-in-one statements like: def foo(arg1 as str, arg2 as int) returns str [classmethod] {attrA: 3}: I understand the desire to keep all those bits near each other on the page, but stronger is my desire to make them independent statements. If we could bind a "blank" function object and supply its actual codeblock in a later statement, the rest falls magically into place, IMO.
I sat down and banged out a metaclass solution, just to see if I could get the syntax I wanted in the example Shoe class, and to see what might be required behind the scenes. I put Shoe and all the decorator junk in one module to make the syntax look as clean as if Decorable, etc. were builtins.
Basically, Decorable (the metaclass) looks at all attributes of the Shoe class; if there's an attribute "x" and an attribute "x_suite", then Shoe.x gets rebound as x(x_suite). The example provides classmethod and arbitrary function attributes. There are ways to clean it up, of course; this was a quick and dirty proof-of-concept. Rather than playing with "_suite", it should probably either reuse the same name "x" or use a token other than def. I also arbitrarily chose to allow a tuple or list for the decorator (but didn't demonstrate it).
----decorate.py----
import new
class Decorable(type): def init(cls, name, bases, dct): type.init(cls, name, bases, dct) for attr in dct: if attr + "_suite" in dct: # Wrap the attr_suite in the attr decorator. inner_func = getattr(cls, attr + "_suite") decorator = getattr(cls, attr) if isinstance(decorator, (tuple, list)): wrapped_func = inner_func for item in decorator: wrapped_func = item.decorate(wrapped_func) else: wrapped_func = decorator.decorate(inner_func) setattr(cls, attr, wrapped_func)
# [Optional] Unbind the inner function from the class.
delattr(cls, attr + "_suite")
class Decorator(object): def init(self): self.attributes = {}
def __setattr__(self, key, value):
if key == 'attributes':
self.__dict__['attributes'] = value
else:
self.__dict__['attributes'][key] = value
def decorate(self, function):
for key, value in self.attributes.iteritems():
function.__setattr__(key, value)
return function
class clsmethod(Decorator): def decorate(self, function): newfunc = new.instancemethod(function, function.im_class(), function.im_class()) return super(clsmethod, self).decorate(newfunc)
class Shoe(object): metaclass = Decorable
sized_shoe = clsmethod()
sized_shoe.author = "Robert E Brewer"
def sized_shoe_suite(cls, size):
"""Make a new Shoe with a 'size' attribute."""
newShoe = Shoe()
newShoe.size = size
return newShoe
----end decorate.py----
import decorate dir(decorate.Shoe) ['class', 'delattr', 'dict', 'doc', 'getattribute', 'hash', 'init', 'metaclass', 'module', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'str', 'weakref', 'sized_shoe']
decorate.Shoe.sizedshoe.author 'Robert E Brewer'
s = decorate.Shoe.sizedshoe(3) s <decorate.Shoe object at 0x0115CAD0> s.size 3
Robert Brewer MIS Amor Ministries fumanchu at amor.org
- Previous message: [Python-Dev] More imformative iterator representations
- Next message: [Python-Dev] Expert floats
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]