Python can be used as a calculator since there is no need to declare types and most of the operations behave as expected (like the int division). The power operator is not ^ but **.
In [1]:
2 + 2
Out[1]:
In [2]:
3 / 2
Out[2]:
In [3]:
2 ** 8
Out[3]:
Variables can be defined freely and change type. There is a very handy print function (this is very different from Python2!). The format function can be used to customize the output. More at https://pyformat.info/
In [4]:
a = 42
b = 256
z = 2 + 3j
w = 5 - 6j
print("I multiply", a, "and", b, "and I get", a * b)
print("Compex numbers!", z + w)
print("Real:", z.real)
# Variables as objects (in Python everything is an object)
print("Abs:", abs(z))
In [5]:
almost_pi = 3.14
better_pi = 3.14159265358979323846264338327950288419716939937510
c = 299792458
print("Look at his scientific notation {:.2E} or ar this nice rounding {:.3f}".format(c, better_pi))
Note that Python does not require semicolons to terminate an instruction (but they don't harm) but require the indendation to be respected. (After for, if, while, def, class, ...)
In [6]:
for i in range(5):
if (not i%2 == 0 or i == 0):
print(i)
It's easy to work with variables of different nature. There are three kinds of structured variable: tuple (), lists [], and dicts {}. Tuples are immutable (ofter output of functions is given as a tuple). Lists are the usual arrays (multidimensional). Dictionaries are associative arrays with keywords.
In [9]:
a = 5
a = "Hello, World"
# Multiple assignation
b, c = "Hello", "World"
print(a)
print(b, c)
tuple_example = (1,2,3)
print("Tuple", tuple_example[0])
# tuple_example[1] = 3
list_example = [1,2,3]
print("List 1", list_example[0])
list_example[1] = 4
print("List 2", list_example[1])
dict_example = {'one' : 1,
'two' : 2,
'three' : 3
}
print("Dict", dict_example['one'])
Lists are very useful as most of the methods are build it, like for sorting, reversing, inserting, deleting, slicing, ...
In [10]:
random_numbers = [1,64,78,13,54,34, "Ravioli"]
print("Length:", len(random_numbers))
true_random = random_numbers[0:5]
print("Sliced:", true_random)
print("Sorted:", sorted(true_random))
print("Max:", max(true_random))
random_numbers.remove("Ravioli")
print("Removed:", random_numbers)
multi_list = ["A string", ["a", "list"], ("A", "Tuple"), 5]
print("Concatenated list", random_numbers + multi_list)
CAVEAT: List can be dangerous and have unexpected behavior due to the default copy method (like pointers pointing to the same area of memory)
In [11]:
cool_numbers = [0, 11, 42]
other_numbers = cool_numbers
print(other_numbers)
cool_numbers.append(300)
print(other_numbers)
To avoid this problem usually slicing is used.
In [13]:
cool_numbers = [0, 11, 42]
other_numbers = cool_numbers[:]
print(other_numbers)
cool_numbers.append(300)
print(other_numbers)
String are considered list and slicing can be applied on strings, with a sleek behavior with respect to indeces:
In [14]:
s = "GNU Emacs"
# No problem with "wrong" index
print(s[4:100])
# Backwards!
print(s[-9:-6])
With a for loop it is possible to iterate over lists. (But attention not to modify the list over which for is iterating!)
In [15]:
for num in cool_numbers:
print("I like the number", num)
List can generate other list via list comprehension which is a functional way to operate on a list or a subset defined by if statements.
In [16]:
numbers = [0, 1, 2, 3, 4, 5, 6, 7]
# Numbers via list comprehension
numbers = [i for i in range(0,8)]
print("Numbers:", numbers)
even = [x for x in numbers if x%2 == 0]
odd = [x for x in numbers if not x in even]
print("Even:", even)
print("Odd:", odd)
Python can have user-defined functions. There are some details about passing by reference or passing by value (what Python actually does is passing by assignment, details here: https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference). There are no return and arguments type but there is no overloading.
In [18]:
def say_hello(to = "Gabriele"):
print("Hello", to)
say_hello()
say_hello("Albert")
def sum_and_difference(a, b):
return (a + b, a - b)
(sum, diff) = sum_and_difference(10, 15)
print("Sum: {}, Diff: {}".format(sum, diff))
def usless_box(a,b,c,d,e,f):
return a,b,c,d,e,f
first, _, _, _, _, _ = usless_box(100, 0, 1, 2, 3, 4)
print(first)
A very useful construct is try-except that can be used to handle errors.
In [19]:
hey = "String"
ohi = 6
try:
print(hey/3)
except:
print("Error in hey!")
try:
print(ohi/3)
except:
print("Error in ohi!")
NOTE: Prefer this name convenction (no CamelCase) and space over tabs
There is full support to OOP with Ineheritance, Encapsulation and Polymorphism. (https://docs.python.org/3/tutorial/classes.html)
For Python there exist a huge number of modules that extend the potentiality of Python. Here are some examples:
In [20]:
# Modules have to be imported
# In this way I import thw whole module
import os
# To access an object inside the module I have to prepend the name
# In this way I import only a function but I don't have to prepend the
# module's name
from os import getcwd
print(os.getcwd())
print(getcwd())
os with Python's capability for manipulating string is a very simple way to interact with files and dir
In [21]:
dir = "test"
files = os.listdir(dir)
print(files)
# Sorting
files.sort()
print(files)
# I take the subset starting with d and not ending with 10 and that are not directories
dfiles = [f for f in files if f.startswith("d") and not f.endswith("10") and not os.path.isdir(f)]
print(dfiles)
for f in dfiles:
data = f.split("_")
n1 = data[1]
n2 = data[2]
print("From the name of the file {} I have extrected {} {}".format(f, n1, n2))
sys is another module for interactive with the system or to obtain information about it, in particular by means of the command line. argparse is a module for defining flags and arguments.
In [22]:
import sys
# sys provides the simplest way to pass command line arguments to a python script
print(sys.argv[0])
# argparse is more flexible but requires also more setup
Numpy is a module that provides a framework for numerical application. It defines new type of data highly optimized (NumPy is written in C) and provides simple interfaces for importing data from files and manipulate them. It is well integrated with the other scientific libraries for Python as it serves as base in many cases (SciPy, Matplotlib, Pandas, ...) Its fundamental object is the numpy array. With good (enough) documentation!
In [24]:
# Standard import
import numpy as np
# Array from list
num = [0,1,2]
print("List:", num)
x = np.array(num)
print("Array:", x)
y = np.random.randint(3, size = (3))
print("Random", y)
z = np.array([x,y])
print("z:", z)
print("Shape", z.shape)
zres = z.reshape(3,2)
print("z reshaped:", zres)
# Attention: numpy does not alter any object!
# Operation behave well on arrays
y3 = y + 3
print("y + 3:", y3)
print("y squared:", y**2)
# Many built-in operations
print("Scalar product:", np.dot(x,y))
# Handy way to create an equispaced array
xx = np.linspace(0, 15, 16)
print("xx:", xx)
yy = np.array([x**2 for x in xx])
print("yy:", yy)
zz = yy.reshape(4,4)
print("zz", zz)
print("Eigenvalues:", np.linalg.eigvals(zz))
NumPy offers tools for:
In [25]:
# Example: Polynomail x^2 + 2 x + 1
p = np.poly1d([1, 2, 1])
print(p)
# Evaluate it at 1
print("p(1):", p(1))
# Find the roots
print("Roots:", p.r)
# Take derivative
print("Deriv:", np.polyder(p))
Interaction with files is really simple
In [26]:
arr = np.random.random(10)
# Prints a single column file, for arrays print many columns
np.savetxt("array.dat", arr)
files = os.listdir(".")
print([f for f in files if f == "array.dat"])
data = np.loadtxt("array.dat")
print(data)
It is possible to save data compressed in a gzip by appending tar.gz to the name of the file (in this case array.dat.tar.gz).
REMEMBER:
tar cvzf archive.tar.gz foldertar xvzf archive.tar.gzMatplotlib is the tool for plotting and graphics
In [27]:
import matplotlib.pyplot as plt
plt.plot(arr)
plt.ylabel('Some numbers')
plt.xlabel('An index')
plt.title("The title!")
plt.show()
Matplotlib has a seamless integration with NumPy
In [28]:
x = np.linspace(0,2 * np.pi, 100)
y = np.sin(x)
z = np.cos(x)
plt.plot(x, y, "r-", x, z, "g-")
plt.show()
Matplotlib has a great library of examples (https://matplotlib.org/examples/) that in particular contains many of the most common plots (histograms, contour, scatter, pie, ...)
In [29]:
# Plot of the Lorenz Attractor based on Edward Lorenz's 1963 "Deterministic
# Nonperiodic Flow" publication.
# http://journals.ametsoc.org/doi/abs/10.1175/1520-0469%281963%29020%3C0130%3ADNF%3E2.0.CO%3B2
#
# Note: Because this is a simple non-linear ODE, it would be more easily
# done using SciPy's ode solver, but this approach depends only
# upon NumPy.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def lorenz(x, y, z, s=10, r=28, b=2.667):
x_dot = s*(y - x)
y_dot = r*x - y - x*z
z_dot = x*y - b*z
return x_dot, y_dot, z_dot
dt = 0.01
stepCnt = 10000
# Need one more for the initial values
xs = np.empty((stepCnt + 1,))
ys = np.empty((stepCnt + 1,))
zs = np.empty((stepCnt + 1,))
# Setting initial values
xs[0], ys[0], zs[0] = (0., 1., 1.05)
# Stepping through "time".
for i in range(stepCnt):
# Derivatives of the X, Y, Z state
x_dot, y_dot, z_dot = lorenz(xs[i], ys[i], zs[i])
xs[i + 1] = xs[i] + (x_dot * dt)
ys[i + 1] = ys[i] + (y_dot * dt)
zs[i + 1] = zs[i] + (z_dot * dt)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(xs, ys, zs, lw=0.5)
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
ax.set_title("Lorenz Attractor")
plt.show()
SciPy is a module that relies on NumPy and provides many ready-made tools used in science. Examples:
Example, minimize: $f\left(\mathbf{x}\right)=\sum_{i=1}^{N-1}100\left(x_{i}-x_{i-1}^{2}\right)^{2}+\left(1-x_{i-1}\right)^{2}.$
In [1]:
import numpy as np
from scipy.optimize import minimize
def rosen(x):
"""The Rosenbrock function"""
return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
res = minimize(rosen, x0, method='nelder-mead', options={'xtol': 1e-8, 'disp': True})
print(res.x)
Scripted!