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

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

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

问题是3 in top返回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相关问答推荐

已安装' owiener ' Python模块,但在导入过程中始终没有名为owiener的模块

将词典写入Excel

Python中使用Delivercio进行多个请求

在Docker中运行HAProxy时无法获得503服务

如何使用PyTest根据self 模拟具有副作用的属性

Python主进程和分支进程如何共享gc信息?

由于瓶颈,Python代码执行太慢-寻求性能优化

在使用Guouti包的Python中运行MPP模型时内存不足

如何使用上下文管理器创建类的实例?

在Pandas框架中截短至固定数量的列

具有症状的分段函数:如何仅针对某些输入值定义函数?

对Numpy函数进行载体化

使用FASTCGI在IIS上运行Django频道

难以在Manim中正确定位对象

. str.替换pandas.series的方法未按预期工作

计算每个IP的平均值

在含噪声的3D点网格中识别4连通点模式

交替字符串位置的正则表达式

语法错误:文档. evaluate:表达式不是合法表达式

Tensorflow tokenizer问题.num_words到底做了什么?