尽管 Aidan Kane 可能是正确的,您不应该以这种方式做事,但您所说的问题的解决方案可以这样表述:
这是可以装饰方法的函数。
import functools
def run_load(function):
"""Make a function run the class' load method before running."""
@functools.wraps(function)
def inner(self, *args, **kwargs):
self.load()
return function(self, *args, **kwargs)
return inner
函数是可变的,所以你可以标记它们。
def without_load(function):
"""Tag a method so that it shouldn't be decorated to call self.load."""
function.without_load = True
return function
您可以通过浏览其成员并setattr
-ing 来装饰该类(在此处找到)。
import inspect
def decorate_all_with(decorator, predicate=None):
"""Apply a decorator to all methods that satisfy a predicate, if given."""
if predicate is None:
predicate = lambda _: True
def decorate_all(cls):
for name, method in inspect.getmembers(cls, inspect.isfunction):
if predicate(method):
setattr(cls, name, decorator(method))
return cls
return decorate_all
就是这样!
def should_be_loaded(function):
try:
return not bool(function.without_load)
except AttributeError:
return True
@decorate_all_with(run_load, should_be_loaded)
class MyClass:
things = []
params = []
@without_load
def __init__(self, params):
self.params = params
@without_load
def load(self):
self.things = do_a_ton_stuff()
def get_things(self):
return self.things
def get_some_things(self):
return apply_a_filter(self.things)
def get_first_thing(self):
return self.things[0]
def get_last_thing(self):
return self.things[-1]