<ex*****@divmod.comescribió:
On Wed, 22 Oct 2008 08:29:08 -0400, Neal Becker <nd*******@gmail.com>
wrote:>I have a class (actually implemented in c++ using boost::python). For
an instance of this class, 'r', I'd like to support len (r). I don't
want to add it to the c++ code, because this is a unique situation:
this class should not normally support len().
So I try:
r = ring_int (10)
r.__len__ = lambda: 10
This doesn't work:>>>>len(r)TypeError: object of type 'ring_int' has no len()
Special methods aren't looked up in the instance dict of instances ofAll special methods have names like "__special__" (except "next" -used in
new-style classes. Exactly what constitutes the set of "special methods"
is a bit undefined. Consider anything that CPython has to look up to
satisfy some other operation, such as len or +, to be a special method
and don't rely on _either_ it being looked up on the instance or it _not_
being looked up on the instance (ie, don't put a method there and expect
it
not to be called). The methods which are actually considered special by
CPython can change and has in the past.
the iterator protocol- which will become __next__ in 3.0; any others?) -
this is stated here
http://docs.python.org/reference/lex...of-identifiers.
(But I'm sure you already knew that)
To the OP: you may use a "template method". In the C++ class do the
equivalent of:
class Ring_int(int):
def __len__(self): return self._len_impl()
def _len_impl(self): raise NotImplementedError
Now you can override _len_impl in the instance:
pyr = Ring_int(10)
pyr._len_impl = lambda: 10
pylen(r)
10
Note that hasattr(r, '__len__') is true, don't use that check in this case.
--
Gabriel Genellina