Iterator Custom Performance

I come across what seems like a rather unexpected difference in performance when repeating multiple containers with a custom iterator. I was hoping that someone could help me understand where these differences came from.

First context; I am writing several python extension modules using boost :: python, one of which contains a binding to the three-dimensional vector type float, which implements getitem. Since it has the ability to iterate over it, however it seems rather slow, but it is not clear why I decided to play with some regular python iterators in order to better understand how everything works. That's where these iterators came from ...

class MyIterator1(object):
    __slots__ = ['values', 'popfn']

    def __init__(self):
        self.values = ['x', 'y', 'z']
        self.popfn = self.values.pop

    def __length_hint__(self):
        return 3

    def __iter__(self):
        return self

    def next(self):
        try:
            return self.popfn()
        except IndexError:
            raise StopIteration

class MyIterator2(object):
    __slots__ = ['values', 'itfn']

    def __init__(self):
        self.values = ['x', 'y', 'z']
        it = iter(self.values)
        self.itfn = it.next

    def __length_hint__(self):
        return 3

    def __iter__(self):
        return self

    def next(self):
        return self.itfn()

class MyIterator3(object):
    __slots__ = ['values', 'i']

    def __init__(self):
        self.values = ['x', 'y', 'z']
        self.i = 0

    def __length_hint__(self):
        return 3

    def __iter__(self):
        return self

    def next(self):
        if self.i >= 3:
            raise StopIteration
        value = self.values[self.i]
        self.i += 1
        return value

def MyIterator4():
    val = ['x', 'y', 'z']
    yield val[0]
    yield val[1]
    yield val[2]

script timeit ( , testiter)

import timeit

timer1 = timeit.Timer('r = list(testiter.MyIterator1())', 'import testiter')
timer2 = timeit.Timer('r = list(testiter.MyIterator2())', 'import testiter')
timer3 = timeit.Timer('r = list(testiter.MyIterator3())', 'import testiter')
timer4 = timeit.Timer('r = list(testiter.MyIterator4())', 'import testiter')
timer5 = timeit.Timer('r = list(iter(["x", "y", "z"]))', 'import testiter')

print 'list(testiter.MyIterator1())'
print timer1.timeit()

print "\n"

print 'list(testiter.MyIterator2())'
print timer2.timeit()

print "\n"

print 'list(testiter.MyIterator3())'
print timer3.timeit()

print "\n"

print 'list(testiter.MyIterator4())'
print timer4.timeit()

print "\n"

print 'list(iter(["x", "y", "z"]))'
print timer5.timeit()

list(testiter.MyIterator1())
8.57359290123


list(testiter.MyIterator2())
5.28959393501


list(testiter.MyIterator3())
6.11230111122


list(testiter.MyIterator4())
2.31263613701


list(iter(["x", "y", "z"]))
1.26243281364

, python , . , python. , MyIterator, , , c, . . try/except , , - ?

! .

+5
1

; , :

  • pop next, , . , . , .
  • , () . , , , , .
  • , . , , , , , .
+2

All Articles