Emulating membership-test in Python: delegating __contains__ to contained-object correctly
containers, delegation, emulation, iterable, python
Solution
Special methods such as `__contains__` are only special when defined on the class, not on the instance (except in legacy classes in Python 2, which you should not use anyway).
So, do your delegation at class level:
class A(object):
def __init__(self):
self.mydict = {}
def __contains__(self, other):
return self.mydict.__contains__(other)
I'd actually prefer to spell the latter as `return other in self.mydict`, but that's a minor style issue.
Edit: if and when "totally dynamic per-instance redirecting of special methods" (like old-style classes offered) is indispensable, it's not hard to implement it with new-style classes: you just need each instance that has such peculiar need to be wrapped in its own special class. For example:
class BlackMagic(object):
def __init__(self):
self.mydict = {}
self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
self.__class__.__contains__ = self.mydict.__contains__
Essentially, after the little bit of black magic reassigning `self.__class__` to a new class object (which behaves just like the previous one but has an empty dict and no other instances except this one `self`), anywhere in an old-style class you would assign to `self.__magicname__`, assign to `self.__class__.__magicname__` instead (and make sure it's a built-in or `staticmethod`, not a normal Python function, unless of course in some different case you do want it to receive the `self` when called on the instance).
Incidentally, the `in` operator on an instance of this `BlackMagic` class is faster, as it happens, than with any of the previously proposed solutions -- or at least so I'm measuring with my usual trusty `-mtimeit` (going directly to the `built-in method`, instead of following normal lookup routes involving inheritance and descriptors, shaves a bit of the overhead).
A metaclass to automate the `self.__class__`-per-instance idea would not be hard to write (it could do the dirty work in the generated class's `__new__` method, and maybe also set all magic names to actually assign on the class if assigned on the instance, either via `__setattr__` or many, many properties). But that would be justified only if the need for this feature was really widespread (e.g. porting a huge ancient Python 1.5.2 project that liberally use "per-instance special methods" to modern Python, including Python 3).
Do I recommend "clever" or "black magic" solutions? No, I don't: almost invariably it's better to do things in simple, straightforward ways. But "almost" is an important word here, and it's nice to have at hand such advanced "hooks" for the rare, but not non-existent, situations where their use may actually be warranted.
Problem
I am used to that Python allows some neat tricks to delegate functionality to other objects. One example is delegation to contained objects. But it seams, that I don't have luck, when I want to delegate __contains __: ``` class A(object): def __init__(self): self.mydict = {} self.__contains__ = self.mydict.__contains__ a = A() 1 in a ``` I get: ``` Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: argument of type 'A' is not iterable ``` What I am making wrong? When I call a.__contains __(1), everything goes smooth. I even tried to define an __iter __ method in A to make A more look like an iterable, but it did not help. What I am missing out here?