python - 无法用 lambda 覆盖 __contains__

标签 python

我想创建一个可以在in语句中使用的类,并将条件传递给__init__中的对象。一个例子:

class Set:
    def __init__(self, contains):
        self.__contains__ = contains  # or setattr; doesn't matter

top = Set(lambda _: True)
bottom = Set(lambda _: False)

问题是 top 中的 3 返回 TypeError: argument of type 'Set' is not iterable,即使 top.__contains__(3) 按预期返回 True

更重要的是,如果我这样修改代码:

class Set:
    def __init__(self, contains):
        self.__contains__ = contains

    def __contains__(self, x):
        return False

top = Set(lambda _: True)

, 3 in top 将返回 False,而 top.__contains__(3) 按预期返回 True ,再次。

这里发生了什么?我使用的是 Python 3.9.2。

(注意: data model 中的其他方法也会发生同样的情况,例如 __gt____eq__ 等)

最佳答案

这是因为魔术方法是在类上查找的,而不是在实例上查找的。解释器在执行“可重载”操作时绕过了通常的属性获取机制。

似乎是这样,因为它最初是如何在 CPython 中实现的,例如因为 type slots工作(不是 __slots__ 插槽,这是另一回事):+* 或其他运算符如何作用于值由其类决定,不是基于每个实例。

这样做有一个性能优势:查找 dunder 方法可能涉及字典查找,或更糟糕的是,使用 __getattr__/__getattribute__ 进行一些动态计算。不过,我不知道这是否是造成这种情况的主要原因。

我找不到详细的书面描述,但有 a talk by Armin Ronacher on YouTube对此进行了相当深入的研究。

关于python - 无法用 lambda 覆盖 __contains__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72451109/

相关文章:

python - 在运行时设置点属性?

python - 从文件导入模块不起作用

python - Nuke Python 获取 if 语句的旋钮值

python - 将 os.system() 与 sed 命令一起使用时出现问题

python - python中的pycurl和curl有什么区别

python - 检查元组中的两个元素是否具有相同的值

python - 问题 "removing".sql 文件中的行 block

javascript - 是否有基于 html/css/js 的富 Web 客户端框架?

python - 按字符串值选择行的最优雅方式

Python 将日期和时间转换为 pandas 索引