admin管理员组文章数量:1384317
I'm investigating the pattern whereby you have a method decorator which annotates the method in some way, and then once the class is defined it looks through its methods, finds the annotated methods, and registers or processes them in some way. e.g.
def class_decorator(cls):
for name, method in cls.__dict__.iteritems():
if hasattr(method, "use_class"):
# do something with the method and class
print name, cls
return cls
def method_decorator(view):
# mark the method as something that requires view's class
view.use_class = True
return view
@class_decorator
class ModelA(object):
@method_decorator
def a_method(self):
# do some stuff
pass
(From here: )
I wondered if anyone has a solution to the problem of multiple decorators. For example, this example works fine in isolation, but if I do the following, it will break because the use_class
annotation will be hidden.
def hiding_decorator(fn):
def wrapper(*args, **kwargs):
print("do some logging etc.")
return fn(*args, **kwargs)
return wrapper
@class_decorator
class ModelA(object):
@hiding_decorator
@method_decorator
def a_method(self):
# do some stuff
pass
Does anyone have a reliable and user-friendly way around this problem?
Non-optimal solutions I can think of:
- Dictate that your decorator should be outermost (but what if other decorators also have this requirement?)
- Dictate that it only works with decorators that are transparent proxies for attributes of their inner functions/methods.
- Require other decorators to be aware of the requirements of the tagging decorator (means generic utility decorators become difficult to use).
None of these are particularly attractive.
I'm investigating the pattern whereby you have a method decorator which annotates the method in some way, and then once the class is defined it looks through its methods, finds the annotated methods, and registers or processes them in some way. e.g.
def class_decorator(cls):
for name, method in cls.__dict__.iteritems():
if hasattr(method, "use_class"):
# do something with the method and class
print name, cls
return cls
def method_decorator(view):
# mark the method as something that requires view's class
view.use_class = True
return view
@class_decorator
class ModelA(object):
@method_decorator
def a_method(self):
# do some stuff
pass
(From here: https://stackoverflow/a/2367605/1256529)
I wondered if anyone has a solution to the problem of multiple decorators. For example, this example works fine in isolation, but if I do the following, it will break because the use_class
annotation will be hidden.
def hiding_decorator(fn):
def wrapper(*args, **kwargs):
print("do some logging etc.")
return fn(*args, **kwargs)
return wrapper
@class_decorator
class ModelA(object):
@hiding_decorator
@method_decorator
def a_method(self):
# do some stuff
pass
Does anyone have a reliable and user-friendly way around this problem?
Non-optimal solutions I can think of:
- Dictate that your decorator should be outermost (but what if other decorators also have this requirement?)
- Dictate that it only works with decorators that are transparent proxies for attributes of their inner functions/methods.
- Require other decorators to be aware of the requirements of the tagging decorator (means generic utility decorators become difficult to use).
None of these are particularly attractive.
Share Improve this question asked Mar 18 at 8:21 samfrancessamfrances 3,7673 gold badges28 silver badges48 bronze badges1 Answer
Reset to default 3Since a "tag" is always applied on a function object itself, it is always going to be susceptible to obstruction by an unaware wrapper function.
To achieve a similar usage you can implement the behavior with a registry pattern instead by adding method names to a list with a method decorator so that the class decorator can obtain the final decorated function object with getattr
:
class Registry:
def __init__(self):
self.names = []
def register(self, func):
self.names.append(func.__name__)
return func
def apply(self, cls):
for name in self.names:
print(cls, name)
print(getattr(cls, name))
registry = Registry()
@registry.apply
class ModelA(object):
@hiding_decorator
@registry.register
def a_method(self):
pass
This outputs something like:
<class '__main__.ModelA'> a_method
<function hiding_decorator.<locals>.wrapper at 0x1551795d67a0>
Demo: https://ideone/R43Izy
版权声明:本文标题:python - Method decorators which "tag" method - prevent overwriting by other decorators - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744516185a2610175.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论