在Python中模拟成员资格测试:将_包含_正确地委托给包含的对象

在Python中模拟成员资格测试:将_包含_正确地委托给包含的对象,python,containers,delegation,emulation,iterable,Python,Containers,Delegation,Emulation,Iterable,我习惯于Python允许一些巧妙的技巧将功能委托给其他对象。一个例子是对包含对象的委托 但是,我没有运气,当我想授权时,包含: class A(object): def __init__(self): self.mydict = {} self.__contains__ = self.mydict.__contains__ a = A() 1 in a 我得到: Traceback (most recent call last): File "<st

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

但是,我没有运气,当我想授权时,包含:

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
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:类型为“A”的参数不可编辑

我做错了什么?当我调用._包含_(1)时,一切都很顺利。我甚至试图在A中定义一个iter方法,使A看起来更像一个iterable,但没有帮助。我在这里遗漏了什么?

特殊方法,如
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>仅当在类上定义时才是特殊的,而不是在实例上(除了在

那么,你的代表团是否在班级层面:

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

    def __contains__(self, other):
       return self.mydict.__contains__(other)
实际上,我更喜欢将后者拼写为self.mydict中的
return other,但这是一个小的样式问题

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

class BlackMagic(object):
    def __init__(self):
        self.mydict = {}
        self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
        self.__class__.__contains__ = self.mydict.__contains__
本质上,经过一点点的黑魔法将
self.\uuu class\uuuu
重新分配给一个新的类对象(它的行为与前一个对象一样,但有一个空的dict,除了这个
self
)之外没有其他实例),在一个旧样式类中的任何地方都可以分配给
self.\uu magicname\uu
,改为分配给
self.\uuuuu class.\uuuuu magicname.\uuuuu
(并确保它是内置的或
staticmethod
,而不是普通的Python函数,当然,除非在某些不同的情况下,您确实希望它在实例上调用时接收
self

顺便说一句,这个
BlackMagic
类实例上的
in
操作符比以前提出的任何解决方案都要快,或者至少我用我通常的trusty
-mtimeit
(直接转到
内置方法
,而不是遵循涉及继承和描述符的常规查找路径,从而节省了一点开销)

一个自动执行
self.\uuuuu class\uuuuuuu
的元类——每个实例的想法并不难编写(它可以在生成的类的
\uuuu new\uuuuuuuuuu
方法中完成繁琐的工作,如果通过
\uuuuuu setattr\uuuuuuuuuu>或许多属性在实例上分配,也可以将所有魔法名称设置为实际分配给类)。但只有在对该功能的需求非常广泛的情况下(例如,将大量使用“每实例特殊方法”的大型古代Python 1.5.2项目移植到包括Python 3在内的现代Python中),这才是合理的


我推荐“聪明”或“黑魔法”解决方案吗?不,我不推荐:几乎总是以简单、直接的方式做事情更好。但是“几乎”在这里是一个重要的词,手头有这样先进的“钩子”很好对于极少数但并非不存在的情况,它们的使用可能是有理由的。

好吧,这对我来说有一些解释,但对我来说并不完全令人满意,因为这种类型的委托会花费额外的时间(我可以在旧式课程中节省些什么——为什么我不应该使用它们??)“不惜任何代价的表现”不是一个合理的目标:“过早优化是编程中万恶之源”(Knuth,引用Hoare的话)。现代风格的类在功能上更丰富、更通用、更规则、更简单(请参阅“简而言之的Python”第103页的底部,您可以在Google Book Search上读到它——搜索“每实例方法”)。在Python3及更高版本中,遗留类将永远消失-不要将代码绑定到它们以节省微秒的相关性。顺便说一句,更快的方法是从dict继承(这也为您提供了一个新样式的类)。嗨,Alex,感谢编程方面的讲座,我不需要;-)对不起,我们不是圣经学者,所以只需引用一些圣经经文或“大教师“对我来说还不够好。其他解释很好,特别是关于遗留类的解释。我不想坚持旧有的观点,但我要讲道理!同时,我也想到了继承解决方案,它满足了我的特殊问题。不过,在这一点上,旧式类更灵活/更具动态性(特殊方法的每个实例重写在其他情况下也可能很好!)Addon:我的意思是,在速度不是首要原因的情况下,此功能也可能很有用。我喜欢Python的是它的动态性——这在这方面有一点降低。老式的类很粗糙——如果你想要无限制的动态性,Python对你来说不是最佳选择(monkeypatch内置的东西不能像Javascript和Ruby中的那样,等等);相反,我们总是试图平衡好的结构和动态。如果最快速度不是关键问题,那么您总是可以在类上定义特殊方法,并根据需要使其重定向功能。