在 Python 中批量添加属性?
Batch-adding properties in Python?
在我的代码中,我想创建一堆惰性变量,但是,如果查询其中任何一个,则应该调用整个 Load()
函数,这将填充所有底层惰性变量变量一次。
目前我的 class 看起来像这样:
@property
def test1(self):
if (not self.__test1):
self.Load()
return self.__test1
@property
def test2(self):
if (not self.__test2):
self.Load()
return self.__test2
....
因为如果在 30 多个变量上完成这看起来很丑陋,我想知道是否有办法在 Python 中做得更漂亮,也许使用一些智能装饰器?
感谢您的回复
你可以定义一个metaclass来动态创建所有需要延迟加载的属性。此元class 从您自己的 class 中定义的列表 lazy_props
中获取 属性 名称,并在 __new__()
中生成您的 class 中的属性.
代码是这样的:
class LazyMeta(type):
def __new__(cls, clsname, bases, clsdict):
d = dict(clsdict)
props = d.get("lazy_props")
def lazy_load(_attr):
def wrapped_method(self):
variable = "_" + _attr
if not hasattr(self, variable):
self.Load()
return getattr(self, variable)
return wrapped_method
for prop in props:
_method = lazy_load(prop)
_property = property(_method)
d[prop] = _property
return type.__new__(cls, clsname, bases, d)
# Your class uses LazyMeta as metaclass
class LazyClass:
__metaclass__ = LazyMeta
lazy_props = ['test1', 'test2']
def Load(self):
print "Loading ..."
self._test1=123
self._test2=456
现在实例化 LazyClass 的对象时:
>>> l = LazyClass()
>>> l.test1
Loading ...
123
>>> l.test2
456
注意我用_test1, _test2
代替了__test1, __test2
,因为python对以双下划线开头的变量进行了特殊处理,它可以防止getattr()
工作正常。
在我的代码中,我想创建一堆惰性变量,但是,如果查询其中任何一个,则应该调用整个 Load()
函数,这将填充所有底层惰性变量变量一次。
目前我的 class 看起来像这样:
@property
def test1(self):
if (not self.__test1):
self.Load()
return self.__test1
@property
def test2(self):
if (not self.__test2):
self.Load()
return self.__test2
....
因为如果在 30 多个变量上完成这看起来很丑陋,我想知道是否有办法在 Python 中做得更漂亮,也许使用一些智能装饰器?
感谢您的回复
你可以定义一个metaclass来动态创建所有需要延迟加载的属性。此元class 从您自己的 class 中定义的列表 lazy_props
中获取 属性 名称,并在 __new__()
中生成您的 class 中的属性.
代码是这样的:
class LazyMeta(type):
def __new__(cls, clsname, bases, clsdict):
d = dict(clsdict)
props = d.get("lazy_props")
def lazy_load(_attr):
def wrapped_method(self):
variable = "_" + _attr
if not hasattr(self, variable):
self.Load()
return getattr(self, variable)
return wrapped_method
for prop in props:
_method = lazy_load(prop)
_property = property(_method)
d[prop] = _property
return type.__new__(cls, clsname, bases, d)
# Your class uses LazyMeta as metaclass
class LazyClass:
__metaclass__ = LazyMeta
lazy_props = ['test1', 'test2']
def Load(self):
print "Loading ..."
self._test1=123
self._test2=456
现在实例化 LazyClass 的对象时:
>>> l = LazyClass()
>>> l.test1
Loading ...
123
>>> l.test2
456
注意我用_test1, _test2
代替了__test1, __test2
,因为python对以双下划线开头的变量进行了特殊处理,它可以防止getattr()
工作正常。