Arfat Salman
Software Engineer at Pesto Tech
@salman_arfat
Presented at PyDelhi, Gurgaon
class Range(object):
def __init__(self, low, high):
self.start = low
self.end = high
def __iter__(self):
class Iterator(object):
def __init__(self, low, high):
self.start = low
self.end = high
self.current = low
def __next__(self):
if self.current >= self.end:
raise StopIteration
val = self.current
self.current += 1
return val
return Iterator(self.start, self.end)
my_range = Range(2, 10)
range_iterator = iter(my_range)
print('Using iterator and next - ')
print(next(range_iterator)) # 2
print(next(range_iterator)) # 3
print(next(range_iterator)) # 4
print('Using iterable - ')
for val in my_range:
print(val, end=' ')
# 2 3 4 5 6 7 8 9
class Range(object):
def __init__(self, low, high):
self.start = low
self.end = high
self.current = low
def __iter__(self):
return self
def __next__(self):
if self.current >= self.end:
raise StopIteration
val = self.current
self.current += 1
return val
my_range = Range(2,10)
range_iterator = iter(my_range)
print('Using iterator and next - ')
print(next(range_iterator)) # 2
print(next(range_iterator)) # 3
print(next(range_iterator)) # 4
print('Using iterable - ')
for val in my_range:
print(val, end=' ')
# 5 6 7 8 9
for elm in [1, 2, 'a', 'b']:
print(elm)
# Results
1
2
a
b
details = {
'first_name': 'Arfat',
'last_name': 'Salman',
'twitter_handle': '@salman_arfat'
}
for key in details:
print(key, end=' ')
# first_name last_name twitter_handle
for key in 'abcdefghi':
print(key, end=' ')
# a b c d e f g h i
for line in open('text.txt'):
print(line)
# A line printed here
a,b,c = iter([1,2,3])
def Range(start, end):
current = start
while current < end:
yield current
current += 1
raise StopIteration
my_range_generator = Range(2,10)
range_iterator = iter(my_range_generator)
print(Range)
print(my_range_generator)
print('range_iterator is my_range_generator? - ',
range_iterator is my_range_generator)
for val in my_range_generator:
print(val, end=' ')
# <function Range at 0x10f6100d0>
# <generator object Range at 0x10f78bf68>
# range_iterator is my_range_generator? - True
# 2 3 4 5 6 7 8 9
generating_func = (n for n in range(3, 9) if n > 5)
print(generating_func)
print(next(generating_func))
print(next(generating_func))
print(next(generating_func))
# <generator object <genexpr> at 0x102a0af68>
# 6
# 7
# 8
( expression for expr in sequence1 if condition1 ...
for exprN in sequenceN
if conditionN )
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
import itertools
list(itertools.islice(fib(), 10))
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
def fib(n):
a = b = 1
result = []
for i in xrange(n):
result.append(a)
a, b = b, a + b
return result
Use a list instead of a generator when:
for i in outer: # used once, okay to be a generator or return a list
for j in inner: # used multiple times, reusing a list is better
...
for i in reversed(data): ... # generators aren't reversible
s[i], s[j] = s[j], s[i] # generators aren't indexable
Premature optimization is the root of all evil in programming. - Knuth
s = ''.join(data) # lists are faster than generators in this use case
# str.join makes one pass to add-up the lengths of all the string fragments
# so it knows much memory to allocate for the combined final result.
# The second pass copies the string fragments into in
# the new buffer to create a single new string.
# If the input to join isn't a list, it has to
# do extra work to build a temporary list for the two passes.
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
saved = list(iterable)
while saved:
for element in saved:
yield element
def dropwhile(predicate, iterable):
# dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
yield x
break
for x in iterable:
yield x
Please feel free to contact me.
@salman_arfat