lxml HtmlElement 属性的结构模式匹配

问题描述 投票:0回答:1

我想使用 PEP 634 – 结构模式匹配 来匹配具有特定属性的

HtmlElement
。这些属性可通过
.attrib
属性访问,该属性返回
_Attrib
类的实例,IIUC 它具有使其成为
collections.abc.Mapping
的所有方法。

政治公众人物这样说:

要使映射模式成功,主题必须是映射,其中映射被定义为其类是以下之一:

  • 继承自
    collections.abc.Mapping
  • 的类
  • 已注册为
    collections.abc.Mapping
  • 的 Python 类
  • ...

这就是我想要做的,但它不会打印

href

from collections.abc import Mapping
from lxml.html import HtmlElement, fromstring
el = fromstring('<a href="https://stackoverflow.com/">StackOverflow</a>')
Mapping.register(type(el.attrib))  # lxml.etree._Attrib
assert(isinstance(el.attrib, Mapping))  # It's True even before registering _Attrib.

match el:
    case HtmlElement(tag='a', attrib={'href': href}):
        print(href)

这匹配并打印

attrib

match el:
    case HtmlElement(tag='a', attrib=Mapping() as attrib):
        print(attrib)

这与预期不匹配:

match el:
    case HtmlElement(tag='a', attrib=list() as attrib):
        print(attrib)

我也尝试过这个,它有效:

class Upperer:
    def __getitem__(self, key): return key.upper()
    def __len__(self): return 1
    def get(self, key, default): return self[key]
Mapping.register(Upperer)  # It doesn't work without this line.
match Upperer():
    case {'href': href}:
        print(href)  # Prints "HREF"

我知道使用 XPath/CSS 选择器会更容易,但此时我只想知道

_Attrib
类和我的代码有什么问题。

另外,我不想解压元素并将

_Attrib
实例转换为 dict,如下所示:

match el.tag, dict(el.attrib):
    case 'a', {'href': href}:
        print(href)

或使用防护装置:

match el:
    case HtmlElement(tag='a', attrib=attrs) if 'href' in attrs:
        print(attrs['href'])

它可以工作,但看起来不正确。我想找到一个解决方案,以便原来的

case HtmlElement(tag='a', attrib={'href': href})
能够工作。或者非常接近它的东西。

我使用的Python版本是3.11.4。

python python-3.x lxml python-3.11 structural-pattern-matching
1个回答
0
投票

Python 使用

match case
来比较两个对象是否相等似乎存在问题,因为使用 match case 语句的模式匹配通常用于匹配不同的值,而不是比较对象是否相等。在Python中,
==
运算符经常用于比较对象是否相等。如果要比较两个对象是否相等,应使用
==
而不是
match case

写一个类进行比较:

class Element:
    def __init__(self,data : HtmlElement= None,**kwargs):
        if not kwargs:
            temp={'tag': data.tag, 'text': data.text,'tail': data.tail,'attrib': data.attrib}
            self.__dict__ = {i:temp[i] for i in temp if temp[i]}
            return
        self.__dict__ =kwargs
    def __eq__(self, other):
        return self.__dict__ == other.__dict__

使用if语句判断是否相等

if Element(el) == Element(tag='a',text= 'StackOverflow', attrib={'href': 'https://stackoverflow.com/'}):
    print('equal')
© www.soinside.com 2019 - 2024. All rights reserved.