python - 在 Python : delegating __contains__ to contained-object correctly 中模拟成员资格测试

标签 python containers delegation emulation iterable

我已经习惯了 Python 允许一些巧妙的技巧将功能委托(delegate)给其他对象。一个例子是委托(delegate)给包含的对象。

但它接缝,我没有运气,当我想委托(delegate) __contains __ 时:

class A(object):
    def __init__(self):
       self.mydict = {}
       self.__contains__ = self.mydict.__contains__

a = A()
1 in a

我得到:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'A' is not iterable

我做错了什么?当我调用 a.__contains __(1) 时,一切都很顺利。我什至试图在 A 中定义一个 __iter __ 方法来使 A 看起来更像一个可迭代对象,但它没有帮助。我在这里错过了什么?

最佳答案

__contains__ 等特殊方法只有在类上定义时才是特殊的,而不是在实例上(Python 2 中的遗留类除外,您无论如何都不应使用它们) ).

那么,在类(class)层面做你的代表团:

class A(object):
    def __init__(self):
       self.mydict = {}

    def __contains__(self, other):
       return self.mydict.__contains__(other)

我实际上更愿意将后者拼写为 return other in self.mydict,但这是一个小的样式问题。

编辑:如果“特殊方法的完全动态的按实例重定向”(如提供的旧式类)是必不可少的,那么用新式类实现它并不难:你只需要将具有这种特殊需求的每个实例都包装在自己的特殊类中。例如:

class BlackMagic(object):
    def __init__(self):
        self.mydict = {}
        self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
        self.__class__.__contains__ = self.mydict.__contains__

本质上,在将 self.__class__ 重新分配给一个新的类对象(其行为与前一个类对象一样,但有一个空的字典,除了这个之外没有其他实例 >self),在旧式类中的任何地方,你将分配给 self.__magicname__,改为分配给 self.__class__.__magicname__(并确保它是一个内置的或 staticmethod,而不是一个普通的 Python 函数,当然除非在某些不同的情况下你确实希望它在调用实例时接收 self。/p>

顺便说一下,这个 BlackMagic 类的实例上的 in 操作符 faster 碰巧比之前提出的任何一个解决方案——或者至少我正在用我通常信任的-mtimeit 进行测量(直接转到内置方法,而不是遵循涉及继承和描述符,减少了一些开销)。

一个元类来自动化 self.__class__-per-instance 的想法并不难写(它可以在生成的类的 __new__ 方法中完成肮脏的工作,如果通过 __setattr__ 或许多 many 属性分配给实例,也可能将所有魔法名称设置为实际分配给类)。但只有当对该功能的需求真的很普遍时(例如,将一个巨大的古老 Python 1.5.2 项目自由地使用“每个实例的特殊方法”移植到现代 Python,包括 Python 3),这才是合理的。

推荐“聪明”或“黑魔法”解决方案吗?不,我不知道:几乎总是以简单、直接的方式做事更好。但是“几乎”在这里是一个重要的词,很高兴手头有这样的高级“钩子(Hook)”,用于实际可能需要使用它们的罕见但并非不存在的情况。

关于python - 在 Python : delegating __contains__ to contained-object correctly 中模拟成员资格测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1022499/

相关文章:

java - 分组类的方式与 PHP 不同吗?

ASP.Net Web 应用程序尝试使用模拟和委派连接到 SQL Server

python - 在 SQL 中编写多个 LIKE 子句的另一种方法

python - 运行时警告: You're running the worker with superuser privileges: this is absolutely not recommended

c++ - 池容器的最佳数据结构是什么?

docker - Kubeadm init 警告 - 没有可用的验证器

dependency-injection - Dockerfile 自定义命令/指令

inheritance - Kotlin - 委托(delegate)而不是单例中的继承

python - Python 的 os.system() 相当于 cocoa/Objective-C 的什么?

python - 使用 urllib2 加速多次下载