[英]Python decorator which set class variable
我有一个代码,它获取FooBar
中所有函数的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()
?
直接使用函数装饰器执行此操作是不可能的,因为您需要访问当前正在定义的类,并且此类尚不存在。 一种解决方案是使装饰器只将正则表达式存储为方法的属性,并具有在基类上收集这些方法的功能:
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))
当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))
无论如何我写了它,所以我可能只是发布了第三个选项。 它使用元类来收集函数:
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))
我想在一个线程中将所有选项放在一起很好。
这是Jochen Ritzel为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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.