我有一个代码,它获取FooBar
中所有函数的列表以及函数在其参数消息上支持的正则表达式:
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)
我想做类似的事情,但将函数及其参数列表作为类变量放入类中。当存在更多类FooBar
时,它可以防止出现问题。每个班级都应该有自己的清单。
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)
放入notify()
的内容是什么?
答案 0 :(得分:4)
直接使用函数装饰器执行此操作是不可能的,因为您需要访问当前正在定义的类,并且此类尚不存在。一种解决方案是使装饰器只将正则表达式存储为方法的属性,并具有在基类上收集这些方法的功能:
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))
答案 1 :(得分:3)
当调用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))
答案 2 :(得分: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 :(得分:0)
此处为Python 3更新了Jochen Ritzel's答案。
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))