Python decoder that sets the class variable

I have code that gets a list of all the functions in FooBarand a regular expression that the function supports in 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 similar, but list the list of functions and their parameters in the class as a class variable. This will prevent problems when more classes exist, such as FooBar. Each class must 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 is placed in notify()?

+3
source share
4 answers

, , , . , :

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))
+4

notify , Foobar . .

, . , :

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))
+3

, . :

def notify(regex):
    def mark( func ):
        func.regex = regex
        return func
    return mark

class RegexBase(object):
    class __metaclass__(type):
        """ creates a list of functions with a `regex` attribute 
            and stores it on the class as `functionList`
        """
        def __new__(cls, name, bases, attr):
            fl = []
            for obj in attr.itervalues():
                    if hasattr(obj, 'regex'):
                        fl.append(obj)
            attr['functionList'] = fl
            return type.__new__(cls, name, bases, attr)


class FooBar(RegexBase):

    @notify(".*")
    def everything(self, message):
        pass

    @notify("(\w+):.*")
    def reply(self, message):
        pass

for foo in FooBar.functionList:
     print("%s => %s" % (foo.regex, foo))

, .

+3

Python 3.

def notify(regex):
    def mark( func ):
        func.regex = regex
        return func
    return mark


class Meta(type):
    """ creates a list of functions with a `regex` attribute 
        and stores it on the class as `functionList`
    """
    def __new__(cls, name, bases, attr):
        fl = []
        for obj in attr.values():
                if hasattr(obj, 'regex'):
                    fl.append(obj)
        attr['functionList'] = fl
        return type.__new__(cls, name, bases, attr)

class RegexBase(object, metaclass=Meta):
  pass


class FooBar(RegexBase):
    @notify(".*")
    def everything(self, message):
        pass

    @notify("(\w+):.*")
    def reply(self, message):
        pass


for foo in FooBar.functionList:
     print("%s => %s" % (foo.regex, foo))
0

All Articles