add method to class dynamically?

Jean-Paul Calderone exarkun at divmod.com
Wed Oct 22 08:37:11 EDT 2008


On Wed, 22 Oct 2008 08:29:08 -0400, Neal Becker <ndbecker2 at 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()
>
>It appears that __len__ is being looked up only on the class dict, not the instance dict?  What's the correct way to do this?  (Of course, I could just use inheritance, but this is an opportunity for me to learn more about python)
>

I don't really know anything about the kind of classes that boost makes,
however the behavior you describe is like the behavior of new-style
classes:

  >>> class x: pass
  ... 
  >>> y = x()
  >>> y.__len__ = lambda: 10
  >>> len(y)
  10
  >>> class x(object): pass
  ... 
  >>> y = x()
  >>> y.__len__ = lambda: 10
  >>> len(y)
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  TypeError: object of type 'x' 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.

Jean-Paul



More information about the Python-list mailing list