Basic Introduction to Python

This is a very basic introduction to Python. It is not exhaustive, but is meant to give you a starting point.

This notebook was written for PHY 403 by Segev BenZvi, University of Rochester, (Spring 2016).

It is based on a similar (longer) Python guide written by Kyle Jero (UW-Madison) for the IceCube Programming Bootcamp in June 2015, and includes elements from older guides by Jakob van Santen and Nathan Whitehorn.

What is Python?

Python is an imperative, interpreted programming language with strong dynamic typing.

  • Imperative: programs are built around one or more subroutines known as "functions" and "classes"
  • Interpreted: program instructions are executed on the fly rather than being pre-compiled into machine code
  • Dynamic Typing: data types of variables (int, float, string, etc.) are determined on the fly as the program runs
  • Strong Typing: converting a variable from one type to another (e.g., int to string) is not always done automatically

Python offers fast and flexible development and can be used to glue together many different analysis packages which have "Python bindings."

As a rule, Python programs are slower than compiled programs written in Fortran, C, and C++. But it's a much more forgiving programming language.

Why Use Python?

Python is one of the most popular scripting languages in the world, with a huge community of users and support on all major platforms (Windows, OS X, Linux).

Pretty much every time I've run into a problem programming in Python, I've found a solution after a couple of minutes of searching on google or stackoverflow.com!

Key Third-Party Packages

Must-Haves

  • NumPy: random number generation, transcendental functions, vectorized math, linear algebra.
  • SciPy: statistical tests, special functions, numerical integration, curve fitting and minimization.
  • Matplotlib: plotting: xy plots, error bars, contour plots, histograms, etc.
  • IPython: an interactive python shell, which can be used to run Mathematica-style analysis notebooks.

Worth Using

  • SciKits: data analysis add-ons to SciPy, including machine learning algorithms.
  • Pandas: functions and classes for specialized data analysis.
  • AstroPy: statistical methods useful for time series analysis and data reduction in astronomy.
  • Emcee: great implementation of Markov Chain Monte Carlo; nice to combine with the package Corner.

Specialized Bindings

Many C and C++ packages used in high energy physics come with bindings to Python. For example, the ROOT package distributed by CERN can be run completely from Python.

Online Tools

If you don't want to install all these packages on your own computer, you can create a free account at wakari.io.

Wakari gives you access to ipython notebooks running on remote servers. Recent versions of SciPy, NumPy, and Matplotlib are provided.

Programming Basics

We will go through the following topics, and then do some simple exercises.

  • Arithmetic Operators
  • Variables and Lists
  • Conditional Statements
  • Loops (for and while)
  • Functions
  • Importing Modules

Arithmetic Operators

Addition

In [1]:
1+2
Out[1]:
3

Subtraction

In [2]:
4 - 1
Out[2]:
3

Multiplication

In [3]:
3*8
Out[3]:
24

Division

In [4]:
50 / 2
Out[4]:
25
In [5]:
1 / 2
Out[5]:
0

Note: in Python 2, division of two integers is always floor division. In Python 3, 1/2 automatically evaluates to the floating point number 0.5. To use floor division in Python 3, you'll have to run 1 // 2.

In [6]:
1.0000000 / 2
Out[6]:
0.5
In [7]:
float(1) / 2
Out[7]:
0.5

Modulo/Remainder

In [8]:
30 % 4
Out[8]:
2
In [9]:
3.14159265359 % 1.
Out[9]:
0.14159265359000006

Exponentiation

In [10]:
2**4
Out[10]:
16

Variables

Variables are extremely useful for storing values and using them later. One can declare a variable to contain the output of any variable, function call, etc. However, variable names must follow certain rules:

  1. Variable names must start with a letter (upper or lower case) or underscore
  2. Variable names may contain only letters, numbers, and underscores _
  3. The following names are reserved keywords in Python and cannot be used as variable names:

    and del from not while

    as elif global or with

    assert else if pass yield

    break except import print

    class exec in raise

    continue finally is return

    def for lambda try

In [18]:
x = 5 + 6

This time nothing printed out because the output of the expression was stored in the variable x. To see the value we have to call the print function:

In [19]:
print(x)
11

Alternatively, just call x and the notebook will evaluate it and dump the value to the output:

In [20]:
x
Out[20]:
11

Recall that we don't have to explicitly declare what type something is in python, something that is not true in many other languages, we simply have to name our variable and specify what we want it to store. However, it is still nice to know the types of things sometimes and learn what types python has available for our use.

In [21]:
print(type(x))
<type 'int'>
In [22]:
y = 2
print(type(x/y))
<type 'int'>
In [23]:
z = 1.
print(type(z/y))
<type 'float'>
In [24]:
h = 'Hello'
print(type(h))
<type 'str'>
In [25]:
s = " "
w = "World!"

print(h + s + w)
Hello World!
In [26]:
apostrophes="They're "
quotes='"hypothetically" '
saying=apostrophes + quotes + "good for you to know."

print(saying)
They're "hypothetically" good for you to know.

C-style formatted printing is also allowed:

In [27]:
p = "Pi"
print("%s = %.3f" % (p, 3.14159265359))
Pi = 3.142

Lists

Imagine that we are storing the heights of people or the results of a random process. We could imagine taking and making a new variable for each piece of information but this becomes convoluted very quickly. In instances like this it is best to store the collection of information together in one place. In python this collection is called a list and can be defined by enclosing data separated by commas in square brackets. A empty list can also be specified by square brackets with nothing between them and filled later in the program.

In [28]:
blanklist=[]
blanklist
Out[28]:
[]
In [29]:
alist=[1,2,3]
print(alist)
print(type(alist))
[1, 2, 3]
<type 'list'>

Notice that the type of our list is list and no mention of the data type it contains is made. This is because python does not fuss about what type of thing is in a list or even mixing of types in lists. If you have worked with nearly any other language this is different then you are used to since the type of your list must be homogeneous.

In [30]:
blist=[1, "two", 3.0]
blist
Out[30]:
[1, 'two', 3.0]
In [31]:
print(type(blist))
<type 'list'>

You can check the current length of a list by calling the len function with the list as the argument:

In [32]:
len(blist)
Out[32]:
3

In addition, you can add objects to the list or remove them from the list in several ways:

In [33]:
blist.append("4")
blist
Out[33]:
[1, 'two', 3.0, '4']
In [34]:
blist.insert(0, "0")
blist
Out[34]:
['0', 1, 'two', 3.0, '4']
In [35]:
blist.extend([5,6])
print(blist)
print(len(blist))
['0', 1, 'two', 3.0, '4', 5, 6]
7
In [36]:
blist.append(7)
blist
Out[36]:
['0', 1, 'two', 3.0, '4', 5, 6, 7]
In [37]:
blist = blist*2
blist
Out[37]:
['0', 1, 'two', 3.0, '4', 5, 6, 7, '0', 1, 'two', 3.0, '4', 5, 6, 7]
In [38]:
blist.remove("4")
blist
Out[38]:
['0', 1, 'two', 3.0, 5, 6, 7, '0', 1, 'two', 3.0, '4', 5, 6, 7]
In [39]:
blist.remove('4')
blist
Out[39]:
['0', 1, 'two', 3.0, 5, 6, 7, '0', 1, 'two', 3.0, 5, 6, 7]
List Element Access

Individual elements (or ranges of elements) in the list can be accessed using the square bracket operators [ ]. For example:

In [40]:
print(blist[0])
print(blist[4])
0
5
In [41]:
print(blist[-1])
print(blist[-2])
print(blist[-3])
7
6
5
In [42]:
blist[0:4]
Out[42]:
['0', 1, 'two', 3.0]
In [43]:
print(blist)   # list slicing example:
blist[0:6:2]   # sytax: start, stop, stride
['0', 1, 'two', 3.0, 5, 6, 7, '0', 1, 'two', 3.0, 5, 6, 7]
Out[43]:
['0', 'two', 5]

This is an example of a slice, where we grab a subset of the list and also decide to step through the list by skipping every other element. The syntax is

listname[start:stop:stride]

Note that if start and stop are left blank, the full list is used in the slice by default.

In [44]:
blist[::2]
Out[44]:
['0', 'two', 5, 7, 1, 3.0, 6]
In [45]:
print(blist[::-1])   # An easy way to reverse the order of elements
print(blist)
[7, 6, 5, 3.0, 'two', 1, '0', 7, 6, 5, 3.0, 'two', 1, '0']
['0', 1, 'two', 3.0, 5, 6, 7, '0', 1, 'two', 3.0, 5, 6, 7]

A simple built-in function that is used a lot is the range function. It is not a list but returns one so we will discuss it here briefly. The syntax of the function is range(starting number, ending number, step size ). All three function arguments are required to be integers with the ending number not being included in the list. Additionally the step size does not have to be specified, and if it is not the value is assumed to be 1.

In [46]:
range(0,10)
Out[46]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [47]:
range(0,10,2)
Out[47]:
[0, 2, 4, 6, 8]

Conditional Statements

Conditionals are useful for altering the flow of control in your programs. For example, you can execute blocks of code (or skip them entirely) if certain conditions are met.

Conditions are created using if/elif/else blocks.

For those of you familiar with C, C++, Java, and similar languages, you are probably used to code blocks being marked off with curly braces: { }

In Python braces are not used. Code blocks are indented, and the Python interpreter decides what's in a block depending on the indentation. Good practice (for readability) is to use 4 spaces per indentation. The IPython notebook will automatically handle the indentation for you.

In [48]:
x = 55

if x > 10:
    print("x > 10")
elif x > 5:
    print("x > 5")
else:
    print("x <= 5")
x > 10
In [49]:
isEven = (x % 2 == 0)    # Store a boolean value

if not isEven:
    print("x is odd")
else:
    print("x is even")
x is odd

Comparison Operators

There are several predefined operators used to make boolean comparisons in Python. They are similar to operators used in C, C++, and Java:

== ... test for equality

!= ... test for not equal

> ... greater than

>= ... greater than or equal to

< ... less than

<= ... less than or equal to

Combining Boolean Values

Following the usual rules of boolean algebra, boolean values can be negated or combined in several ways:

Logical AND

You can combine two boolean variables using the operator && or the keyword and:

In [50]:
print("x  y  |  x && y")
print("---------------")

for x in [True, False]:
    for y in [True, False]:
        print("%d  %d  |  %d" % (x, y, x and y))
x  y  |  x && y
---------------
1  1  |  1
1  0  |  0
0  1  |  0
0  0  |  0
In [51]:
x = 10
if x > 2 and x < 20:
    print(x)
10
In [52]:
if x < 2 and x > 20:
    print(x)
Logical OR

You can also combine two boolean variables using the operator || or the keyword or:

In [53]:
print("x  y  |  x || y")
print("---------------")

for x in [True, False]:
    for y in [True, False]:
        print("%d  %d  |  %d" % (x, y, x or y))
x  y  |  x || y
---------------
1  1  |  1
1  0  |  1
0  1  |  1
0  0  |  0
In [54]:
x = 10
if x > 2 or x < 0:
    print(x)
10
In [55]:
if x < 2 or x > 20:
    print(x)
Logical NOT

It's possible to negate a boolean expression using the keyword not:

In [56]:
print("x  | not x")
print("----------")
for x in [True, False]:
    print("%d  |  %d" % (x, not x))
x  | not x
----------
1  |  0
0  |  1

A more complex truth table demonstrating the duality

$\overline{AB} = \overline{A}+\overline{B}$:

In [57]:
print("A  B  |  A and B  |  !(A and B)  | !A or !B")
print("-------------------------------------------")
for A in [True, False]:
    for B in [True, False]:
        print("%d  %d  |  %-7d  |  %-12d|  %d" % 
              (A, B, A and B, not (A and B), not A or not B))
A  B  |  A and B  |  !(A and B)  | !A or !B
-------------------------------------------
1  1  |  1        |  0           |  0
1  0  |  0        |  1           |  1
0  1  |  0        |  1           |  1
0  0  |  0        |  1           |  1

Loops

Loops are useful for executing blocks of code as long as a logical condition is satisfied.

Once the loop condition is no longer satisfied, the flow of control is returned to the main body of the program. Note that infinite loops, a serious runtime bug where the loop condition never evaluates to False, are allowed, so you have to be careful.

While Loop

The while loop evaluates until a condition is false. Note that loops can be nested inside each other, and can also contain nested conditional statements.

In [58]:
i = 0
while i < 10:         # Loop condition: i < 10
    i += 1            # Increment the value of i
    if i % 2 == 0:    # Print i if it's even
        print(i)
2
4
6
8
10

For Loop

The for loop provides the same basic functionality as the while loop, but allows for a simpler syntax in certain cases.

For example, if we wanted to access all the elements inside a list one by one, we could write a while loop with a variable index i and access the list elements as listname[i], incrementing i until it's the same size as the length of the list.

However, the for loop lets us avoid the need to declare an index variable. For example:

In [59]:
for x in range(1,11):    # Loop through a list of values [1..10]
    if x % 2 == 0:       # Print the list value if it's even
        print(x)
2
4
6
8
10
In [60]:
for i, x in enumerate(['a', 'b', 'c', 'd', 'e']):
    print("%d  %s" % (i+1, x))
1  a
2  b
3  c
4  d
5  e

If we are interested in building lists we can start from a blank list and append things to it in a for loop or use a list comprehension which combines for loops and list creation into line. The syntax is a set of square brackets that contains formula and a for loop.

In [61]:
squaredrange = [e**2 for e in range(1,11)]

print(squaredrange)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

You can also loop through two lists simultaneously using the zip function:

In [62]:
mylist  = range(1,11)
mylist2 = [e**2 for e in mylist]

for x, y in zip(mylist, mylist2):
    print("%2d %4d" % (x, y))
 1    1
 2    4
 3    9
 4   16
 5   25
 6   36
 7   49
 8   64
 9   81
10  100

Functions

Functions are subroutines that accept some input and produce zero or more outputs. They are typically used to define common tasks in a program.

Rule of thumb: if you find that you are copying a piece of code over and over inside your script, it should probably go into a function.

Example: Rounding

The following function will round integers to the nearest 10:

In [63]:
def round_int(x):
    return 10 * ((x + 5)/10)

for x in range(2, 50, 5):
    print("%5d %5d" % (x, round_int(x)))
    2     0
    7    10
   12    10
   17    20
   22    20
   27    30
   32    30
   37    40
   42    40
   47    50

In-Class Exercise

With the small amount we've gone through, you can already write reasonably sophisticated programs. For example, we can write a loop that generates the Fibonacci sequence.

Just to remind you, the Fibonacci sequence is the list of numbers

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...

It is defined by the linear homogeneous recurrence relation

$F_{n} = F_{n-1} + F_{n-2}$, where $F_0=F_1=1$.

The exercise is:

  1. Write a Python function that generate $F_n$ given $n$.
  2. Use your function to generate the first 100 numbers in the Fibonacci sequence.
In [64]:
# Easy implementation: recursive function

def fib(n):
    """Generate term n of the Fibonacci sequence"""
    if n <= 1:
        # if n==0 or n==1: return 1
        return 1
    else:
        return fib(n-1) + fib(n-2)
In [65]:
for n in range(0, 35):
    Fn = fib(n)
    print("%3d%25d" % (n, Fn))
  0                        1
  1                        1
  2                        2
  3                        3
  4                        5
  5                        8
  6                       13
  7                       21
  8                       34
  9                       55
 10                       89
 11                      144
 12                      233
 13                      377
 14                      610
 15                      987
 16                     1597
 17                     2584
 18                     4181
 19                     6765
 20                    10946
 21                    17711
 22                    28657
 23                    46368
 24                    75025
 25                   121393
 26                   196418
 27                   317811
 28                   514229
 29                   832040
 30                  1346269
 31                  2178309
 32                  3524578
 33                  5702887
 34                  9227465

This function will work just fine for small n. Unfortunately, the recursive calls to fib cause the function call stack to grow rapidly with n. When n gets sufficiently large, you may hit the Python call stack limit. At that point your program will crash.

Here is a more efficient approach that does not require recursion:

In [66]:
def fibBetter(n):
    """Generate the Fibonacci series at position n"""
    a, b = 0, 1
    while n > 0:                 # build up the series from n=0
        a, b, n = b, a+b, n-1    # store results in loop variables
    return b
In [67]:
for n in range(0, 100):
    Fn = fibBetter(n)
    print("%3d%25d" % (n, Fn))
  0                        1
  1                        1
  2                        2
  3                        3
  4                        5
  5                        8
  6                       13
  7                       21
  8                       34
  9                       55
 10                       89
 11                      144
 12                      233
 13                      377
 14                      610
 15                      987
 16                     1597
 17                     2584
 18                     4181
 19                     6765
 20                    10946
 21                    17711
 22                    28657
 23                    46368
 24                    75025
 25                   121393
 26                   196418
 27                   317811
 28                   514229
 29                   832040
 30                  1346269
 31                  2178309
 32                  3524578
 33                  5702887
 34                  9227465
 35                 14930352
 36                 24157817
 37                 39088169
 38                 63245986
 39                102334155
 40                165580141
 41                267914296
 42                433494437
 43                701408733
 44               1134903170
 45               1836311903
 46               2971215073
 47               4807526976
 48               7778742049
 49              12586269025
 50              20365011074
 51              32951280099
 52              53316291173
 53              86267571272
 54             139583862445
 55             225851433717
 56             365435296162
 57             591286729879
 58             956722026041
 59            1548008755920
 60            2504730781961
 61            4052739537881
 62            6557470319842
 63           10610209857723
 64           17167680177565
 65           27777890035288
 66           44945570212853
 67           72723460248141
 68          117669030460994
 69          190392490709135
 70          308061521170129
 71          498454011879264
 72          806515533049393
 73         1304969544928657
 74         2111485077978050
 75         3416454622906707
 76         5527939700884757
 77         8944394323791464
 78        14472334024676221
 79        23416728348467685
 80        37889062373143906
 81        61305790721611591
 82        99194853094755497
 83       160500643816367088
 84       259695496911122585
 85       420196140727489673
 86       679891637638612258
 87      1100087778366101931
 88      1779979416004714189
 89      2880067194370816120
 90      4660046610375530309
 91      7540113804746346429
 92     12200160415121876738
 93     19740274219868223167
 94     31940434634990099905
 95     51680708854858323072
 96     83621143489848422977
 97    135301852344706746049
 98    218922995834555169026
 99    354224848179261915075

Accessing Functions Beyond the Built-In Functions

If we want to use libraries and modules not defined within the built-in functionality of python we have to import them. There are a number of ways to do this.

In [68]:
import numpy, scipy

This imports the module numpy and the module scipy, and creates a reference to that modules in the current namespace. After you’ve run this statement, you can use numpy.name and scipy.name to refer to constants, functions, and classes defined in module numpy and scipy.

In [69]:
numpy.pi
Out[69]:
3.141592653589793
In [70]:
from numpy import *

This imports the module numpy, and creates references in the current namespace to all public objects defined by that module (that is, everything that doesn’t have a name starting with “_”).

Or in other words, after you’ve run this statement, you can simply use a plain name to refer to things defined in module numpy. Here, numpy itself is not defined, so numpy.name doesn’t work. If name was already defined, it is replaced by the new version. Also, if name in numpy is changed to point to some other object, your module won’t notice.

In [71]:
pi
Out[71]:
3.141592653589793
In [72]:
from scipy import special

print(special.erf(0),
      special.erf(1),
      special.erf(2))
(0.0, 0.84270079294971478, 0.99532226501895271)

This imports the module scipy, and creates references in the current namespace functions in the submodule special. We then make 3 function calls to the Error Function erf.

In [73]:
import numpy as np
In [74]:
np.pi
Out[74]:
3.141592653589793
In [75]:
np.arange(0,8)    # acts like the range function, but return a numpy array
Out[75]:
array([0, 1, 2, 3, 4, 5, 6, 7])
In [76]:
np.arange(0,8, 0.1)  # unlike builtin range, you can use non-integer stride
Out[76]:
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ,
        1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7,  1.8,  1.9,  2. ,  2.1,
        2.2,  2.3,  2.4,  2.5,  2.6,  2.7,  2.8,  2.9,  3. ,  3.1,  3.2,
        3.3,  3.4,  3.5,  3.6,  3.7,  3.8,  3.9,  4. ,  4.1,  4.2,  4.3,
        4.4,  4.5,  4.6,  4.7,  4.8,  4.9,  5. ,  5.1,  5.2,  5.3,  5.4,
        5.5,  5.6,  5.7,  5.8,  5.9,  6. ,  6.1,  6.2,  6.3,  6.4,  6.5,
        6.6,  6.7,  6.8,  6.9,  7. ,  7.1,  7.2,  7.3,  7.4,  7.5,  7.6,
        7.7,  7.8,  7.9])

This imports numpy but assigns the name of the module to np so that you can type np rather than numpy when you want to access variables and functions defined inside the module.

NumPy Tips and Tricks

NumPy is optimized for numerical work. The array type inside of the module behaves a lot like a list, but it is vectorized so that you can apply arithmetic operations and other functions to the array without having to loop through it.

For example, when we wanted to square every element inside a python list we used a list comprehension:

In [77]:
mylist = range(1,11)
[x**2 for x in mylist]
Out[77]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

This isn't that hard, but the syntax is a little ugly and we do have to explicitly loop through the list. In contrast, to square all the elements in the NumPy array you just apply the operator to the array variable itself:

In [78]:
myarray = np.arange(1,11)
myarray**2
Out[78]:
array([  1,   4,   9,  16,  25,  36,  49,  64,  81, 100])

Evenly Spaced Numbers

NumPy provides two functions to give evenly spaced numbers on linear or logarithmic scales.

In [79]:
np.linspace(1, 10, 21)   # gives 21 evenly spaced numbers in [1..10]
Out[79]:
array([  1.  ,   1.45,   1.9 ,   2.35,   2.8 ,   3.25,   3.7 ,   4.15,
         4.6 ,   5.05,   5.5 ,   5.95,   6.4 ,   6.85,   7.3 ,   7.75,
         8.2 ,   8.65,   9.1 ,   9.55,  10.  ])
In [80]:
np.logspace(1, 6, 6)     # gives 6 logarithmically spaced numbers
                         # between 1e1=10 and 1e6=1000000
Out[80]:
array([  1.00000000e+01,   1.00000000e+02,   1.00000000e+03,
         1.00000000e+04,   1.00000000e+05,   1.00000000e+06])
In [81]:
np.logspace(1, 6, 6, base=2)    # same as above, but base-2 logarithm
Out[81]:
array([  2.,   4.,   8.,  16.,  32.,  64.])

Slicing Arrays with Boolean Masks

An extremely useful feature in NumPy is the ability to create a "mask" array which can select values satisfying a logical condition:

In [82]:
x = np.arange(0, 8)      # [0, 1, 2, 3, 4, 5, 6, 7]
y = 3*x                  # [0, 3, 6, 9, 12, 15, 18, 21]

c = x < 3
print(c)
[ True  True  True False False False False False]
In [83]:
print(x[c])
[0 1 2]
In [84]:
print(y[c])
print(y[x >= 3])
[0 3 6]
[ 9 12 15 18 21]
In [85]:
c = (x<3) | (x>5)         # Combine cuts with bitwise OR or AND
print(y[c])
[ 0  3  6 18 21]

This is the type of selection used all the time in data analysis.

File Input/Output

Standard Python has functions to read basic text and binary files from disk.

However, for numerical analysis your files will usually be nicely formatted into numerical columns separated by spaces, commas, etc. For reading such files, NumPy has a nice function called genfromtxt:

In [86]:
# Load data from file into a multidimensional array
data = np.genfromtxt("data.txt")

x = data[:,0]   # x is the first column (numbering starts @ 0)
y = data[:,1]   # y is the second column

print(x)
print(y)
[  1.   2.   3.   4.   5.   6.   7.   8.   9.  10.]
[   1.    4.    9.   16.   25.   36.   49.   64.   81.  100.]

Plotting with Matplotlib

Matplotlib is used to plot data and can be used to produce the usual xy scatter plots, contour plots, histograms, etc. that you're used to making for all basic data analyses.

I strongly recommend that you go to the Matplotlib website and check out the huge plot gallery. This is the easiest way to learn how to make a particular kind of plot.

Note: when you want to plot something in an IPython notebook, put the magic line

%matplotlib inline

before you import the matplotlib module. This will ensure that your plots appear inside the notebook. Otherwise the plots will pop open in another window, which can be annoying.

In [87]:
%matplotlib inline

import matplotlib.pyplot as plt
In [88]:
plt.plot(x, y, "k.")
plt.xlabel("x [arb. units]")
plt.ylabel("y [arb. units]")
plt.title("Some XY data")
Out[88]:
<matplotlib.text.Text at 0x104cd1f10>

Here is an example of how to change the default formatting of the text in your plot. Also note how LaTeX is supported!

In [89]:
import matplotlib as mpl
mpl.rc("font", family="serif", size=16)

plt.plot(x, y, "k.")
plt.xlabel(r"$\sin({x)}$ [arb. units]")
plt.ylabel(r"$\zeta(y)$ [arb. units]")
plt.title("Some XY data")
Out[89]:
<matplotlib.text.Text at 0x104d1ae10>

Using NumPy and Matplotlib Together

Here we create some fake data with NumPy and plot it, including a legend.

In [90]:
x = x=np.linspace(-np.pi, np.pi, 1000,endpoint=True)
c = np.cos(x)
s = np.sin(x)

plt.plot(x,c,label="Cosine",color="r",linestyle="--",linewidth=2)
plt.plot(x,s,label="Sine",color="b",linestyle="-.",linewidth=2)
plt.xlabel("$x$",fontsize=14)
plt.xlim(-np.pi,np.pi)

# Override default ticks and labels
xticks = [-np.pi, -0.5*np.pi, 0, 0.5*np.pi, np.pi]
labels = ["$-\pi$", "$-\pi/2$", "$0$", "$\pi/2$", "$\pi$"]
plt.xticks(xticks, labels)

plt.ylabel("$y$",fontsize=14)
plt.ylim(-1,1)
plt.legend(fontsize=14, loc="best", numpoints=1)
Out[90]:
<matplotlib.legend.Legend at 0x104ecc710>

Help Manual and Inspection

When running interactive sessions, you can use the built-in help function to view module and function documentation.

For example, here is how to view the internal documentation for the built-in function that calculates the greatest common divisor of two numbers:

In [91]:
from fractions import gcd

help(gcd)
Help on function gcd in module fractions:

gcd(a, b)
    Calculate the Greatest Common Divisor of a and b.
    
    Unless b==0, the result will have the same sign as b (so that when
    b is divided by it, the result comes out positive).

The inspect module is nice if you actually want to look at the source code of a function. Just import inspect and call the getsource function for the code you want to see:

In [92]:
from inspect import getsource

print(getsource(gcd))
def gcd(a, b):
    """Calculate the Greatest Common Divisor of a and b.

    Unless b==0, the result will have the same sign as b (so that when
    b is divided by it, the result comes out positive).
    """
    while b:
        a, b = b, a%b
    return a