En Wed, 22 Oct 2008 10:37:11 -0200, Jean-Paul Calderone <[EMAIL PROTECTED]> escribió:

On Wed, 22 Oct 2008 08:29:08 -0400, Neal Becker <[EMAIL PROTECTED]> 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 of
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.

All special methods have names like "__special__" (except "next" -used in the iterator protocol- which will become __next__ in 3.0; any others?) - this is stated here http://docs.python.org/reference/lexical_analysis.html#reserved-classes-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:

py> r = Ring_int(10)
py> r._len_impl = lambda: 10
py> len(r)
10

Note that hasattr(r, '__len__') is true, don't use that check in this case.

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to