tags:

views:

15204

answers:

5

In python is this the only way to get the number of elements:

arr.__len__()

If so, why the strange syntax?

+33  A: 
mylist = [1,2,3,4,5]
len(mylist)

The same works for tuples:

mytuple = (1,2,3,4,5)
len(mytuple)

It was intentionally done this way so that lists, tuples and other container types didn't all need to explicitly implement a public .length() method, instead you can just check the len() of anything that implements the 'magic' __len__() method. So even objects you may not consider to be lists of elements could still be length-checked. This includes strings, queues, trees, etc.

Soviut
What's the difference between len and __len__?
Joan Venge
len() is a language command, __len__() is a method on container types.
Soviut
len() is a global, builtin function; __len__() is a method that object can implement. len(foo) usually ends up calling foo.__len__().
Tim Lesher
Good one, thanks.
Joan Venge
Also in this case, shouldn't the __len__ be prevented to be called directly? Because some people might just use it without knowing.
Joan Venge
it doesn't matter if it gets called directly, the double underscores indicate that its a special method and basically to use at your own risk.
Soviut
But for cleanest, or tidiness shouldn't these internal methods get hidden?
Joan Venge
They start with double underscores - what more hiding do you want?
David Zaslavsky
You mention that by supplying len() each container does not have to implement a .length() method, but how is this different, if each type still implements a __len__() method which gets called by len() anyways? Is different container types handled differently by len()?
Simon Jensen
... Not debating your answer, merely a question out of interest. I'm not that familiar with the internal workings of Python.
Simon Jensen
@David: I was thinking more like a private member so you can't access it directly.
Joan Venge
@Joan: No, nothing in Python is inaccessible because of the dynamic nature and duck typing. Let the explicit public/private thing from Java/.NET go, it simply doesn't apply in Python. Took me a while to get used to too.
Soviut
@Simon: len() doesn't handle them differently, its just that different containers have different ways of collecting their lengths (a tree container may only return the number of top level branches it has, etc.) and __len__ is a universal entry point for implementing this.
Soviut
@Simon: the bit about "don't all need to implement .length()" is confusing. Container types still need to implement a method for returning their length; the point is that it's a standardized protocol, not an ad-hoc method you have to look up for each type. The double-underscores signify this.
Carl Meyer
I've tried rewording my answer just a little to be more clear.
Soviut
+2  A: 

Just use len(arr):

>>> import array
>>> arr = array.array('i')
>>> arr.append('2')
>>> arr.__len__()
1
>>> len(arr)
1
Tim Lesher
Usually we just assume that when a newbie says "array" she means "list"; +1 for not assuming that :)
nosklo
I saw that, and saw that there was already an answer using list. The only reason I added an answer was in case the question really was using an array, and was about to ask, "Well, yes, but what about an array?" I upvoted Soviut's answer anyway. :-)
Tim Lesher
+8  A: 

The preferred way to get the length of any python object is to pass it as an argument to the len function. Internally, python will then try to call the special __len__ method of the object that was passed.

David Locke
+3  A: 

The way you take a length of anything for which that makes sense (a list, dictionary, tuple, string, ...) is to call len on it.

l = [1,2,3,4]
s = 'abcde'
len(l) #returns 4
len(s) #returns 5

The reason for the "strange" syntax is that internally python translates len(object) into object.__len__(). This applies to any object. So, if you are defining some class and it makes sense for it to have a length, just define a __len__() method on it and then one can call len on those instances.

rz
don't you mean __len__?
Algorias
the markup turns __len__ into bolded len. put backticks around it to make it read as code: `__len__()`.
Autoplectic
underscores have special meaning in StackOverflow's formatting so they won't show up so you must escape. I fixed it for you, next time read your answer in the preview area before posting :)
nosklo
thanks, nosklo. no more answering in a hurry for me :)
rz
+2  A: 

Python uses duck typing: it doesn't care about what an object is, as long as it has the appropriate interface for the situation at hand. When you call the built-in function len() on an object, you are actually calling its internal __len__ method. A custom object can implement this interface and len() will return the answer, even if the object is not conceptually a sequence.

For a complete list of interfaces, have a look here: http://docs.python.org/reference/datamodel.html#basic-customization

UncleZeiv