19

example:

a_list = [1, 2, 3]
a_list.len() # doesn't work
len(a_list) # works

Python being (very) object oriented, I don't understand why the 'len' function isn't inherited by the object. Plus I keep trying the wrong solution since it appears as the logical one to me

Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256
Franck Mesirard
  • 3,169
  • 3
  • 20
  • 17

7 Answers7

45

Guido's explanation is here:

First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:

(a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. Compare the easy with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.

(b) When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container. To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len(). Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.

Saying the same thing in another way, I see ‘len‘ as a built-in operation. I’d hate to lose that. /…/

Community
  • 1
  • 1
Jim
  • 72,985
  • 14
  • 101
  • 108
  • 28
    For those who don't know, HCI stands for Human-Computer Interface. So when Guido says he made the decision for "HCI reasons" he's saying he thought it made the code more readable. – Eli Courtwright Sep 17 '08 at 16:47
  • 1
    @Thomas: Python uses `|` for bitwise OR, just like C does. – dan04 Aug 03 '10 at 23:32
  • 2
    The one where Guido argues generic functions are better than methods. The mind boggles. :/ – Andy Hayden Nov 20 '15 at 18:08
13

The short answer: 1) backwards compatibility and 2) there's not enough of a difference for it to really matter. For a more detailed explanation, read on.

The idiomatic Python approach to such operations is special methods which aren't intended to be called directly. For example, to make x + y work for your own class, you write a __add__ method. To make sure that int(spam) properly converts your custom class, write a __int__ method. To make sure that len(foo) does something sensible, write a __len__ method.

This is how things have always been with Python, and I think it makes a lot of sense for some things. In particular, this seems like a sensible way to implement operator overloading. As for the rest, different languages disagree; in Ruby you'd convert something to an integer by calling spam.to_i directly instead of saying int(spam).

You're right that Python is an extremely object-oriented language and that having to call an external function on an object to get its length seems odd. On the other hand, len(silly_walks) isn't any more onerous than silly_walks.len(), and Guido has said that he actually prefers it (http://mail.python.org/pipermail/python-3000/2006-November/004643.html).

Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256
  • 5
    Ah... this finally made sense of it all. len() is more of an operator that a function, really. – Nate Sep 18 '08 at 14:28
11

It just isn't.

You can, however, do:

>>> [1,2,3].__len__()

3

Adding a __len__() method to a class is what makes the len() magic work.

Nate
  • 4,561
  • 2
  • 34
  • 44
6

This way fits in better with the rest of the language. The convention in python is that you add __foo__ special methods to objects to make them have certain capabilities (rather than e.g. deriving from a specific base class). For example, an object is

  • callable if it has a __call__ method
  • iterable if it has an __iter__ method,
  • supports access with [] if it has __getitem__ and __setitem__.
  • ...

One of these special methods is __len__ which makes it have a length accessible with len().

dF.
  • 74,139
  • 30
  • 130
  • 136
2

Maybe you're looking for __len__. If that method exists, then len(a) calls it:

>>> class Spam:
...   def __len__(self): return 3
... 
>>> s = Spam()
>>> len(s)
3
Bill Barksdale
  • 2,466
  • 1
  • 14
  • 6
2

Well, there actually is a length method, it is just hidden:

>>> a_list = [1, 2, 3]
>>> a_list.__len__()
3

The len() built-in function appears to be simply a wrapper for a call to the hidden len() method of the object.

Not sure why they made the decision to implement things this way though.

Dave Costa
  • 47,262
  • 8
  • 56
  • 72
2

there is some good info below on why certain things are functions and other are methods. It does indeed cause some inconsistencies in the language.

http://mail.python.org/pipermail/python-dev/2008-January/076612.html

Corey Goldberg
  • 59,062
  • 28
  • 129
  • 143