遵循PEP-562:
https://www.python.org/dev/peps/pep-0562/
现在可以为模块定义属性。不幸的是,某些内置组件尚未适应此新功能。在以下代码中:
@property
def lazyFn():
return 3
v = lazyFn
v
理想情况下,v
应该具有属性值3。不幸的是,当前@property
的实现只能产生以下结果:
<property at 0x7f3e703eae30>
如何解决它的预期行为?或者,在哪里可以找到具有适当实现方式的替代产品?
答案 0 :(得分:0)
我不敢相信答案是多么容易(以及它不是内置的或固定的),不需要反射,模块, setattr 或PEP -562。我需要定义一个装饰器:
def lazy(fn):
if fn.__name__ == fn.__qualname__:
# not a property
result = fn()
return result
else:
return LazyProperty(fn)
# the following are from PyPI lazy library
class LazyProperty(object):
"""lazy descriptor
Used as a decorator to create lazy attributes. Lazy attributes
are evaluated on first use.
"""
def __init__(self, func):
self.__func = func
functools.wraps(self.__func)(self)
def __get__(self, inst, inst_cls):
if inst is None:
return self
if not hasattr(inst, '__dict__'):
raise AttributeError("'%s' object has no attribute '__dict__'" % (inst_cls.__name__,))
name = self.__name__
if name.startswith('__') and not name.endswith('__'):
name = '_%s%s' % (inst_cls.__name__, name)
value = self.__func(inst)
inst.__dict__[name] = value
return value
进行测试:
nn = 0
@lazy
def fn1():
global nn
nn = nn + 1
return nn
@dataclass
class HasFn2(object):
nn = 0
@lazy
def fn2(self):
self.nn = self.nn + 1
return self.nn
def test_lazy():
vs1 = [fn1 for i in range(0, 5)]
assert vs1 == [1, 1, 1, 1, 1]
c = HasFn2()
vs2 = [c.fn2 for i in range(0, 5)]
assert (vs2 == [1, 1, 1, 1, 1])
如果此实现有缺陷,请纠正我