Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Image: ubuntu2004
More Python basics
Camilo A. Garcia Trillos - 2020
In this notebook
we look at how to define and test functions, and how to think in terms of error management.
we discuss Python packages and start looking at some notable Python packages or libraries.
Function definition
Python code is better structured by defining functions.
The basic syntaxis is def name_function: --- return(---)
Let us look at a first example: we will create a function that establishes if two integers are relative primes (i.e., that their maximum common divisor is 1). We will create several iterations of the function.
Let us start with a first simple implementation:
Check with other cases that the function works as it should.
In Python, when the code within a function is executed, a new 'environment' is created. Every object/function that is defined within a function only lives within the function. So for example, tha variables x,y,z above are not accessible in the following line
However, functions can access variables and functions defined outside themselves. This is useful (as will be seen further below), but is sometimes a source of confusion (particualrly regarding variables).
In the above definition of 'rel_prime, apart from the funcional part, we included a help description. At any point this information can be retrieved with ? after the name of a function.
What happens when we test the function with values that are not integers?
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-149e970ce731> in <module>
----> 1 rel_primes(1.2,1.4)
<ipython-input-1-143c359c2d08> in rel_primes(x, y)
7
8 z = min(x,y) # Assign to z the minimum from a and b
----> 9 for i in range(2,z) : # run over all numbers between 2 and z (!)
10 if (x%i)==0 and (y%i==0): # if a number divides both a, b (i.e. the residual in both cases is zero)
11 # they are not relative primes ...
TypeError: 'float' object cannot be interpreted as an integer
Note that sometimes we get an error and sometimes we do not. Moreover, the error is not very informative of what happened. We can create our own error messages. In what follows we create a function that 'wraps' the previous one, while providing some error management.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-58e533b5cb3e> in <module>
----> 1 rel_primes2('a',123) # Here we raise an error as we defined it
<ipython-input-4-21a95bd1e322> in rel_primes2(a, b)
4
5 if type(a)!=int:
----> 6 raise TypeError("Both numbers must be integers")
7
8 if type(b)!=int:
TypeError: Both numbers must be integers
You can check that errors are raised in other cases (for example if you provide complex numbers or floats).
The other very common type of error to be raised is ValueError (i.e. raise ValueError(...)). This means that a given input has a value outside the accepted domain.
It is possible also to check if a call to a function produces an error using the keword 'try', so taht any error can be managed by the programmer. This can be useful when one wants to allow
Note that we performed 4 tests. The last one fails and illustrates that the function defined above is not working properly. When the test fails, the associated fail message is displayed.
We proceed to fix the error (which is located on the rel_prime function). Run the code below and then run the tests again.
What happened? We have fixed the error on the rel_primes function (we were not including the las element in the cycle). Since the function rel_primes2 calls rel_prime, this one gets fixed as well. This helps it pass all the tests.
Note we have learnt something very important in addition: in jupyter, code depends on the order of execution, not the order in which the code is written.
Remark: In more professional settings, the preferred form of testing is via unittesting. If you want to learn more about it, read the Python documentation on unittest
Lambda functions
We had seen that to define a function in Python, we use the command def followed by the name of the function, arguments and colon. There is an alternative in the form of lambda functions, that is useful to define inline functions.
The syntax is *name_function = lambda (vars): operations *
Here is an example where we implement the same function twice.
Lambda functions are very convenient for short tasks. In particular it is an easy way to encapsulate one line instructions in a function. Note, though that it is very hard
Some final observations:
Functions are not forced to return a value (sometimes these are called procedures)
More testing tools are provided on the [package](## 2. Packages) unitest
Python comes with many functions already defined. Some of them come as part of the standard language (we have encountered some of them). However, the real power of Python comes from sets of functions put together in packages.
Here are some of the ones we will use in this course (and are very useful in finance):
math : some mathematical functions
numpy : vector and matrix capabilities and operations
scipy : numerical scientific computing including integration, fixed points, solving ODEs, optimisation, …)
matplotlib : plots
pandas : database access and manipulation, and more plots routines
statutils: Some statistical tools including test of hypothesis
Some packages we will not use but sare very useful in finance include:
keras: Keras is a high-level neural networks library
sklearn: A library with tools for data mining and data analysis
Here and in the nest notebook, we look at numpy and math. We will learn about the following packages while making applications ion finance.
Packages must be imported into the kernel we are excuting. By convention all imports should be done at the start of the program, and in the Jupyter case at the start of the notebook.
After running the above code, we can use all functions on the math package. Here are some examples:
Some examples with numpy
Let us now look at numpy. Numpy is a scientific library taht has been optimised to perform vector and matrix operations.
We start by looking at how to create numpy objects. We can either transform another structure (for example a list) using the function array, or wwe can use one of the functions producing directly an array. Here are some examples:
Note that the above objects are of class array, which was defined in the package numpy. Observe also how the result is printed if no print function is invoked.
Let us look at some simple operations before arrays:
Note the difference with respect to lists: the operator + means vector addition. Note also that most operations like '*' and '/' are defined pointwise.
Since operations are mostly pointwise, the sizes of vectors need to coincide or an error will be raised.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-15-7b6584d97316> in <module>
1 a2 = np.arange(10)
2 print(a2,b)
----> 3 a2*b # This raises an error
ValueError: operands could not be broadcast together with shapes (10,) (3,)
We also have some vector and matrix operations. We can, for example, find the dot product of two vectors of the same size with the operator @
We will frequently make use of the possibility to generate (pseudo) random numbers following some given distributions. Numpy allows for this through its sub-module random. We can generate (pseudo-)random arrays and matrices of a given size. Here are some examples using the current prefered way of calling the generator function.
This produces arrays in dimension 2 or matrices. We can also see the second use of operator '@': matrix (and matrix-vector) multiplication:
The random generator can produce samples from different distributions: look at the help for rng.normal, rng.lognormal, rng.exponential....
Remark: Once imported, we can make use of numpy functions within our function definitions. We can also import a module within a function definition, however in that case, the imported modules are available only within that function.
Exercises
Create a function that receives a positive integer and a probability , and returns the mean and standard deviation of a binomial distribution with these parameters. Your function must raise errors whenever the probability is outside the given range and if that the number n is not and integer greater than 0. Use the statement assert to test your function on some known cases.
Using np.rand, create a function that receives a positive integer and a probability , and returns an array with bernoulli trials with parameter . Your function must raise errors whenever the probability is outside the given range and if that the number n is not and integer greater than 0.
Using the previous function, estimate the empirical mean and variance for n=[10,100,1000,10000]. Comment.