I have a code which get list of all functions in FooBar
and a regular expression the function supports on its parameter message:
functionList = []
def notify(RegExpression):
def _notify(function):
functionList.append((RegExpression, function))
return function
return _notify
class FooBar:
@notify(".*")
def everything(self, message):
pass
@notify("(\w+):.*")
def reply(self, message):
pass
for foo in functionList:
print("%s => %s" % foo)
I would like to do something like that but put the list of functions and their parameters into class as a class variable. It would prevent problems when more classes like FooBar
exist. Each class should have its own list.
def notify(RegExpression):
# ???
class FooBar:
functionList = []
@notify(".*")
def everything(self, message):
pass
@notify("(\w+):.*")
def reply(self, message):
pass
for foo in FooBar.functionList:
print("%s => %s" % foo)
What put into notify()
?
Doing this directly with a function decorator is impossible, since you would need to access the class which is currently being defined, and this class does not exist yet. One solution would be to make the decorator just store the regex as an attribute of the method and have functionality collecting these methods on a base class:
def notify(regex):
def decorate(func):
func.regex = regex
return func
return decorate
class Baz(object):
@property
def function_list(self):
for attr in dir(self):
obj = getattr(self, attr)
if callable(obj) and hasattr(obj, "regex"):
yield obj
class FooBar(Baz):
@notify(".*")
def everything(self, message):
pass
@notify("(\w+):.*")
def reply(self, message):
pass
for foo in FooBar().function_list:
print("%s => %s" % (foo.regex, foo))
When notify
is called the class Foobar
does not even exist yet. Therefore, you can't do with just the decorator.
What you can do is mark the functions with a decorator and collect them after the class has been defined. You can do it with a metaclass or with a class decorator like this:
import inspect
def notify(regex):
def mark( func ):
func.regex = regex
return func
return mark
def collect( cls ):
cls.functionList=[]
for name, func in inspect.getmembers(cls, inspect.ismethod):
if hasattr(func, 'regex'):
cls.functionList.append(func)
return cls
@collect
class FooBar(object):
@notify(".*")
def everything(self, message):
pass
@notify("(\w+):.*")
def reply(self, message):
pass
for foo in FooBar.functionList:
print("%s => %s" % (foo.regex, foo))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With