Registry of Methods via Decorators
Bruno Desthuilliers
onurb at xiludom.gro
Thu Jun 22 10:36:00 EDT 2006
bayerj wrote:
> I want to make a registry of methods of a class during creation. My
> attempt was this
>
> """ classdecorators.py
>
> Author: Justin Bayer
> Creation Date: 2006-06-22
> Copyright (c) 2006 Chess Pattern Soft,
> All rights reserved. """
>
> class decorated(object):
>
> methods = []
>
> @classmethod
> def collect_methods(cls, method):
> cls.methods.append(method.__name__)
> return method
>
> class dec2(decorated):
>
> @collect_methods
> def first_func(self):
> pass
>
> @collect_methods
> def second_func(self):
> pass
>
>
> def main():
> print dec2.methods
>
> if __name__ == '__main__':
> main()
>
> This does not work and exits with "NameError: ("name 'collect_methods'
> is not defined",)". Which is understandable due to the fact that the
> class dec2 is not complete.
>
> Anyone can give me a hint how to work around this?
If you insist on doing black-magic (else go directly to the end of this
post), here's a way to do it, based on Ian Bicking's __classinit__ recipe
http://blog.ianbicking.org/a-conservative-metaclass.html
(BTW, Ian, many many thanks for this trick - I really love it).
class DeclarativeMeta(type):
def __new__(meta, class_name, bases, new_attrs):
cls = type.__new__(meta, class_name, bases, new_attrs)
cls.__classinit__.im_func(cls, new_attrs)
return cls
class Declarative(object):
__metaclass__ = DeclarativeMeta
def __classinit__(cls, new_attrs): pass
class MethodCollector(Declarative):
def __classinit__(cls, new_attrs):
cls.methods = [name for name, attr in new_attrs.items() \
if callable(attr)]
class dec2(MethodCollector):
def first_func(self):
pass
def second_func(self):
pass
If you want to choose which methods to collect, then it's just a matter
of adding a simple decorator and a test in MethodCollector.__classinit__:
def collect(func):
func._collected = True
return func
class MethodCollector(Declarative):
def __classinit__(cls, new_attrs):
cls.methods = [name for name, attr in new_attrs.items() \
if callable(attr) \
and getattr(attr, '_collected', False)]
class dec2(MethodCollector):
@collect
def first_func(self):
pass
@collect
def second_func(self):
pass
def not_collected(self):
pass
*BUT* is it really useful to go thru all this mess ?
class DeadSimple(object):
@classmethod
def methods(cls):
return [name for name in dir(cls) \
if not name.startswith('__') \
and callable(getattr(cls, name))]
My 2 cents...
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"
More information about the Python-list
mailing list