特殊方法,例如__contains__
仅在类上定义时才特殊,而不是在实例上定义(Python 2 中的遗留类除外,无论如何都不应该使用)。
所以,在课堂上做你的代表团:
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__
给一个新的类对象之后(它的行为与前一个类似,但有一个空的 dict 并且除了这个之外没有其他实例self
),在旧式类中的任何地方,您将分配给self.__magicname__
,分配改为self.__class__.__magicname__
(并确保它是内置的 or staticmethod
,而不是普通的 Python 函数,当然,除非在某些不同的情况下您确实希望它self
在实例上调用时接收)。
顺便说一下,这个类in
的实例上的操作符比以前提出的任何解决方案都要快——或者至少我用我通常的信任来测量(直接去,而不是遵循正常的查找涉及继承和描述符的路由,减少了一些开销)。BlackMagic
-mtimeit
built-in method
一个自动执行self.__class__
每个实例想法的元类并不难编写(它可以在生成的类的__new__
方法中完成繁琐的工作,并且如果在实例上分配,也可以将所有魔术名称设置为实际分配给类,或者通过__setattr__
或许多许多属性)。但这只有在对这个特性的需求真的很普遍的情况下才是合理的(例如,将一个巨大的古老的 Python 1.5.2 项目移植到现代 Python,包括 Python 3,该项目自由地使用“每个实例的特殊方法”)。
我推荐“聪明”还是“黑魔法”解决方案?不,我不这样做:几乎总是以简单、直接的方式做事更好。但是“几乎”在这里是一个重要的词,很高兴手头有这样先进的“钩子”,用于可能实际需要使用它们的罕见但并非不存在的情况。