Is there a way to make len()
work with instance methods without modifying the class?
Example of my problem:
>>> class A(object):
... pass
...
>>> a = A()
>>> a.__len__ = lambda: 2
>>> a.__len__()
2
>>> len(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'A' has no len()
Note:
A
will have different __len__
methods attachedA
No. Python always looks up special methods through the object's class. There are several good reasons for this, one being that repr(A)
should use type(A).__repr__
instead of A.__repr__
, which is intended to handle instances of A
instead of the A
class itself.
If you want different instances of A
to compute their len
differently, consider having __len__
delegate to another method:
class A(object):
def __len__(self):
return self._len()
a = A()
a._len = lambda: 2
Special methods such as __len__
(double-underscore or "dunder" methods) must be defined on the class. They won't work if only defined on the instance.
It is possible to define non-dunder methods on an instance. However, you must convert your function to an instance method by adding a wrapper to it, which is how self
gets passed in. (This would normally be done when accessing the method, as a method defined on the class is a descriptor that returns a wrapper.) This can be done as follows:
a.len = (lambda self: 2).__get__(a, type(a))
Combining these ideas, we can write a __len__()
on the class that delegates to a len()
that we can define on the instance:
class A(object):
def __len__(self):
return self.len()
a = A()
a.len = (lambda self: 2).__get__(a, type(a))
print(len(a)) # prints 2
You can actually simplify this in your case because you don't need self
in order to return your constant 2
. So you can just assign a.len = lambda: 2
. However, if you need self
, then you need to make the method wrapper.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With