具有GET/SET/DEL/init /依赖/缓存映射功能的灵活缓存属性。
promised的Python项目详细描述
承诺
承诺
一种灵活的延迟评估缓存属性,具有GET/SET/DEL/init能力,用于跨属性关系。
链接
一种依赖管理承诺,当调用其任何链接器方法时,它将刷新依赖属性。(通常是deleter和setter)
成员
为@promise decorator设计的一个缓存映射扩展类,类似于显式(im-)可变内存。
获取
输入终端/命令行:
pip install promised
这就变成了python:
from promised import promise, linked, Member # linked are dependent promises, Member is for cached-mapping extension.
目的
此项目当前用作管理属性依赖项的简单方法,例如:
class _TestLine(object):
@linked
def length(self):
self._length = 2.0
class _TestSquare(object):
@linked(chain=True)
def side(self):
self._side = _TestLine()
@side.chain("length")
def width(self):
self._width = self.side.length
@side.chain("length")
def height(self):
self._height = self.side.length
@width.linked
@height.linked
def area(self):
self._area = self.width * self.height
class _TestBox(object):
"""This is a test class for linked promises. I don't know what more you're expecting."""
@linked(chain=True)
def side(self):
self._side = _TestLine()
@linked(chain=True)
def base(self):
self._base = _TestSquare()
@side.chain("length")
@base.chain("area")
def volume(self):
self._volume = self.base.area * self.side.length
def _test_area():
box = _TestBox()
assert box.volume == 8.0, "Box volume is 2.0 * 2.0 * 2.0 as Line's default length is 2.0"
box.side.length = 4
assert box.volume == 16.0, "Box volume has updated due to change in side's length."
box.base.side.length = 10
assert box.volume == 400.0, "Box volume has update due to change in base's side length."
line = _TestLine()
line.length = 0.5
box.side = line
assert box.volume == 50.0, "Box volume has updated due to changed side."
这是因为我发现自己经常这样做:
@property
def property_public_name(self):
'''Why am I typing the same lines with tiny changes in every project all the time?'''
try:
return self._property_public_name_with_leading_underscore
except AttributeError:
self._property_public_name_with_leading_underscore = self._method_to_calculate_property()
return self._property_public_name_with_leading_underscore
用法
现在,看起来是这样:
@promise
def property_public_name(self):
'''Now this is promising!'''
self._property_public_name_with_leading_underscore = self._method_to_calculate_property()
仍然可以这样访问:
property_value = self.property_public_name
您仍然可以这样做:
@property_public_name.setter
@property_public_name.deleter
@property_public_name.getter
通过将私有变量(最初在promise's keeper中设置的变量)的名称传递给promise's init,您可以用同一个keeper对一组promise进行分组:
def _set_associated_properties(self):
associated_map_one = {}
associated_map_two = {}
for thing in self.iterable:
associated_map_one = thing.map_one(associated_map_one)
associated_map_two = thing.map_two(associated_map_two)
self._property_one_public_name = associated_map_one
self._property_two_public_name = associated_map_two
property_one_public_name = promised(_set_associated_properties, name="_property_one_public_name")
property_two_public_name = promised(_set_associated_properties, name="_property_two_public_name")
您可以使用@linked属性(其功能类似于承诺的属性)将依赖属性链接在一起,并使用@linked\u property.linked decorator修饰任何依赖属性的getter/setter/deleter/keeper方法,每个依赖属性一次:
@linked
def heroes(self):
self._heroes = None
@heroes.linked
@promise
def future_of_townsville(self):
self._future_of_townsville = "Bleak" if not self.heroes else "FAN-tastic!"
@future_of_townsville.deleter
def future_of_townsville(self):
del self._future_of_townsville
@heroes.linker
@heroes.setter
def heroes(self, value):
self._heroes = value
def test_town_turnaround(self):
""Setting self.heroes to a different value should reset its dependent properties."""
assert not hasattr(self, "_heroes"), "promise should not have already been kept!"
assert not hasattr(self, "_future_of_townsville"), "promise should not have already been kept!"
assert self.future_of_townsville == "Bleak", "There should be no heroes - yet!"
assert self.heroes is None, "There should be no heroes - yet!"
self.heroes = "POWER-PUFF GIRLS"
assert not hasattr(self, "_future_of_townsville"), "The future of townsville is dependent on heroes, so it should be deleted once changed!"
assert self.future_of_townsville == "FAN-tastic!", "The future of townsville should be looking up!"
@当调用其@linker方法时,链接属性将自动刷新依赖属性。为了便于使用,因为这至少需要在依赖属性中使用一个删除方法,@linked properties是@promise properties,带有默认的deleters和setters,它们也是默认的链接器。使用链接属性的默认值,前面的示例将变成:
@linked
def heroes(self):
self._heroes = None
@heroes.linked
def future_of_townsville(self):
self._future_of_townsville = "Bleak" if not self.heroes else "FAN-tastic!"
def test_town_turnaround(self):
""Setting self.heroes to a different value should reset its dependent properties."""
...
有关删除默认删除器/设置器/链接器的详细信息,请参阅boiler_property.py中的文档:
@linked(linkers=("keeper",)
def property_which_refreshes_dependent_properties_when_keeper_method_used(self):
"""This would typically reset all dependent properties after this property is accessed for the first time and first access post-refresh/deletion."""
self._property_which_refreshes_dependent_properties_when_keeper_method_used = "RESET"
@linked(deleter=False, setter=False, linkers=("getter",)
def read_only_property_which_refreshes_dependent_properties_on_every_access(self):
"""Not advised for properties which access this property once reset (as the typical dependent property would.)"""
self._read_only_property_which_refreshes_dependent_properties_on_every_access = None
可以使用@linked properties的chain=true init参数指定类间依赖源。
@linked(chain=True)
def side(self):
self._side = _TestLine()
@linked(chain=True)
def base(self):
self._base = _TestSquare()
并使用@dependency_source.chain(“dependent_property_name”)模拟@property_name.linked的类内行为。
@side.chain("length")
@base.chain("area")
def volume(self):
self._volume = self.base.area * self.side.length
您可以使用member类创建一个缓存的promised属性,该属性随输入而变化(例如memoization,但显式可变/不可变):
def _children_of_parent_with_attribute_value(self, parent, child_attribute_value):
return self.parent_children_map[parent] & self.attribute_value_to_set_of_objects_map[child_attribute_value]
@promise
def adult_children(self):
self._adult_children = Member(self._children_of_parent_with_attribute_value, "The White House")
然后按如下方式访问:
donnie = countries.adult_children["America"]
未来
这些只是模式中我认为对显式缓存属性有用的第一步,我对构建对关联和依赖属性的更自动化支持非常感兴趣-请随意分享任何建议。
版权所有
安德鲁·M·霍根承诺的模块。(承诺©2019霍根咨询集团)
许可证
根据apache许可证授权。