1. Basic Datatypes

1.1 Integer

Intergers are not limited and there is no signed or unsigned type


In [1]:
1, type(1)


Out[1]:
(1, int)

In [2]:
-1, type(-1)


Out[2]:
(-1, int)

1.2 Floating point

Almost all platforms map Python floats to IEEE-754 “double precision”.


In [3]:
3.14, type(3.14)


Out[3]:
(3.14, float)

Floating point math madness: http://0.30000000000000004.com


In [4]:
0.1 + 0.2


Out[4]:
0.30000000000000004

1.3 Strings


In [5]:
'Hello World', type('Hello World')


Out[5]:
('Hello World', str)

More on strings later

1.4 Bool


In [6]:
True, type(True)


Out[6]:
(True, bool)

In [7]:
False, type(False)


Out[7]:
(False, bool)

1.5 None


In [8]:
None, type(None)


Out[8]:
(None, NoneType)

1.6 Type Conversion

Type conversion is very easy and most of the time very intuitiv

int to float


In [9]:
float(2)


Out[9]:
2.0

float to int, no rounding


In [10]:
int(3.99)


Out[10]:
3

float/int to str


In [11]:
str(3.14)


Out[11]:
'3.14'

In [12]:
str(10)


Out[12]:
'10'

str to int/float


In [13]:
float('3.14')


Out[13]:
3.14

In [14]:
int('3')


Out[14]:
3

float string to int will raise a ValueError


In [15]:
int('3.14')


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-15-276b8f268da7> in <module>()
----> 1 int('3.14')

ValueError: invalid literal for int() with base 10: '3.14'

However you can force it


In [16]:
int(float('3.14'))


Out[16]:
3

bool to int/float


In [17]:
int(True), int(False)


Out[17]:
(1, 0)

In [18]:
float(True), float(False)


Out[18]:
(1.0, 0.0)

In [19]:
str(True), str(False)


Out[19]:
('True', 'False')

str to bool


In [20]:
bool('Hello World')


Out[20]:
True

empty strings


In [21]:
bool('')


Out[21]:
False

All numbers different from 0 convert to True


In [22]:
bool(2), bool(1), bool(0.01), bool(0), bool(-0.001), bool(-1), bool(-2)


Out[22]:
(True, True, True, False, True, True, True)

2. Variables

2.1 Assignement


In [23]:
pi = 3.14
pi


Out[23]:
3.14

In [24]:
pi0 = pi1 = pi2 = 3.14
pi0, pi1, pi2


Out[24]:
(3.14, 3.14, 3.14)

In [25]:
pos, pi, text = 1, 3.14, 'Hello World'
pos, pi, text


Out[25]:
(1, 3.14, 'Hello World')

2.2 Swap variables


In [26]:
a, b = 1, -1
print(a, b)

a, b = b, a
print(a, b)


1 -1
-1 1

3. Operators

3.1 Addition '+'


In [27]:
result = 1 + 1
result


Out[27]:
2

3.2 Substraction '-'


In [28]:
result = 5 - 8
result


Out[28]:
-3

3.3 Multiplication '*'

Integer multiplication returns integer


In [29]:
result = -2 * 5
result


Out[29]:
-10

3.4 Division '/'

Always returns float in Python 3. (In Python 2 integer division returns integer, 1 / 2 = 0).


In [30]:
result = 4 / 2
result, type(result)


Out[30]:
(2.0, float)

3.5 Power '**'


In [31]:
result = 4**2
result, type(result)


Out[31]:
(16, int)

In [32]:
result = 3.14**2
result, type(result)


Out[32]:
(9.8596, float)

In [33]:
result = 3**2.23
result, type(result)


Out[33]:
(11.587250556694206, float)

3.6 Equal '==' and unequal '!='

Returning True or False


In [34]:
3.14 == 3.14


Out[34]:
True

In [35]:
'Hallo' == 'World'


Out[35]:
False

In [36]:
'3.14' != 3.14


Out[36]:
True

In [37]:
3.14 != 3.14


Out[37]:
False

4. Lists

Python ist probabliy most important Data structure are list.


In [38]:
l = [1, 'Hallo', 2, 2, 'Welt', print, [1, 'test', 1.92e-19], 3.14, 10]
l


Out[38]:
[1, 'Hallo', 2, 2, 'Welt', <function print>, [1, 'test', 1.92e-19], 3.14, 10]

4.1 Indexing

By index number starting at 0


In [39]:
l[1], l[4]


Out[39]:
('Hallo', 'Welt')

negative number are possible


In [40]:
l[-2]


Out[40]:
3.14

4.2 Slicing

positive


In [41]:
l[1:3]


Out[41]:
['Hallo', 2]

negative numbers


In [42]:
l[:-3]


Out[42]:
[1, 'Hallo', 2, 2, 'Welt', <function print>]

negative and positiv


In [43]:
l[1:-3]


Out[43]:
['Hallo', 2, 2, 'Welt', <function print>]

steps


In [44]:
l[1:-1:2]


Out[44]:
['Hallo', 2, <function print>, 3.14]

naming slices


In [45]:
center = slice(1, -1)
l[center]


Out[45]:
['Hallo', 2, 2, 'Welt', <function print>, [1, 'test', 1.92e-19], 3.14]

4.3 Alter elements


In [46]:
l[4] = 'Nano'
l


Out[46]:
[1, 'Hallo', 2, 2, 'Nano', <function print>, [1, 'test', 1.92e-19], 3.14, 10]

In [47]:
l[2:4] = [3, 3]
l


Out[47]:
[1, 'Hallo', 3, 3, 'Nano', <function print>, [1, 'test', 1.92e-19], 3.14, 10]

4.4 Deleting elements


In [48]:
del l[5]
l


Out[48]:
[1, 'Hallo', 3, 3, 'Nano', [1, 'test', 1.92e-19], 3.14, 10]

4.5 Length of list


In [49]:
len(l)


Out[49]:
8

4.7 Append


In [50]:
l.append('am ende')
l


Out[50]:
[1, 'Hallo', 3, 3, 'Nano', [1, 'test', 1.92e-19], 3.14, 10, 'am ende']

Extending lists


In [51]:
l1 = [1, 2, 3]
l2 = [4, 5, 6]
l3 = [7, 8, 9]

Using extend function


In [52]:
l1.extend(l2)
l1


Out[52]:
[1, 2, 3, 4, 5, 6]

Using Operators


In [53]:
l1 += l3
l1


Out[53]:
[1, 2, 3, 4, 5, 6, 7, 8, 9]

4.8 Pop


In [54]:
l


Out[54]:
[1, 'Hallo', 3, 3, 'Nano', [1, 'test', 1.92e-19], 3.14, 10, 'am ende']

In [55]:
l.pop()


Out[55]:
'am ende'

In [56]:
l


Out[56]:
[1, 'Hallo', 3, 3, 'Nano', [1, 'test', 1.92e-19], 3.14, 10]

The del equivalent


In [57]:
last_item = l[-1] 
del l[-1]
last_item


Out[57]:
10

4.9 Count


In [58]:
l


Out[58]:
[1, 'Hallo', 3, 3, 'Nano', [1, 'test', 1.92e-19], 3.14]

In [59]:
l.count(3)


Out[59]:
2

4.10 Index finding


In [60]:
l


Out[60]:
[1, 'Hallo', 3, 3, 'Nano', [1, 'test', 1.92e-19], 3.14]

In [61]:
l.index('Nano')


Out[61]:
4

In [62]:
l.index(3)


Out[62]:
2

4.11 Many more methods


In [63]:
help(l)


Help on list object:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable's items
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __iadd__(self, value, /)
 |      Implement self+=value.
 |  
 |  __imul__(self, value, /)
 |      Implement self*=value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.n
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(...)
 |      L.__reversed__() -- return a reverse iterator over the list
 |  
 |  __rmul__(self, value, /)
 |      Return self*value.
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      L.__sizeof__() -- size of L in memory, in bytes
 |  
 |  append(...)
 |      L.append(object) -> None -- append object to end
 |  
 |  clear(...)
 |      L.clear() -> None -- remove all items from L
 |  
 |  copy(...)
 |      L.copy() -> list -- a shallow copy of L
 |  
 |  count(...)
 |      L.count(value) -> integer -- return number of occurrences of value
 |  
 |  extend(...)
 |      L.extend(iterable) -> None -- extend list by appending elements from the iterable
 |  
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |  
 |  insert(...)
 |      L.insert(index, object) -- insert object before index
 |  
 |  pop(...)
 |      L.pop([index]) -> item -- remove and return item at index (default last).
 |      Raises IndexError if list is empty or index is out of range.
 |  
 |  remove(...)
 |      L.remove(value) -> None -- remove first occurrence of value.
 |      Raises ValueError if the value is not present.
 |  
 |  reverse(...)
 |      L.reverse() -- reverse *IN PLACE*
 |  
 |  sort(...)
 |      L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None

5. Tuples

The differences between tuples and lists are, the tuples cannot be changed unlike lists.


In [64]:
t = (1, 'Hallo', 2, 2, 'Welt', print, [1, 'test', 1.92e-19], 3.14, 10)
t


Out[64]:
(1, 'Hallo', 2, 2, 'Welt', <function print>, [1, 'test', 1.92e-19], 3.14, 10)

5.1 Indexing and slicing


In [65]:
t[0]


Out[65]:
1

In [66]:
t[1:-1:2]


Out[66]:
('Hallo', 2, <function print>, 3.14)

5.2 Not alterable


In [67]:
t[0] = 4


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-67-66917334790a> in <module>()
----> 1 t[0] = 4

TypeError: 'tuple' object does not support item assignment

In [68]:
del t[2]


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-68-e0f6b690504d> in <module>()
----> 1 del t[2]

TypeError: 'tuple' object doesn't support item deletion

In [69]:
help(t)


Help on tuple object:

class tuple(object)
 |  tuple() -> empty tuple
 |  tuple(iterable) -> tuple initialized from iterable's items
 |  
 |  If the argument is a tuple, the return value is the same object.
 |  
 |  Methods defined here:
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(self, key, /)
 |      Return self[key].
 |  
 |  __getnewargs__(...)
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.n
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __rmul__(self, value, /)
 |      Return self*value.
 |  
 |  __sizeof__(...)
 |      T.__sizeof__() -- size of T in memory, in bytes
 |  
 |  count(...)
 |      T.count(value) -> integer -- return number of occurrences of value
 |  
 |  index(...)
 |      T.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.

6. Dictonaries

Dicts are unsorted (Key, Value) Pairs, internal realized by hash tables. They are equivalent to maps in C++, Java or Matlabt but they take every datatype as key and item.


In [70]:
d = {'Hello': 'World', 'pi': 3.14, print: 'function', 2.718: 'euler'}
d


Out[70]:
{<function print>: 'function', 2.718: 'euler', 'Hello': 'World', 'pi': 3.14}

6.1 Key access


In [71]:
d['Hello']


Out[71]:
'World'

In [72]:
d.get('Hello')


Out[72]:
'World'

In [73]:
d[2.718]


Out[73]:
'euler'

In [74]:
d[print]


Out[74]:
'function'

In [75]:
d['no_key']


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-75-67a0efeee120> in <module>()
----> 1 d['no_key']

KeyError: 'no_key'

In [76]:
d.get('no_key', 'key does not exist')


Out[76]:
'key does not exist'

6.2 Change Value


In [77]:
d['Hello'] = 'Nano'
d['Hello']


Out[77]:
'Nano'

6.3 Deleting elements


In [78]:
del d[print]
d


Out[78]:
{2.718: 'euler', 'Hello': 'Nano', 'pi': 3.14}

In [79]:
d.pop(2.718)


Out[79]:
'euler'

In [80]:
d


Out[80]:
{'Hello': 'Nano', 'pi': 3.14}

6.4 Change Key

Changing a key is not possible but


In [81]:
d['PI'] = d['pi']
del d['pi']
d


Out[81]:
{'Hello': 'Nano', 'PI': 3.14}

In [82]:
d['pi'] = d.pop('PI')
d


Out[82]:
{'Hello': 'Nano', 'pi': 3.14}

6.5 Adding pairs

Using assignment for single pairs


In [83]:
d['pi'] = 3.14
d


Out[83]:
{'Hello': 'Nano', 'pi': 3.14}

For adding dictionaries


In [84]:
d2 = {'python': 'in the lab', print: 'function', 'euler': 2.178}
d.update(d2)
d


Out[84]:
{'euler': 2.178,
 'python': 'in the lab',
 <function print>: 'function',
 'Hello': 'Nano',
 'pi': 3.14}

6.6 Item views

Views are dynamic


In [85]:
vview = d.values()
lview = list(vview)
vview, lview


Out[85]:
(dict_values([2.178, 'in the lab', 'function', 'Nano', 3.14]),
 [2.178, 'in the lab', 'function', 'Nano', 3.14])

In [86]:
del d[print]

In [87]:
vview, lview


Out[87]:
(dict_values([2.178, 'in the lab', 'Nano', 3.14]),
 [2.178, 'in the lab', 'function', 'Nano', 3.14])

6.7 Key views


In [88]:
d.keys()


Out[88]:
dict_keys(['euler', 'python', 'Hello', 'pi'])

6.8 Item views


In [89]:
d.items()


Out[89]:
dict_items([('euler', 2.178), ('python', 'in the lab'), ('Hello', 'Nano'), ('pi', 3.14)])

7. If statement

7.1 if


In [90]:
i = float(input('Enter number: '))

if i > 0:
    print('positive')

if i < 0:
    print('negative')
    
if i == 0:
    print('zero')


Enter number: 2
positive

7.2 elif and else


In [91]:
i = float(input('Enter number: '))

if 0 <= i and i < 10:
    print('between 0 and 10')
elif i >= 10:
    print('bigger 10')
else:
    print('negative')


Enter number: -22
negative

7.3 If and lists, dicts


In [92]:
l = [1, 'Hello', 2, 2, 'World', print, [1, 'test', 1.92e-19], 3.14, 10]

Check if item is in list


In [93]:
if 'Hello' in l:
    print(True)
else:
    print(False)


True

Check if item is not in list


In [94]:
if 'Hällö' not in l:
    print(True)


True

'In' and 'not in' are available outside if statement


In [95]:
d = {'Hello': 'World', 'pi': 3.14, 'e': 2.718, 'h': 6.626e-34}

In [96]:
# Check keys
if 'pi' in d:
    print('pi:', True)
    
if 'e' in d.keys():
    print('e:', True)

# Check values
if 1.92e-19 not in d.values():
    print('charge:', False)


pi: True
e: True
charge: False

'In' and 'not in' are not coupled to the if statement


In [97]:
print('Hello' not in l)
print('pi' in d)


False
True

7.4 If and is


In [98]:
a = True

# Good style
if a:
    print('good style: is True')
    
# Bad style
if a is True:
    print('bad style is True')   
    
# Very bad style
if a == True:
    print('very bad style: is True')


good style: is True
bad style is True
very bad style: is True

8. Case

8.1 The adventures of Case

The typical text based adventure:

"You are at the roof of the the University Tower. Supringsly the tower is buring, what will you do:

  • 0: Take the buring stairs.
  • 1: Take the elevator.
  • 2: Take the fastes way and jump.
  • 3: Stay and see what happens.

In [ ]:
# C++ code

switch ( i ) {
    case 0:
        cout << 'You get a smoke intoxication and die.' << endl;
    case 1:
        cout << 'The elevator stucks and you die.' << endl;
    case 2:
        cout << 'You die.' << endl;
    case 3:
        cout << 'An UFO picks you up and your adventure starts.' << ;
}
!!! There is no case structure in Python. However we learnt a lot today. !!!

8.2 If replacement


In [99]:
i = int(input('Your choice? '))

if i == 0:
    print('You get a smoke intoxication and die.')
elif i == 1:
    print('The elevator stucks and you die.')
elif i == 2:
    print('You die without pain.')
elif i == 3:
    print('An UFO picks you up and your adventure starts.')
else:
    print('You die because you are to stupid to pick a number.')


Your choice? 33
You die because you are to stupid to pick a number.

8.3 Dicts are great


In [100]:
i = int(input('Your choice? '))

case = {0: 'You get a smoke intoxication and die.',
        1: 'The elevator stucks and you die.',
        2: 'You die without pain.',
        3: 'An UFO picks you up and your adventure starts.'}

print(case.get(i, 'Wrong choice, you die'))


Your choice? 3
An UFO picks you up and your adventure starts.

9. For loops

9.1 Indexed Based

C++


In [ ]:
int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

for(int i = 0; i < sizeof(data); i++)
{
    std::cout << data[i] << endl;
}

Java


In [ ]:
int[] data = new int[]{4, 8, 4, 2, 2, 1, 1, 5, 9};

for(int i = 0; i < data.length; i++)
{
    System.out.println(array[i]);
}

Python


In [101]:
data  = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

for i in range(len(data)):
    print(data[i], end=', ')


1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
!!! THERE MUST BE A BETTER WAY !!!

9.2 Elementwise Iteration

Python

Iterate over a list


In [102]:
data  = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

for datapoint in data:
    print(datapoint, end=', ')


1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 

Iterate over a dictionary


In [103]:
d = {'Hello': 'World', 'pi': 3.14, 'e': 2.718, 'h': 6.626e-34}

Iterate over keys


In [104]:
for key in d:
    print(key, end=', ')


h, Hello, e, pi, 

In [105]:
for key in d.keys():
    print(key, end=', ')


h, Hello, e, pi, 

Iterate over values


In [106]:
for value in d.values():
    print(value, end=', ')


6.626e-34, World, 2.718, 3.14, 

Iterate over items


In [107]:
for item in d.items():
    print(item, end=', ')


('h', 6.626e-34), ('Hello', 'World'), ('e', 2.718), ('pi', 3.14), 

Java For Each


In [ ]:
for( int i: array )
{
    System.out.println(i + ', ');
}

C++11 Range Based iteration with auto type


In [ ]:
for ( auto &i: data):
{
    std::cout << i << ', ';
}

9.3 Enumerate

Some times you need the index, use enumerate


In [108]:
data = list(range(10))

for i, datapoint in enumerate(data):
    data[i] = datapoint * 2
data


Out[108]:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
!!! THERE MUST BE A BETTER WAY !!!

8 List comprehensions


In [109]:
data  = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

In [110]:
data * 2


Out[110]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Use list comprehensions for this


In [111]:
[datapoint**2 for datapoint in data]


Out[111]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Numpy arrays behave 'mathematically' but more on that later


In [112]:
import numpy as np

ary = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10] )
ary * 2


Out[112]:
array([ 2,  4,  6,  8, 10, 12, 14, 16, 18, 20])

Use filters with if statement


In [113]:
data  = [-4, -3, -2, -1, 0 , 1, 1, 2, 3, 4]

In [114]:
[datapoint**2 for datapoint in data if datapoint >= 0]


Out[114]:
[0, 1, 1, 4, 9, 16]

Nested for list comprehensions


In [115]:
[(x,y,z) for x in range(1,30) for y in range(x,30) for z in range(y,30) if x**2 + y**2 == z**2]


Out[115]:
[(3, 4, 5),
 (5, 12, 13),
 (6, 8, 10),
 (7, 24, 25),
 (8, 15, 17),
 (9, 12, 15),
 (10, 24, 26),
 (12, 16, 20),
 (15, 20, 25),
 (20, 21, 29)]

10 While loop


In [116]:
import random
import time

while random.random() > 0.005:
    print('.', end='')
    time.sleep(0.025)


...................................................................

10.2 break and continue


In [117]:
import math

print('Calculate Sqr')
print('q: QUIT')

while True:
    
    value = input('Put in number: ')
    
    # Check for 
    if value == 'q':
        print('Good bye')
        break
    
    value = float(value)
    
    if value < 0:
        print('Negative numbers are not allowed!')
        continue
    
    print('Sqr({}) = {}'.format(value, math.sqrt(value)))


Calculate Sqr
q: QUIT
Put in number: 2
Sqr(2.0) = 1.4142135623730951
Put in number: 1
Sqr(1.0) = 1.0
Put in number: 222
Sqr(222.0) = 14.89966442575134
Put in number: -22
Negative numbers are not allowed!
Put in number: q
Good bye

11 Functions

11.1 Definition

Math provides basic mathematic functions and is part of the standart libary.


In [118]:
import math

In [119]:
def area(radius):
    return math.pi * radius**2

def circum(radius):
    return 2 * math.pi * radius

In [120]:
area(10)


Out[120]:
314.1592653589793

In [121]:
circum(10)


Out[121]:
62.83185307179586

11.2 Namespace


In [122]:
def my_print(a):
    a = a**2
    print(a)

In [123]:
a = 10
my_print(a)
print(a)


100
10

11.3 Multiple return values


In [124]:
def circle(radius):
    area = math.pi * radius**2
    circum = 2 * math.pi * radius
    return area, circum

In [125]:
circle(10)


Out[125]:
(314.1592653589793, 62.83185307179586)

The return value is a tuple


In [126]:
a = circle(10)
type(a)


Out[126]:
tuple

So this is equivalent


In [127]:
def circle(radius):
    area = math.pi * radius**2
    circum = 2 * math.pi * radius
    return (area, circum)

a = circle(10)
type(a)


Out[127]:
tuple

Some times you want to return a list or some othe other datatype


In [128]:
def circle(radius):
    area = math.pi * radius**2
    circum = 2 * math.pi * radius
    return [area, circum]

a = circle(10)
type(a)


Out[128]:
list

11.4 Multiple arguments


In [129]:
def pythagoras(a, b):
    return math.sqrt(a**2 + b**2)

In [130]:
pythagoras(1, 3)


Out[130]:
3.1622776601683795

In [131]:
pythagoras(1, b=3)


Out[131]:
3.1622776601683795

In [132]:
pythagoras(a=1, b=3)


Out[132]:
3.1622776601683795

In [133]:
def cuboid(a, b, c):
    volumn = a * b * c
    return volumn

In [134]:
cuboid(2, 3, 2)


Out[134]:
12

11.5 Keyword arguments


In [135]:
def cuboid(a, b=1, c=1):
    return a * b * c

In [136]:
cuboid(2)


Out[136]:
2

In [137]:
cuboid(2, 3)


Out[137]:
6

In [138]:
cuboid(2, c=3)


Out[138]:
6

In [139]:
cuboid(2, 3, 4)


Out[139]:
24

You can make all arguments default but not very common


In [140]:
def cuboid(a=1, b=1, c=1):
    return a * b * c

In [141]:
cuboid()


Out[141]:
1

11.6 Optinal arguments


In [142]:
def some_function(a, *args):
    print(args, type(args))
    
    for value in args:
        print(value, end=', ')

In [143]:
some_function(1, 2, 3, 'Hallo', 4, [2, 3, 4])


(2, 3, 'Hallo', 4, [2, 3, 4]) <class 'tuple'>
2, 3, Hallo, 4, [2, 3, 4], 

In [144]:
def some_function(a, *args, **kwargs):
    print(args, type(args))
    for value in args:
        print(value, end=', ')
    
    print()
    
    print(kwargs, type(kwargs))
    for pair in kwargs.items():
        print(pair)

In [145]:
some_function(1, 2, 3, 'Hallo', 4, [2, 3, 4], name='python', where='in the lab', nr=10)


(2, 3, 'Hallo', 4, [2, 3, 4]) <class 'tuple'>
2, 3, Hallo, 4, [2, 3, 4], 
{'where': 'in the lab', 'nr': 10, 'name': 'python'} <class 'dict'>
('where', 'in the lab')
('nr', 10)
('name', 'python')

When is this usefull


In [146]:
import matplotlib.pyplot as plt
%matplotlib inline

Wrapping functions


In [147]:
def plot_sqrt(xdata, ydata):
    ydata_2 = [point**2 for point in ydata]

    return plt.gca().plot(xdata, ydata_2)

In [148]:
plot_sqrt(range(11), range(11))


Out[148]:
[<matplotlib.lines.Line2D at 0x75eeda0>]

In [149]:
def plot_sqrt(xdata, ydata, *plot, **kwplot):
    ydata_2 = [point**2 for point in ydata]

    return plt.gca().plot(xdata, ydata_2, *plot, **kwplot)

In [150]:
plt.figure()
plot_sqrt(range(11), range(11), ':o', c='red')


Out[150]:
[<matplotlib.lines.Line2D at 0x7d15940>]

In [151]:
plot_global = {'color':'green', 'ls':'--', 'lw':3, 'marker':'o', 'ms':5}

In [156]:
from collections import ChainMap

def plot_sqrt(xdata, ydata, *plot, **kwplot):
    ydata_2 = [point**2 for point in ydata]
    
    # Override global plot config with local plot config
    kwplot = ChainMap(kwplot, plot_global)
    
    return plt.gca().plot(xdata, ydata_2, *plot, **kwplot)

In [157]:
plot_sqrt(range(10), range(10))


Out[157]:
[<matplotlib.lines.Line2D at 0x7e5c278>]

In [158]:
plot_sqrt(range(10), range(10), marker='D')


Out[158]:
[<matplotlib.lines.Line2D at 0x7ec8470>]

In [159]:
d0 = {'class':'Python in the lab', 'time':'16:15', 'location':'somewhere'}
d1 = {'location':'seminar room', 'people':10}

In [160]:
d = d0.copy()
d.update(d1)
d


Out[160]:
{'class': 'Python in the lab',
 'location': 'seminar room',
 'people': 10,
 'time': '16:15'}

In [162]:
from collections import ChainMap

dict(ChainMap(d1, d0))


Out[162]:
{'class': 'Python in the lab',
 'location': 'seminar room',
 'people': 10,
 'time': '16:15'}

In [ ]:
# Very hot Python 3.5 shit

d = {**d0, **d1}

In [163]:
plot_global = {'color':'green', 'ls':'--', 'lw':3, 'marker':'o', 'ms':5}

def plot_sqrt(xdata, ydata,  *plot, ax=None, **kwplot):
    ydata_2 = [point**2 for point in ydata]
    
    if ax is None:
        ax = plt.gca()
    
    # Override global plot config with local plot config
    kwplot = ChainMap(plot_global, kwplot)
    
    return ax.plot(xdata, ydata_2, *plot, **kwplot)

In [164]:
fig, axs = plt.subplots(1, 2, figsize=(12, 6))

plot_sqrt(range(-10, 11), range(-10, 11), ax=axs[1], marker='D', ms=10)
plot_sqrt(range(-10, 11), range(-10, 11), ax=axs[0], color='red', ls=':')


Out[164]:
[<matplotlib.lines.Line2D at 0x7f8a860>]

11.7 Docstrings


In [165]:
plot_global = {'color':'green', 'ls':'--', 'lw':3, 'marker':'o', 'ms':5}

def plot_sqrt(xdata, ydata, *plot, **kwplot):
    """Plot the square of xdata as a function of ydata.
    
    *plot and **kwplot are optional arguments of matplotlib.pyplot.plot
    """
    
    ydata_2 = [point**2 for point in ydata]
    
    kwplot = ChainMap(plot_global, kwplot)
    
    return plt.gca().plot(xdata, ydata_2, *plot, **kwplot)

In [166]:
help(plot_sqrt)


Help on function plot_sqrt in module __main__:

plot_sqrt(xdata, ydata, *plot, **kwplot)
    Plot the square of xdata as a function of ydata.
    
    *plot and **kwplot are optional arguments of matplotlib.pyplot.plot

12. Get some Help


In [167]:
a = 'Hello'
b = 'World'
l = [a, b]

12.1 Tab Completion

Some words on TAB completion


In [ ]:
l.<TAB>
l.

12.2 Greedy Completer

Nested TAB completion


In [ ]:
a.<TAB>
a.

In [ ]:
l[0].<TAB>
l[0].

In [169]:
%config IPCompleter.greedy = True

In [ ]:
l[0].<TAB>
l[0].

12.3 Help

Getting help in the notebook or IPython


In [ ]:
l.append(<TAB>)
l.append()

In [170]:
l.append?

In [171]:
plot_sqrt??

Getting help everywhere else


In [168]:
help(l.append)


Help on built-in function append:

append(...) method of builtins.list instance
    L.append(object) -> None -- append object to end