Python 将默认修饰符应用于类上的所有方法,并有选择地排除它们
我有一个包含大量方法的类,其中大多数方法要求首先运行一个方法来填充类中的列表。但是,我也希望使用延迟加载,这样我就可以在不使用初始加载的情况下创建实例,直到调用需要重载的方法为止。因此,我想创建一个类,其中假设所有方法都需要运行给定的方法,除非有选择地排除该方法。以下是我的伪代码:Python 将默认修饰符应用于类上的所有方法,并有选择地排除它们,python,python-2.7,python-decorators,Python,Python 2.7,Python Decorators,我有一个包含大量方法的类,其中大多数方法要求首先运行一个方法来填充类中的列表。但是,我也希望使用延迟加载,这样我就可以在不使用初始加载的情况下创建实例,直到调用需要重载的方法为止。因此,我想创建一个类,其中假设所有方法都需要运行给定的方法,除非有选择地排除该方法。以下是我的伪代码: @all_methods_run_load class myClass things = [] params = [] @dont_run_load def __init__(sel
@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]
希望这是有道理的。我对装潢师自己还很陌生,还记得他们,所以我担心答案可能会让我大吃一惊,然而我突然想到了这个问题,我忍不住进一步调查:)我对你想要实现的目标有点困惑。如果您想进行延迟加载,为什么不使用需要对仅第一次计算的属性进行数据调用的函数呢
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装饰器,这样他们就不必自己动手了 虽然艾丹·凯恩(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它们(),就可以装饰类
就这样
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]
还可以将所有其他getter转换为属性。哦,是的,为什么我没有想到这一点@邓肯:这种转换会带来什么好处?@DanH,在这种情况下,它只会让使用它的代码更干净一些;您可以使用
instance.things
或instance.last\u thing
而不是instance.get\u things()
和instance.get\u last\u thing()
这样每次访问属性时就少了6个字符。一般来说,如果你直接访问属性,那么代码会更快,也会更短,然后你就可以在这种情况下使用属性,在这种情况下,你不需要重写使用属性的代码。我同意邓肯的建议。实际上,您不需要在其中使用其他方法。人们可以像阅读和理解obj.things[-1]一样快速地阅读和理解obj.last_things——然而,有些东西可能是一种财产。非常酷,谢谢,但我同意你的观点,艾丹·凯恩的观点可能是最好的途径。很高兴阅读您的解决方案:)
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]