from IPython.display import HTML, Image
HTML(open("notes.css", "r").read())
Here are some relatively new Python features you may find useful.
In Python, the "=" is used for the assignment statement:
x = 2 + 2
but you want to assign a value and use it in an expression at the same time, you can't:
# uncomment to see exception
#if x = 2 + 2:
# print(x)
The ":=
" operator, however, lets you do this:
if x := 2 + 2:
print(x)
(See if this allows you to define new variables within your spreadsheet!)
Python does not require type declarations. However, it does permit type annotations. We touched on these when we talked about documentation:
%%file demos/d0_annotation/polar.py
"""
The ``polar`` Module
"""
from math import sin, cos, atan2, pi
__version__ = "1.1"
class Polar:
"""
specifies a 2D position or velocity in polar coordinates
This class represents a 2D position or velocity measured in polar
coordinates and defined by its `distance` (or speed) and an angle
(`bearing`) (in radians) from the positive y ('North') direction.
We follow the conventions of navigation, not mathematics, so 0
degrees is North and bearings increase in a clockwise fashion.
"""
DEGREES_TO_RADIANS = pi / 180
"multiplicative constant to convert degrees to radians"
#: multiplicative constant to convert radians to degrees
RADIANS_TO_DEGREES = 180 / pi
def __init__(self,
distance: float = 0.0 ,
bearing: float = 0.0) -> None:
"""
specifies a polar point by `distance` and `bearing`
"""
self.distance = distance
self.bearing = bearing
def __add__(self, other: 'Polar') -> 'Polar':
"""
returns the result of adding two Polar
"""
(x0, y0) = self.rect()
(x1, y1) = other.rect()
dx = x1 + x0
dy = y1 + y0
mag = (dx**2 + dy**2)**0.5
return Polar(mag, atan2(dy, dx) if mag > 0 else 0)
def __repr__(self) -> str:
"""
returns a 'lossless' string representation of a PolarCoordinate
"""
return "Polar({}, {})".format(self.distance, self.bearing)
def rect(self) -> (float, float):
"""
returns the rectangular (Cartesian) coords as an (x, y) tuple
"""
return (self.distance*sin(self.bearing),
self.distance*cos(self.bearing))
if __name__ == '__main__':
# test1: with a 3-4-5 right triangle
a = Polar(3, 0)
print(' a:', a)
b = Polar(4, pi/2)
print(' b:', b)
print('a+b:', a+b)
# test2: zero relative distance
c = Polar(2, Polar.DEGREES_TO_RADIANS * 30)
print(' c:', c)
d = Polar(2, Polar.DEGREES_TO_RADIANS * 210)
print(' d:', d)
print('c+d:', c+d)
Note how we insert annotations into the code (more than the original).
%%sh
cd demos/d0_annotation
make clean # to force rebuild for demo purposes
make html
chromium _build/html/index.html
You can also add annotations to assignment statements:
x:float = 3.4**2
This might help code readability, but it doesn't affect documentation. So far, we've only used annotations for documentation, but lately Python developers have gone a little farther...
Here's a talk on the subject from PyCon 2018. (Other videos recommended.)
These are a subset of tuples whose members have names. They borrow from classes and tuples and take the place of some of what people use dictionaries for.
from collections import namedtuple
Student = namedtuple('Student', ['firstName', 'lastName', 'year'])
jcleese = Student('John', 'Cleese', 2020)
jcleese
for elem in jcleese:
print(elem)
jcleese.firstName
Python virtual environments allow you to install multiple versions of Python and (for instance) experimental versions of modules in a way that isolates them from the rest of your system. It's like a container (e.g. "docker"), but not quite so isolated.
TBD
PyPy
provides a "just in time" compiler (not interpreter) for Python code. (Java has had one for many years.)
TBD