Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialEric Peppler
3,675 PointsWhy doesn't super().__len__() take any arguments?
class Liar(list):
def __len__(self):
return super().__len__() + 4
I was surprised to find that this was correct. Help me parse what I'm doing into english... I'm extending the list class by creating a list subclass called Liar. It takes a list as an argument. I gave the Liar class a magic len method. It takes an instance of itself (a kind of list) as an argument and returns the length of itself (as defined by the list class's magic len method) plus four.
Am I saying everything right there?
And why doesn't super().len() need an instance passed to it? Isn't it just a method that thinks it's about to be passed something? Why isn't it super().len(self)??
Thanks
1 Answer
Jeff Muday
Treehouse Moderator 28,722 Pointsthe
len(x)
method of Python is a common way to find the length of an object's data store. Thelen()
method calls the magic "dunder method"__len__()
of the object which reports an integer length.The Liar class inherits ALL the methods of the Python list, but we override only the
__len__()
method. To accomplish our goal for the Liar class we need to know what the length of the data contained in the Liar object and then "misreport" the value. So thesuper().__len__()
calls the inherited code which returns the list length and to that we simply add on an offset. So the object "lies" about its length.You are insightful in thinking there are other ways to do this! We have to be careful that we don't create a recursive call when we use Python's
len()
method-- callinglen(self)
will cause a runtime error because the object recursively calls itself. So it involves MAKING A COPY of the object avoids this problem-- we make a copy by callingself[:]
and reporting itslen(self[:])
value
class Liar(list):
def __len__(self):
# call the inherited __len__() + 4
return super().__len__() + 4
class Liar2(list):
def __len__(self):
# return the length of a COPY of the list + 3
return len(self[:]) + 3
x = Liar([1,2,3])
y = Liar2([1,2,3])
print('x =',x)
print('type of x =', type(x))
print('len(x) =', len(x))
print('y=',y)
print('type of y =', type(y))
print('len(y) =', len(y))
Here are the results:
x = [1, 2, 3]
type of x = <class '__main__.Liar'>
len(x) = 7
y= [1, 2, 3]
type of y = <class '__main__.Liar2'>
len(y) = 6