我有一个包含大量方法的类,其中大部分都需要先运行一个方法来填充类中的列表。但是我也想使用延迟加载,这样我就可以在没有初始加载的情况下创建实例,直到调用需要大量加载的方法。因此,我想创建一个类,其中假定所有方法都需要运行给定方法,除非选择性地排除该方法。这是我的伪代码:
@all_methods_run_load
class myClass
things = []
params = []
@dont_run_load
def __init__(self, params):
self.params = params
@dont_run_load
def load(self):
self.things = do_a_ton_stuff()
def get_things():
return self.things
def get_some_things():
return apply_a_filter(self.things)
def get_first_thing():
return self.things[0]
def get_last_thing():
return self.things[-1]
希望这是有道理的。我对装饰者本身很新,并且仍然记住它们,所以我担心答案可能会让我大吃一惊,不过这个想法在我脑海中浮现,我不禁进一步调查:)
答案 0 :(得分:5)
虽然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
对其进行装饰(found here)。
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]
答案 1 :(得分:4)
我对你想要实现的目标感到困惑。如果你想延迟加载,为什么你没有需要在第一次只评估的属性上调用数据的函数?
class myClass
_things = []
params = []
def __init__(self, params):
self.params = params
@property
def things(self):
if not self._things:
self._things = do_a_ton_stuff()
return self._things
def get_things():
return self.things
def get_some_things():
return apply_a_filter(self.things)
def get_first_thing():
return self.things[0]
def get_last_thing():
return self.things[-1]
有些人为这种模式制作一个@cachedproperty装饰器 - 所以他们不必自己做self._things位。 http://code.activestate.com/recipes/576563-cached-property/