From Raymond Hettinger's Transforming Code into Beautiful, Idiomatic Python
Whenever you're manipulating indices directly, you're probably doing it wrong
for i in [0, 1, 2, 3, 4, 5]:
print i**2
# the python way
# range() takes a small amount of memory because it calculates individual items as needed
for i in range(6):
print i**2
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print colors[i]
# the python way
for color in colors:
print color
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)-1, -1, -1):
print colors[i]
# the python way
for color in reversed(colors):
print color
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print i, '-->', colors[i]
# the python way
for i, color in enumerate(colors):
print i, '-->', color
zip(*iterables): Makes an iterator that aggregates elements from each of the iterables.
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue', 'yellow']
n = min(len(names), len(colors))
for i in range(n):
print names[i], '-->', colors[i]
# the python way
for name, color in zip(name, colors):
print name, '-->', color
itertools.product(*iterables, repeat=1): Cartesian product of input iterables.
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue', 'yellow']
for name in names:
for color in colors:
print(name, color)
# the python way
from itertools import product
products = product(names, colors)
for name, color in products:
... print(name, color)
sorted(iterable[, key][, reverse])
colors = ['red', 'green', 'blue', 'yellow']
for color in sorted(colors):
print color
# reverse order
for color in sorted(colors, reverse=True):
print color
# custom order
for color in sorted(colors, key=len):
print color
As soon as you've made something iterable, it works with all of the Python toolkit
iter(object[, sentinel]) functools.partial(func, *args, **keywords)
# sentinel value the traditional way
blocks = []
while True:
block = f.read(32)
if block = '':
break
blocks.append(block)
# the second argument of the iter function is a sentinel value
# in order to make it work, the first function has to be a function with no arguments, hence the partial
blocks = []
for block in iter(partial(f.read, 32), ''):
blocks.append(block)
The for loop else should have been called nobreak
def find(seq, target):
found = False
for i, value in enumerate(seq):
if value == tgt:
found = True
break
if not found:
return -1
return i
def find(seq, target):
for i, value in enumerate(seq):
if value == tgt:
break
else:
return -1
return i
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k in d:
print k
for k in d.keys():
if k.startswith('r'):
del d[k]
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k in d:
print k, '-->', d[k]
# the python way
for k, v in d.items():
print k, '-->', v
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue', 'yellow']
d = dict(zip(names, colors))
class collections.defaultdict([default_factory[, ...]])
colors = ['red', 'green', 'red', 'blue', 'green', 'red']
d = {}
for color in colors:
if color not in d:
d[color] = 0
d[color] += 1
d = {}
for color in colors:
d[color] = d.get(color, 0) + 1
# the python way
d = defaultdict(int)
for color in colors:
d[color] += 1
names = ['raymond', 'rachel', 'matthew', 'roger', 'betty', 'melissa', 'judith', 'charlie']
d = {}
for name in names:
key = len(name)
if key not in d:
d[key] = []
d[key].append(name)
d = {}
for name in names:
key = len(name)
d.setdefault(key, []).append(name)
# the python way
d = defaultdict(list)
for name in names:
key = len(name)
d[key].append(name)
popitem() is atomic so it can be used bewteen threads
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
while d:
key, value = d.popitem()
print key, '-->', value
defaults = {'color': 'red', 'parser': 'guest'}
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args([])
command_line_args = {k: v for k, v in vars(namespace).items() if v}
d = default.copy()
d.update(os.environ)
d.update(command_line_args)
# the python way
d = ChainMap(command_line_args, os.environ, defaults)
twitter_search('@obama', False, 20, True)
# the python way
twitter_search('@obama', retweets=False, numtweets=20, popular=True)
doctest.testmod()
# output: (0, 4)
TestResults = namedtuple('TestResults', ['failed', 'attempted'])
doctest.testmod()
# output: TestResults(failed=0, attempted=4)
p = 'Raymond', 'Hettinger', 0x30, '[email protected]'
fname = p[0]
lname = p[1]
age = p[2]
email = p[3]
# the python way
fname, lname, age, email = p
def fibonacci(n):
x = 0
y = 1
for i in range(n):
print x
t = y
y = x + y
x = t
# the python way
def fibonnaci(n):
x, y = 0, 1
for i in range(n):
print x
x, y = y, x + y
names = ['raymond', 'rachel', 'matthew', 'roger', 'betty', 'melissa', 'judith', 'charlie']
s = names[0]
for name in name[1:]:
s += ', ' + name
print s
# the python way
', '.join(names)
names = ['raymond', 'rachel', 'matthew', 'roger', 'betty', 'melissa', 'judith', 'charlie']
# whenever you use this you should be using a deque instead
del names[0]
names.pop(0)
names.insert(0, 'mark')
names = deque(['raymond', 'rachel', 'matthew', 'roger', 'betty', 'melissa', 'judith', 'charlie'])
del names[0]
names.popleft()
names.appendleft('mark')
@functools.lru_cache(maxsize=128, typed=False)
def web_lookup(url, saved={}):
if url in saved:
return saved[url]
page = urllib.urlopen(url).read()
saved[url] = page
return page
# the python way
@lru_cache
def web_lookup(url):
return urllib.urlopen(url).read()
Anytime your setup and teardown logic get repeated in your code you want a context manager to improve it
old_context = getcontext().copy()
getcontext().prec = 50
print Decimal(355) / Decimal(113)
setcontext(old_context)
# the python way
with localcontext(Context(prec=50)):
print Decimal(355) / Decimal(113)
try:
os.remove('somefile.tmp')
except OSError:
pass
# the python way
@contextlib.contextmanager
def ignored(*exceptions):
try:
yield
except exceptions:
pass
with ignored(OSError):
os.remove('somefile.tmp')
One logical line of code equals one sentence in English
data = [1, 2, 3, 4]
if any(x > 3 for x in data):
print('Un élément est supérieur à 3')