list.__len__() or len(list)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Nikhil

    list.__len__() or len(list)

    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?
  • alex.gaynor@gmail.com

    #2
    Re: list.__len__() or len(list)

    On May 13, 6:57 pm, Nikhil <mnik...@gmail. comwrote:
    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.

    Comment

    • Ian Kelly

      #3
      Re: list.__len__() or len(list)

      On Tue, May 13, 2008 at 5:57 PM, Nikhil <mnikhil@gmail. comwrote:
      __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.

      Comment

      • Christian Heimes

        #4
        Re: list.__len__() or len(list)

        Ian Kelly schrieb:
        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

        Comment

        • Hrvoje Niksic

          #5
          Re: list.__len__() or len(list)

          "Ian Kelly" <ian.g.kelly@gm ail.comwrites:
          On Tue, May 13, 2008 at 5:57 PM, Nikhil <mnikhil@gmail. comwrote:
          > __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.
          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

          Comment

          • Ian Kelly

            #6
            Re: list.__len__() or len(list)

            On Wed, May 14, 2008 at 1:01 AM, Hrvoje Niksic <hniksic@xemacs .orgwrote:
            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. For user-defined types in Python, it's the
            other way around:
            >>setup = 'class L:\n def __len__(self): return 42\nl = L()'
            >>t1 = timeit.Timer('l en(l)', setup)
            >>t2 = timeit.Timer('l .__len__()', setup)
            >>t1.timeit()
            0.6398137891827 0337
            >>t2.timeit()
            0.4105127187952 6041

            Comment

            • Hrvoje Niksic

              #7
              Re: list.__len__() or len(list)

              "Ian Kelly" <ian.g.kelly@gm ail.comwrites:
              On Wed, May 14, 2008 at 1:01 AM, Hrvoje Niksic <hniksic@xemacs .orgwrote:
              > 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 microoptimizati ons rarely make a difference,
              and even then the difference can be counterintuitiv e, as in the list
              example.

              Comment

              • Nikhil

                #8
                Re: list.__len__() or len(list)

                Christian Heimes wrote:
                Ian Kelly schrieb:
                >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
                >
                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

                Comment

                • Duncan Booth

                  #9
                  Re: list.__len__() or len(list)

                  Nikhil <mnikhil@gmail. comwrote:
                  Then why to have __len__() internal method at all when the built-in
                  len() is faster?
                  Because the internal method is used internally.

                  The idea is that you define __len__() on your objects when appropriate. You
                  are not expected to ever call it.

                  Comment

                  • Terry Reedy

                    #10
                    Re: list.__len__() or len(list)


                    "Nikhil" <mnikhil@gmail. comwrote in message
                    news:g0ev6o$utb $1@registered.m otzarella.org.. .
                    | 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.__se titem__(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



                    Comment

                    • Carl Banks

                      #11
                      Re: list.__len__() or len(list)

                      On May 14, 11:07 am, Nikhil <mnik...@gmail. comwrote:
                      Christian Heimes wrote:
                      Ian Kelly schrieb:
                      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
                      >
                      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

                      Comment

                      Working...