I'm trying to have a class act in every way like a tuple that's an attribute of the class, so len(instance) would be the same as len(instance.tup), instance[3] would return instance.tup[3], etc. Here's the class:
class mytup(object):
def __init__(self, a):
self.tup = tuple(a)
def __getattr__(self, nm):
f = types.MethodType(lambda self:getattr(self.tup, nm)(), self, type(self))
f.__func__.func_name = nm
setattr(self, nm, f)
return f
I can
mt = mytup(range(10))
But if I try to:
In [253]: len(mt)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-253-67688b907b8a> in <module>()
----> 1 len(mt)
TypeError: object of type 'mytup' has no len()
mt does in fact have a __len__ that I can call:
In [254]: mt.__len__
Out[254]: <bound method mytup.__len__ of <__main__.mytup object at 0x2e85150>>
In [255]: mt.__len__()
Out[255]: 10
(I even renamed it __len__). As near as I can tell, this should look just as if I did:
def __len__(self, *a):
return self.tup.__len__(*a)
But python won't let me len(mt) (or mt[2] or mt [1:5] for that matter).
New-style classes look-up "special methods"—those that start and end with two underscore characters—on an instance's class not the instance involved, so when len()
is called it tries to call typeof(mt).__len__()
. So the proper way to do what you want would be to use one of the Abstract Base Classes for Containers in the collections
module (since Python 3.3)
import collections.abc
class MyTuple(collections.abc.Sequence):
def __init__(self, a):
self.tup = tuple(a)
def __len__(self):
return len(self.tup)
def __getitem__(self, index):
return self.tup[index]
mt = MyTuple(range(10))
print(len(mt)) # -> 10
print(mt[4]) # -> 4
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