Attributebase对象匹配

matchable的Python项目详细描述


TestsCodecovPyPIPyPI pyversions

相配的

Python中基于属性的对象匹配

安装

PyPI

pip install matchable

使用

matchable是围绕两个对象matchSpec构建的:

  • match用于创建模式并将它们链接到用户指定的值。在
  • Spec包含一个模式列表,这些模式可以与任意对象匹配,以便组合它们的链接值。在

例如:

^{pr2}$

{{{cd7}与一个大于cd6}的属性相匹配。在

match(dict)['key'] == 0

此模式将所有dict(或其子类)与一个项'key'匹配,该项比较等于0。在

此类模式可用于通过Spec类创建规格:

spec = Spec.from_patterns({
    match(object).attr > 0: 'foo',
    match(dict)['key'] == 0: 'bar',
})

等级库可用于将其他对象与其图案相匹配,并组合相应的值:

>>> spec.match({'key': 0})
'bar'
>>> class Test:
...     attr = 1
... 
>>> spec.match(Test())
'foo'

如果没有与给定对象匹配的条件,则引发异常:

>>> spec.match({'key': 5})
[...]
matchable.exceptions.NoMatchError: No matching conditions found for object {'key': 5}

如果多个条件与给定对象匹配,则将组合它们的相应值(参见下面的段落 对于“合并”在不同情况下的含义):

>>> class Test(dict):
...     attr = 1
... 
>>> spec.match(Test(key=0))
'bar'

这里,对于字符串,“组合”意味着只需选择最后看到的值 (有关自定义此行为的信息,请参阅下一节)。 但是,对于字典,标准行为是更新其内容:

>>> spec = Spec.from_patterns({
...     match(object).attr > 0: dict(x='foo'),
...     match(dict)['key'] == 0: dict(y='bar'),
... })
>>> spec.match(Test(key=0))
{'x': 'foo', 'y': 'bar'}

这对于将多个部分配置合并为一个配置非常有用。在

注册自定义组合

上一节的示例显示,对于string,“last seen wins”策略 用于组合两个值。另一种可能是连接值。 我们可以通过以下方式实现:

from matchable.spec import Wrapper, WRAPPER_TYPES

class Concatenate(Wrapper):
    def __or__(self, other):
        return Concatenate(self.obj + other.obj)

WRAPPER_TYPES[str] = Concatenate

基本上,我们需要为WRAPPER_TYPES中的相应类型提供一个自定义的Wrapper类。 由于各个值是通过lhs | rhs组合的,所以这个包装器需要做的就是实现 __or__协议,并在那里执行组合逻辑。这里self.obj访问包装好的对象 (本例中为字符串)。需要注意的是,在创建之前,包装器需要注册 spec因为一旦创建了spec,它就不会更改其值的包装类型。在

现在我们可以创建等级库并匹配一些对象:

spec = Spec.from_patterns({
    match(dict)['x'] > 0: 'foo',
    match(dict)['x'] > 1: 'bar',
})

>>> spec.match({'x': 1})
'foo'
>>> spec.match({'x': 2})
'foobar'

模式、匹配和类层次结构

模式可以引用某些类型的对象的属性(match(obj).x)或项(match(obj)['x']) 或者直接指向类型(或者match(tp)或者只是tp)。在

在匹配过程中,如果应用了多个模式,则基于属性的模式优先于基于类型的模式。 事实上,所有匹配模式的列表都是按照基于类型的模式放在左边的方式进行排序的, 按照匹配对象的反转顺序MRO, 然后是基于属性的模式,在规范创建期间按其外观顺序排列。 然后从左到右更新相应的值,其中r.h.s.值更新l.h.s.值(即lhs | rhs)。 例如,对于一个字符串列表,由于它们更新为“最后看到的胜利”,最右边的值将是结果。 对于一组集合的等价物是s1 | s2 | s3,即它们建立一个联合。在

Spec.match方法还支持一个typewise关键字参数,该参数可用于更改模式的排序 这样,基于属性的模式只优先于其关联的基于类型的模式,否则匹配的 对象的反向MRO是受尊重的。一、 对于typewise=True基于子类型的模式优先于基于属性的模式 一个祖先的模式,而对于typewise=False(默认值),则相反(因为这里基于类型的模式是 一直排到左边)。在

下图显示了类层次结构以及不同匹配风格的优先顺序。在

Diagram

示例

假设一个se应该以某种方式可视化的对象序列。这些对象是:

from dataclasses import dataclass

@dataclass
class Plant:
    height: float

@dataclass
class Flower(Plant):
    n_petals: int

@dataclass
class Tree(Plant):
    pass

plants = [  # some random numbers
    Flower(height=4.0, n_petals=5),
    Flower(height=3.5, n_petals=7),
    Flower(height=6.8, n_petals=4),
    Tree(height=104.6),
    Flower(height=1.8, n_petals=9),
    Tree(height=187.2),
    Tree(height=121.9),
    Flower(height=2.2, n_petals=5),
]

假设我们要将这些植物对象形象化为具有不同样式的矩形来表示它们的属性。 我们可以通过创建一个表示各种矩形配置的规范来实现(注意,如果 规范中有多个匹配项,dict将合并为一个):

config = Spec.from_patterns({
    match(Plant): dict(linestyle='-', linewidth=2, facecolor='none'),
    match(Flower): dict(edgecolor='orange'),
    match(Flower).height < 2.0: dict(hatch='/'),
    match(Flower).n_petals >= 7: dict(facecolor='#ff7f0e33'),
    match(Tree): dict(edgecolor='green'),
    match(Tree).height > 160: dict(linestyle='--'),
})

然后我们可以添加矩形面片,如下所示:

fig, ax = plt.subplots()
for i, plant in enumerate(plants):
    ax.add_patch(Rectangle((i, 0), 0.5, 1, **config.match(plant)))

这给了我们以下的情节:

Example plot

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

推荐PyPI第三方库


热门话题
java Intellij和Eclipse无法找到库工件   java Mapbox Android Symbolayer重置筛选器   java如何在顶部显示特定的recyclerview项?   java如何在Hibernate中使用@Qualifier   我想计算特定文本webdriver java在多个页面上可用的HTML表中的数据   java捕获Spring MVC REST服务抛出的Jersey REST客户端的异常   java Hibernate flush()影响事务   密钥绑定Java密钥绑定   sonarqube java,sonar,圈复杂度   使用3DES在Java中加密,在SQL Oracle中解密   regex正则表达式在regex101上工作。com,但不是prod   JAVAsql。SQLException:ORA00600:内部错误代码,参数:[12811],[93233]   java H2数据库存储在哪里?   java如何避免在使用Jackson时从JSON字符串反序列化空JSON数组元素