list.__len__() or len(list)

N

Nikhil

which one is better? and why?

__len__() is a built-in function of the list object and is updated along
with the list object elements and will be useful incase the list is very
huge.

len() is an external method again, which may require the processing
cycles again.

Is it right?
 
A

alex.gaynor

which one is better? and why?

__len__() is a built-in function of the list object and is updated along
with the list object elements and will be useful incase the list is very
huge.

len() is an external method again, which may require the processing
cycles again.

Is it right?

len() is the correct way to do it, methods that begin with __ are
meant to be more internal.
 
I

Ian Kelly

__len__() is a built-in function of the list object and is updated along
with the list object elements and will be useful incase the list is very
huge.

len() is an external method again, which may require the processing cycles
again.

The purpose of obj.__len__() is to implement len(obj), which simply
calls it. So obj.__len__() may be faster, but only marginally. The
reason to prefer len(obj) is that if you inadvertently pass an object
that does not implement __len__, you get the more appropriate
TypeError rather than an AttributeError.
 
C

Christian Heimes

Ian said:
The purpose of obj.__len__() is to implement len(obj), which simply
calls it. So obj.__len__() may be faster, but only marginally. The
reason to prefer len(obj) is that if you inadvertently pass an object
that does not implement __len__, you get the more appropriate
TypeError rather than an AttributeError.

len(obj) is faster than obj.__len__() for several types like str. In
general len() is as least as fast __len__(). len() also does some extra
sanity checks.

python2.5 -m timeit "'abc'.__len__()"
1000000 loops, best of 3: 0.453 usec per loop

python2.5 -m timeit "len('abc')"
1000000 loops, best of 3: 0.292 usec per loop

Common code paths are already highly optimized. Don't try to be clever
unless you really understand what happens inside the interpreter. The
__internal__ methods are called magic methods for a reason. ;)

Christian
 
H

Hrvoje Niksic

Ian Kelly said:
The purpose of obj.__len__() is to implement len(obj), which simply
calls it. So obj.__len__() may be faster, but only marginally.

Have you tried it? __len__ is in fact marginally slower because it
involves a dict lookup, whereas the built-in len() knows how to cheat
and invoke __len__ through a slot in the C type struct very
efficiently.

$ python -m timeit -s 'l=[1, 2, 3]' 'len(l)'
1000000 loops, best of 3: 0.24 usec per loop
$ python -m timeit -s 'l=[1, 2, 3]' 'l.__len__()'
1000000 loops, best of 3: 0.347 usec per loop
 
H

Hrvoje Niksic

Ian Kelly said:
Have you tried it? __len__ is in fact marginally slower because it
involves a dict lookup, whereas the built-in len() knows how to cheat
and invoke __len__ through a slot in the C type struct very
efficiently.

$ python -m timeit -s 'l=[1, 2, 3]' 'len(l)'
1000000 loops, best of 3: 0.24 usec per loop
$ python -m timeit -s 'l=[1, 2, 3]' 'l.__len__()'
1000000 loops, best of 3: 0.347 usec per loop

For built-in types, sure.

Well, he did ask about list. :)
For user-defined types in Python, it's the other way around:

Yes, in that case the C slot contains a generic wrapper that still has
to locate and call the Python function, which ends up being slower.
The point is that such microoptimizations rarely make a difference,
and even then the difference can be counterintuitive, as in the list
example.
 
N

Nikhil

Christian said:
len(obj) is faster than obj.__len__() for several types like str. In
general len() is as least as fast __len__(). len() also does some extra
sanity checks.

python2.5 -m timeit "'abc'.__len__()"
1000000 loops, best of 3: 0.453 usec per loop

python2.5 -m timeit "len('abc')"
1000000 loops, best of 3: 0.292 usec per loop

Common code paths are already highly optimized. Don't try to be clever
unless you really understand what happens inside the interpreter. The
__internal__ methods are called magic methods for a reason. ;)

Christian
Thanks for the useful insight.
Then why to have __len__() internal method at all when the built-in
len() is faster?
I heard, in Python3, this internal method is being pruned/renamed to
something else? Can someone please shed light here?

Thanks. Nikhil
 
T

Terry Reedy

| Then why to have __len__() internal method at all when the built-in
| len() is faster?

Nearly all syntax constructions and builtin functions are implemented by
calling one or another of the __special__ methods. This is what makes
Python code so generic and plugging your own classes into the system so
easy.

For example, collection[key] = value is implemented by calling
collection.__setitem__(key, value). When you define a class with that
method, that syntax will work with its instances just the same as for
builtin classes.

Similarly, a+b is implemented by calling a.__add__(b). So if a class
defines __add__, you can 'add' its instances (whatever 'add' means for that
class) with '+'.

(The fact that an *implementation* may followup the 'as if' rule and
optimize operations for certain classes by combining steps does not negate
the *language* rules given above.)

tjr
 
C

Carl Banks

Thanks for the useful insight.
Then why to have __len__() internal method at all when the built-in
len() is faster?
I heard, in Python3, this internal method is being pruned/renamed to
something else? Can someone please shed light here?

My advice is to think of len() as an operator. Like other operators,
it can be overloaded using the __opname__ syntax:

-x calls x.__neg__
x+2 calls x.__add__
len(x) calls x.__len__

It's not really an operator: it's a regular built-in function, has no
special syntax, and no opcodes associated with it, but in sometimes it
helps to think of it as one.


Carl Banks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,665
Latest member
salkete

Latest Threads

Top