The following code works perfectly in Python 2.x:
class a:
def __init__ (self, *args):
self.lst = list(args)
self.__len__ = self.lst.__len__
b = a(1, 2, 3)
print(len(b))
In Python 3 it shouts:
TypeError: object of type 'a' has no len()
WHAT HAVE THEY DONE!!!!!!!!????
I disparately need this feature to work, and only time i succeeded was changing it in a class e.g.:
b = a()
b.__class__.__len__ = lambda: 123
But this changes the class, not my instance, and therefore it is not thread safe, and it is stupid besides. It does not work even inside new() instead of init() which I thought it might.
What is even worse, if I do as shown above (with the lambda) on an instance then:
>>> hasattr(b, "__len__")
True
>>> b.__len__()
123
>>> # But:
>>> len(b)
Traceback...
TypeError: object 'b' has no len()
What is alarming is that when I define the len() wrapper inside a class, then change it from outside or within an method, it changes, but len() somehow gets to the original method. I am guessing that this have something to do with trying to introduce statically referenced names at compile time instead of keeping all of them in a dict. But who cares, I need it to work.
clas c:
def __len__ (self):
return 123
>>> d = c()
>>> len(d)
123
>>> d.__len__ = lambda: 333
>>> len(d)
123
>>> d.__len__()
333
Changing d.__dict__ or using setattr()
doesn't help either. How, or rather, where, are the pointers kept apart? Interesting behaviour.
If I redefine the len() function:
len = lambda o: o.__len__()
It may save me for the len() problem, but what is with .__contains__, .__eq__, etc.
I need a custom container and I need to bind the underlying datastructure's wrapper methods to my instances for micro optimization. Besides, I have codes with a lot of such tricks and I need to rewrite them for Py3. I do not plan to spend the eternity hunting for these lines in a code and adding methods that unnecessarily call other methods. This is bad.
What do I do?