具有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许可证授权。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
库伯内特斯的爪哇普罗米修斯jmx_出口商   在Java中使用通配符(仅限最后一个索引)验证ip地址的正则表达式   对象类的java equals()方法   java spring boot(webflux)rest控制器获取远程IP地址   crc Java在同一字符串上返回不同的CRC32结果   包含数字和字母的java排序数组列表   java更改一个类变量的值,然后在另一个类中调用它   java Do While循环终止,不执行scanner函数   作为cron作业运行的linux Java控制台应用程序存在相对路径问题   安卓如何使用HttpUrlConnect使用java查询Github graphql API   视频在java中如何将字节缓冲区写入一半?   安卓如何通过java将RadioButton添加到RadioGroup?   具有TARGET_类代理模式的java请求_作用域bean在注入到其他组件(如@Service或@Repository)中时只能看到空参数