by: James Powell (http://seriously.dontusethiscode.com/)
In [21]:
def gen(x):
yield x+1
yield x+2
for x in gen(11):
print(x)
Two things we do in python:
Generator expressions look like tuple comprehensions
In [28]:
gener1 = (x for x in range(4))
print(gener1)
for x in gener1:
print(x)
def gener2(length):
for x in range(length):
yield x
print(gener2)
for x in gener2(4):
print(x)
An Iterator is merely an iterable and state that remembers where we were.
You can think of a generator as a delayed computation; you only get results as you ask for them. Infinite lists!
Calling a generator will run it until the first yield, then it pauses until it's called again.
gi.next() == gi.send(None)
Generators are generally used for efficiency purposes
Context Managers are a good wrapper around opening files
don't:
f = open('file.txt')
lines = [line for line in f.readline()]
f.close()
print(lines)
do:
with open('file.txt') as f:
lines = [line for line in f.readline()]
print(lines)
watch out for resource leakage, though
Use sorted() instead of [].sort()
namedtuple has the same memory footprint as the equivalent tuple
you can do attribute lookup in string formatting:
In [ ]:
class Foo(object):
def __init__(self, x, y):
self.x, self.y = x, y
def __repr__(self):
return 'Foo({0.x}, {0.y})'.format(self)
In [17]:
from collections import defaultdict
x = defaultdict(int) # calling int() gives you 0
print("int() == {}".format(int()))
x['a'] = 1
In [18]:
print(x)
In [19]:
print("x['a'] == {}".format(x['a']))
print("x['b'] == {}".format(x['b']))
In [20]:
default = lambda: None
y = defaultdict(default)
print(y['one'])
y['one'] = 'hello'
print(y['one'])
print(y)