You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

传入相等参数初始化的Python Frame类实例为何不相等?

问题分析与解决方法

问题原因

1. 默认__eq__方法的身份判断逻辑

Python自定义类的默认__eq__方法仅判断对象身份(即is比较),只有当两个变量指向同一个实例时才返回True。哪怕两个实例初始化参数一致、业务逻辑等价,只要是不同的实例,默认==比较就会返回False。

2. 传入的Playwright Frame实例被污染

从测试输出frame0 == frame1为True可知,这两个是Playwright的同一个Frame实例。在初始化new_frame0时,代码直接修改了传入的frame0的方法(如frame.query_selector = self.query_selector),将其替换为当前自定义Frame实例的方法。当创建new_frame1时,传入的frame1(即同一个Frame实例)的方法已经被new_frame0篡改,导致new_frame1中保存的_origin_xxx属性是new_frame0的绑定方法,而new_frame0的_origin_xxx是原始Playwright Frame的方法——这直接造成两个实例的内部状态(__dict__)完全不一致,进一步导致==比较失败。

解决方法

1. 重写__eq__定义业务相等逻辑

根据实际业务需求,自定义两个Frame实例的相等判断规则(比如基于内部封装的_frame和_page是否相等),同时重写__hash__保证哈希一致性:

class Frame:
    # 保留原有__init__及其他方法
    
    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Frame):
            return False
        # 以封装的原始frame和page相等作为实例相等的依据
        return self._frame == other._frame and self._page == other._page
    
    def __hash__(self) -> int:
        # 基于相等判断属性生成哈希值
        return hash((self._frame, self._page))

2. 采用包装器模式,避免修改原Frame实例

当前代码直接修改传入的Playwright Frame实例方法,会污染原对象并引发连锁问题。建议改为封装原方法调用,不修改原对象:

class Frame:
    def __init__(self, frame: PlaywrightFrame, page: Page) -> None:
        super().__init__(frame)
        self._impl_obj = frame._impl_obj
        self._page = page
        self._frame = frame
        self._parent_frame = frame.parent_frame
        # 无需保存_origin_xxx或替换原frame的方法
    
    def query_selector(self, selector: str):
        # 插入自定义逻辑
        # ...
        # 调用原frame的方法
        return self._frame.query_selector(selector)
    
    # 其他方法同理,直接封装原frame的调用,不修改原对象

如果需要拦截原方法添加逻辑,优先使用装饰器或继承Playwright的Frame类(需确认Playwright类允许继承扩展),避免直接修改实例方法。

3. 确保传入未被修改的原始实例(不推荐)

如果必须保留修改原Frame实例的逻辑,创建多个自定义Frame实例时必须传入原始未被修改的Playwright Frame实例。但该方式风险极高,容易出现对象被意外篡改的情况,仅作为临时 workaround 使用。

内容的提问来源于stack exchange,提问作者cfvWEW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:35:20