- Also Corey Shafer Channel.

Use `reversed`

:

colors = ['red', 'green', 'blue'] for color in reversed(colors): print(color)

Use `enumerate`

:

colors = ['red', 'green', 'blue'] for i, color in enumerate(colors): print("{} -> {}".format(i, color))

names = ['raymond', 'rachel', 'matthew'] colors = ['red', 'green', 'blue', 'yellow'] for name, color in zip(names,colors): print("{} -> {}".format(name, color))

Note that the lengths are different.

Use `sorted`

:

colors = ['red', 'green', 'blue'] for color in sorted(colors): print(color)

To sort by length:

colors = ['red', 'green', 'blue'] for color in sorted(colors, key=len): print(color)

Python's `break`

only breaks out of *one* loop. To break out from two, make it a single loop. So:

for x in range(width): for y in range(height): <do something>

Create a range:

def range_2d(width, height): for x in range(width): for y in range(height): yield x, y

Then, you can do:

for x, y in range_2d(width, height): <do something>

Instead of:

for i in v: for j in w: <do something>

you can do

it = ( (i,j) for i in v for j in w ) # creates a GENERATOR for i,j in it: <do something>

d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'} for k in d: print k

If you want to change the dictionary while you loop, loop over `d.keys()`

:

for k in d.keys(): if k.startswith('r'): del d[k]

for v in d.values() <do stuff>

for key, value in d.items() print("{} --> {}".format(key, value))

d = dict(zip(names, colors))

Use `d.get`

. `d.get(item,0)`

gives `d[item]`

if possible and `0`

otherwise.

d = {} v = [0,0,0,1,1,1,1,1,1,2,2,0,2,1] for x in v: d[x] = d.get(x,0) + 1

There is also `d.setdefault(key, default_value)`

, which also creates the `d[key]`

if it does not exist already.

One can also use `defaultdict(type)`

, which creates an “empty” dictionary with values of `type`

.

For instance, to create a dictionary grouping stings of `names`

by length:

from collections import defaultdict d = defaultdict(list) for name in names: key = len(name) d[key].append(name)

If `key`

does not exist, it creates it and sets the default value for `list`

, which is an empty list. (And for `int`

it is `0`

.)

v = [ 'a', 'b', 'c', 'd' ] w = [ 1, 2, 3, 4 ] my_dict = { letter : number for letter, number in zip(v,w) if number != 2 }

gives `my_dict`

as `{ 'a' : 1, 'c' : 3, 'd' : 4 }`

.

Use `*`

for optional arguments with no default value.

def my_fct(x, *v): print('First value is {}'.format(x)) if v: # runs if v is not empty print('The other values are:') for value in v: print(value)

You can call it with `my_fct(3)`

, `my_fct(3,4)`

, `my_fct(3,4,5)`

, etc.

Also, if `v = [1, 2]`

, then `my_fct(3,*v)`

is the same as `my_fct(3,1,2)`

.

In **Python 3**, if

def f(x, y, *, z=0, w=1): return x+y+z+w

you *cannot* call it as `f(1,2,3,4)`

, you must call it with `f(1,2,x=3,w=4)`

, i.e., the keyword arguments must be entered as keywords.

Instead of

def f(x,y): return x + y

do

f = lambda x, y: x + y

If `v`

is a list and `f`

is a function, then

fv = map(f,v)

applies `f`

to entries of `v`

. In **Python 3** it is iterable. (To make a list, do `fv = list(map(v))`

.)

Now if `test`

is a conditional function,

testv = filter(test,v)

gives only the elements of `v`

satisfying `test`

. Similar to

testv = [ x in v if test(x) ]

but in **Python 3** it gives an iterable, not a list.

You can use the `else`

part of a for loop. So, instead of

def find(seq, target): found = False for i, value in enumerate(seq): if value == target: found = True break if not found: return -1 return i

do

def find(seq, target): for i, value in enumerate(seq): if value == target: found = True break else: return -1 return i

The `else`

is like a `nobreak`

: if the look finished normally, it skips the `else`

part. If there is a break in the look, it runs the `else`

part.

To save functions from recomputing the same value (with the expense of saving the computed values in memory) is to use`@cache`

. So, instead of:

def my_fct(x, saved={}): if x in saved: return saved[x] <compute result> saved[x] = result return result

do

@cache def my_fact(x): <compute result> return result

Instead of:

f = open('data.txt') try: data = f.read() finally: f.close()

do

with open('data.txt') as f: data = f.read()

Instead of

sum([i**2 for i in range(10)])

do

sum(i**2 for i in range(10))

from collections import namedtuple Color = namedtuple('Color',['hue', 'saturation', 'luminosity']) p = Color(170, 0.1, 0.6) if p.saturation > 0.5: print('Bright!') if p.luminosity > 0.5: print('Light!')

See also: https://www.geeksforgeeks.org/namedtuple-in-python/

If you want to loop over the squares of integers from 1 to 1000, instead of creating the list

[ i**2 for i in range(1,1001)]

and looping, create the generator/iterator:

( i**2 for i in range(1,1001))

It's better in most cases to return generators/iterators instead of lists. So instead of:

def cubes(n): res = [] for i in range(n): res.append(i**3) return res

you can do

def cubes(n): for i in range(n): yield i**3

We can make it a list if we want to with `list(cubes(10))`

, but we can use to iterate (**only once** per call), like:

for i in cubes(10): <do something with i>

Or, to extract the first three elements:

c = cubes(100000) next(c) next(c) next(c)

x = 1 if <condition> else 0

number = 100000000 print('The number is {:,}'.format(number))

a, b, c = (1, 2, 3, 4, 5)

gives an error. In **Python 3** we can do

a, b, *c = (1, 2, 3, 4, 5)

gives an `a = 1`

, `b = 2`

, `c = [3, 4, 5]`

.

a, b, *_ = (1, 2, 3, 4, 5)

gives an `a = 1`

and `b = 2`

.

a, b, *c, d = (1, 2, 3, 4, 5)

gives an `a = 1`

, `b = 2`

, `c = [3, 4]`

, and `d = 5`

.

The following values are treated as False: `“”`

(empty string), `0`

, `0.0`

, `[]`

(empty list), `()`

(empty tuple), `{}`

(empty dictionary), `False`

, `None`

. If `variable`

then is any of those, then

if variable: print('OK')

will *not* print `OK`

, but will otherwise.

You cannot create and empty set wit `my_set = {}`

as it creates an empty *dictionary*. So, you do it with `my_set = set()`

.

This also works for lists, tuples or dictionaries:

empty_list = [] empty_list = list() empty_tuple = () empty_tuple = tuple() empty_dict = {} empty_dict = dict()