Jue*_*gen 6 python containers iterable delegation emulation
我习惯于Python允许一些巧妙的技巧将功能委托给其他对象.一个例子是委托给包含的对象.
但当我想委托__contains __时,它接缝,我没有运气
class A(object):
def __init__(self):
self.mydict = {}
self.__contains__ = self.mydict.__contains__
a = A()
1 in a
Run Code Online (Sandbox Code Playgroud)
我明白了:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'A' is not iterable
Run Code Online (Sandbox Code Playgroud)
我错了什么?当我打电话给.__包含__(1)时,一切顺利.我甚至试图在A中定义一个__iter __方法,使A看起来像一个可迭代的,但它没有帮助.我在这里错过了什么?
Ale*_*lli 18
特殊的方法,如__contains__在类中定义的时候,而不是在实例(除在Python 2遗产类,你应该仅仅是特殊的不无论如何使用).
那么,你的代表团是否在课堂上:
class A(object):
def __init__(self):
self.mydict = {}
def __contains__(self, other):
return self.mydict.__contains__(other)
Run Code Online (Sandbox Code Playgroud)
我实际上更喜欢拼写后者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__
Run Code Online (Sandbox Code Playgroud)
基本上,在一小部分黑魔法重新分配self.__class__给一个新的类对象(它的行为与前一个类似,但有一个空的dict,除了这个之外没有其他实例self)之后,你将分配给旧的类self.__magicname__,以self.__class__.__magicname__代替(并确保它是一个内置的或staticmethod不正常的Python的功能,当然,除非在一些不同的情况下你希望它收到self的实例调用时).
顺便说一句,in在这个实例操作BlackMagic类是更快,因为它发生,比任何先前提出的解决方案-或者至少使我和我平时信赖的测量-mtimeit(直接到built-in method,而不是按正常查询涉及继承和描述符的路由,削减了一些开销).
用于自动化self.__class__-per-instance构思的元类并不难写(它可以在生成的类的__new__方法中执行脏工作,并且如果在实例上分配,也可以通过设置所有魔术名称实际分配给类__setattr__或许多很多属性).但是这将是正义的,如果需要这个功能真的很普遍(如移植是自由的使用"每个实例特殊的方法"现代的Python,包括Python 3一个巨大的古老的Python 1.5.2项目).
我推荐 "聪明"或"黑魔法"解决方案吗?不,我不这样做:几乎总是以简单,直接的方式做事情.但"几乎"是一个重要的词在这里,它是很好的手边有这样先进的"钩子"为罕见,但并非不存在,他们的使用实际上可能是必要的情况下.