In [1]:
name = '2017-10-30-pythonic-code'
title = 'Writing Pythonic code'
tags = 'basics'
author = 'Denis Sergeev'
In [2]:
from nb_tools import connect_notebook_to_post
from IPython.core.display import HTML
html = connect_notebook_to_post(name, title, tags, author)
In [3]:
import this
import my_module_name
from foo import bar
# constant, not changed at runtime
MODEL_GRID = 'cartesian'
def calculate_something(data):
"""Compute some parameters"""
# ...
return result
class ModelDomain(object):
"""
Very long description...
Attributes: ...
Parameters: ...
"""
def __init__(self, name='', description='', bounds=None, mask_bounds=None):
self.name = name
self.description = description
# something else...
def mask_var(self, data):
"""Mask the data of the given variable outside the region."""
return data.where(self.mask_bounds, data)
class MyDescriptiveError(Exception):
pass
In [4]:
if []:
print('this is false')
In [5]:
False # false is false
[] # empty lists
{} # empty dictionaries or sets
"" # empty strings
0 # zero integers
0.00000 # zero floats
None # None (but not zero)
Thuthiness is defined by __bool__() method
In [6]:
class MyClass:
def __init__(self, data):
self.data = data
def __bool__(self):
if len(self.data) > 0:
return True
else:
return False
In [7]:
foo = MyClass(data=[1, 2, 3])
In [8]:
if foo:
print('it contains some data')
else:
print('no data')
What's the pythonic way?
In [9]:
vrbl = True
In [10]:
if vrbl:
# NO: if condtion == True
print('do something')
Don't be this guy:
In [11]:
def test_if_greater_than_ten(x):
return True if x>10 else False
In [12]:
test_if_greater_than_ten(11)
Out[12]:
In [13]:
def fun():
print('blah')
In [14]:
x = fun
In [15]:
x()
In [16]:
type(x)
Out[16]:
In [17]:
callable(x)
Out[17]:
In [18]:
isinstance(12345, (int, float))
Out[18]:
if something is None:
print('no results')
else:
print('here are some results')
negation:
if something is not None:
print('Option A')
else:
print('Option B')
In [19]:
my_axis = 'x'
In [20]:
if my_axis in ('x', 'y'):
# Instead of writing like that:
# if my_axis == 'x' or my_axis == 'y'
print('horizontal')
elif my_axis == 'z':
print('vertical')
Sometimes can be a bit slower if used inside a long loop.
In [21]:
a = [1,2,3]
How to check if the variable is a list or dictionary?
In [22]:
import numpy as np
In [23]:
a = np.arange(10)
In [24]:
isinstance(a, np.ndarray)
Out[24]:
In [25]:
the_variable = [1, 2, 3, 4]
another_variable = "This is my string. There are many like it, but this one is mine."
and_another_variable = 1000000000000
In [26]:
for i in another_variable[:10]:
# iterate over the first 10 elements and print them
print(i)
In [27]:
import collections
In [28]:
if isinstance(1234563645, collections.Iterable):
# iterable
print('It is iterable')
else:
# not iterable
print('It is NOT iterable')
Similar way, by checking the methods:
In [29]:
hasattr(the_variable, '__iter__')
Out[29]:
Another way: duck-typing style
Pythonic programming style that determines an object's type by inspection of its method or attribute signature rather than by explicit relationship to some type object ("If it looks like a duck and quacks like a duck, it must be a duck.") By emphasizing interfaces rather than specific types, well-designed code improves its flexibility by allowing polymorphic substitution. Duck-typing avoids tests using type() or isinstance(). Instead, it typically employs the EAFP (Easier to Ask Forgiveness than Permission) style of programming.
try:
for i in the_variable:
# ...
except TypeError:
print(the_variable, 'is not iterable')
In [30]:
day = 30
month = 'October'
won't work, because Python does not automatically convert to str:
print('Today is ' + month + ', ' + day)
Works, but not pythonic:
In [31]:
print('Today is ' + month + ', ' + str(day))
In [32]:
print('Today is {}, {}'.format(month, day))
In [33]:
print('Today is {1}, {0}'.format(month, day))
In [34]:
print('Today is {1}, {0}. Tomorrow will be still {0}'.format(month, day))
In [35]:
print('Today is {m}, {d}. Tomorrow will be still {m}. And again: {d}'.format(m=month, d=day))
In [36]:
data = {'dow': 'Monday', 'location': 'UEA', 'who': 'Python Group'}
In [37]:
print('Today is {dow}. We are at {location}.'.format(**data))
Just pulling variables from the namespace!
In [38]:
print(f'Today is {day}th. The month is {month}')
In [39]:
# print(f'Today is {data["dow"]}. We are at {data["location"]}')
In [40]:
HTML(html)
Out[40]: