Source: Guido van Rossum, Python Software Foundation

- Started as a side-project in 1989 by Guido van Rossum, BDFL (benevolent dictator for life) until 2018.
- Python 3, first released in 2008, is the current major version
- Python 2 support stopped on 1 January 2020

In [1]:

```
import this
```

- Python is an
*intepreted*language (like R and Stata) - Every program is executed one
*command*(aka*statement*) at a time - Which also means that work can be done interactively

In [2]:

```
print("Hello World!")
```

Hello World!

Python programs can be decomposed into modules, statements, expressions, and objects, as follows:

*Programs*are composed of*modules**Modules*contain*statements**Statements*contain*expressions**Expressions*create and process*objects*

- Everything that Python operates on is an
*object* - This includes numbers, strings, data structures, functions, etc.
- Eact object has a
*type*(e.g. string or function) and internal data - Objects can be
*mutable*(e.g. list) and*immutable*(e.g. string)

*Objects* and *operators* are combined to form *expressions*. Key *operators* are:

- Arithmetic (
`+`

,`-`

,`*`

,`**`

,`/`

,`//`

,`%`

) - Boolean (
`and`

,`or`

,`not`

) - Relational (
`==`

,`!=`

,`>`

,`>=`

,`<`

,`<=`

) - Assignment (
`=`

,`+=`

,`-=`

,`*=`

,`/=`

) - Membership (
`in`

)

In [3]:

```
1 + 1
```

Out[3]:

2

In [4]:

```
5 - 3
```

Out[4]:

2

In [5]:

```
6 / 2
```

Out[5]:

3.0

In [6]:

```
4 * 4
```

Out[6]:

16

In [7]:

```
# Exponentiation <- Python comments start with #
2 ** 4
```

Out[7]:

16

In [8]:

```
3 != 1 # Not equal
```

Out[8]:

True

In [9]:

```
3 > 3 # Greater than
```

Out[9]:

False

In [10]:

```
3 >= 3 # Greater than or equal
```

Out[10]:

True

In [11]:

```
False or True # True if either first or second operand is True, False otherwise
```

Out[11]:

True

In [12]:

```
3 > 3 or 3 >= 3 # Combining 3 Boolean expressions
```

Out[12]:

True

- Assignments create object references.
*Target*(or*name*) on the left is assigned to*object*on the right.

In [13]:

```
x = 3
```

In [14]:

```
x
```

Out[14]:

3

In [15]:

```
x += 2 # Increment assignment, equivalent to x = x + 2
```

In [16]:

```
x
```

Out[16]:

5

As `=`

(assignment) and `==`

(equality comparison) operators appear very similar, they sometime can create confusion.

In [17]:

```
x = 3
```

In [18]:

```
x
```

Out[18]:

3

In [19]:

```
x == 3
```

Out[19]:

True

Operator `in`

returns `True`

if an object of the left side is in a sequence on the right.

In [20]:

```
'a' in 'abc'
```

Out[20]:

True

In [21]:

```
4 in [1, 2, 3] # [1,2,3] is a list
```

Out[21]:

False

In [22]:

```
4 not in [1, 2, 3]
```

Out[22]:

True

Python objects can have *scalar* and *non-scalar* types. Scalar objects are indivisible.

4 main types of scalar objects in Python:

- Integer (
`int`

) - Real number (
`float`

) - Boolean (
`bool`

) - Null value (
`None`

)

In [23]:

```
type(7)
```

Out[23]:

int

In [24]:

```
type(3.14)
```

Out[24]:

float

In [25]:

```
type(True)
```

Out[25]:

bool

In [26]:

```
type(None)
```

Out[26]:

NoneType

In [27]:

```
int(3.14) # Scalar type conversion (casting)
```

Out[27]:

3

In contrast to scalars, non-scalar objects, *sequences*, have some internal structure. This allows indexing, slicing and other interesting operations.

Most common sequences in Python are:

- String (
`str`

) -*immutable*ordered sequence of characters - Tuple (
`tuple`

) -*immutable*ordered sequence of elements - List (
`list`

) -*mutable*ordered sequence of elements - Set (
`set`

) -*mutable*unordered collection of unique elements - Dictionary (
`dict`

) -*mutable*unordered collection of key-value pairs

In [28]:

```
s = 'time flies like a banana'
t = (0, 'one', 1, 2)
l = [0, 'one', 1, 2]
o = {'apple', 'banana', 'watermelon'}
d = {'apple': 150.0, 'banana': 120.0, 'watermelon': 3000.0}
```

In [29]:

```
type(s)
```

Out[29]:

str

In [30]:

```
type(t)
```

Out[30]:

tuple

In [31]:

```
type(l)
```

Out[31]:

list

In [32]:

```
type(o)
```

Out[32]:

set

In [33]:

```
type(d)
```

Out[33]:

dict

*Indexing*can be used to subset individual elements from a sequence*Slicing*can be used to extract sub-sequence of arbitrary length- Use square brackets
`[]`

to supply the index (indices) of elements:

`object[index]`

Source: xkcd

Extra: Why Python uses 0-based indexing by Guido van Rossum

Extra: Why numbering should start at zero by Edsger Dijkstra

In [34]:

```
s
```

Out[34]:

'time flies like a banana'

In [35]:

```
len(s) # length of string (including whitespaces)
```

Out[35]:

24

In [36]:

```
s[0] # Subset 1st element (indexing in Python starts from zero!)
```

Out[36]:

't'

In [37]:

```
s[5:] # Subset all elements starting from 6th
```

Out[37]:

'flies like a banana'

In [38]:

```
s + '!' # Strings can be concatenated together
```

Out[38]:

'time flies like a banana!'

- Python objects of built-in types have
*methods*associated with them - They can be thought of function-like objects
- However, their syntax is
`object.method()`

as opposed to`function(object)`

In [39]:

```
len(s) # Function
```

Out[39]:

24

In [40]:

```
s.upper() # Method (makes string upper-case)
```

Out[40]:

'TIME FLIES LIKE A BANANA'

In [41]:

```
s.capitalize() # Note that only the first character gets capitalized
```

Out[41]:

'Time flies like a banana'

In [42]:

```
s.split(sep = ' ') # Here we supply an argument 'sep' to our methods call
```

Out[42]:

['time', 'flies', 'like', 'a', 'banana']

In [43]:

```
s.replace(' ', '-') # Arguments can also be matched by position, not just name
```

Out[43]:

'time-flies-like-a-banana'

In [44]:

```
'-'.join(s.split(sep = ' ')) # Methods calls can be nested within each other
```

Out[44]:

'time-flies-like-a-banana'

In [45]:

```
t # Tuples can contain elements of different types
```

Out[45]:

(0, 'one', 1, 2)

In [46]:

```
len(t)
```

Out[46]:

4

In [47]:

```
t[1:]
```

Out[47]:

('one', 1, 2)

In [48]:

```
t + ('three', 5) # Like strings tuples can be concatenated
```

Out[48]:

(0, 'one', 1, 2, 'three', 5)

In [49]:

```
l # Like tuples lists can contain elements of different types
```

Out[49]:

[0, 'one', 1, 2]

In [50]:

```
l[1] = 1 # Unlike tuples lists are mutable
```

In [51]:

```
l
```

Out[51]:

[0, 1, 1, 2]

In [52]:

```
t[1] = 1 # Compare to tuple
```

In [53]:

```
l
```

Out[53]:

[0, 1, 1, 2]

In [54]:

```
l[1:] # Subset all elements starting from 2nd
```

Out[54]:

[1, 1, 2]

In [55]:

```
l[-1] # Subset the last element
```

Out[55]:

2

In [56]:

```
l[::2] # Subset every second element, list[start:stop:step]
```

Out[56]:

[0, 1]

In [57]:

```
l[::-1] # Subset all elements in reverse order
```

Out[57]:

[2, 1, 1, 0]

In [58]:

```
o
```

Out[58]:

{'apple', 'banana', 'watermelon'}

In [59]:

```
{'apple', 'apple', 'banana', 'watermelon'} # Sets retain only unique values
```

Out[59]:

{'apple', 'banana', 'watermelon'}

In [60]:

```
{'apple'} < o # Sets can be compared (e.g. one being subset of another)
```

Out[60]:

True

In [61]:

```
o[1] # Unlike strings, tuples and lists, sets are unordered
```