# print something

"""
Explanation: Introduction to Python
Maria Dost, Jorin Diemer, Jens Hahn  -  27/10/2017
<a id='content' />
Content


<a href=#intro>Introduction</a>

Python version
Ways to write Python



<a href=#object>Everything is an object</a>

Objects, instances, methods, attributes
References, Mutable and Immutable objects 



<a href=#datatypes>Standard data types</a>

Text: String
Numeric: int, float, complex
Sequence: list, tuple
Mapping: dictionary
Boolean: True/False



<a href=#flowcontrol>Operators and Flow Control</a>

Mathematical and Logical Operators
for
if/else/elif
while



<a href=#functions>Functions and Methods</a>

Definition
Return



<a href=#classes>Classes, Objects, and Instances</a>

Definition
Instances



<a href=#literature>Literature & Links</a>



<a id='intro' />
Introduction
Python 2 or Python 3?
<a href=#content>back</a>    
Short version: Python 2.x is legacy, Python 3.x is the present and future of the language
final 

2.x version 2.7 was released 2010
3.0 was released in 2008
3.4 was released 2014
recent standard library improvements are only available in 3.x


Software
A Python interactive mode makes it easy to test short snippets of code, but there are also a bunch of editors like Sublime Text available as well as bundled development environments IDEs like PyCharm.
We will use:
* Python
* IPython
* Jupyter Notebooks
You could use:
* an editor of your choice like Sublime Text
* an IDE, e.g. PyCharm, Eclipse, spyder, ...
* Jupyter Notebooks in your browser

<a id='object'/>
Everything is an object
<a href=#content>back</a>

Python is an object oriented programming language
Objects are instances of classes
Class = Blueprint of an object
Many objects can be made of the same class

Analogy: Blueprint of a house

All classes have attributes
Attributes can be either data or methods
A method is a function which belongs to an object

Example: the data type integer is a class

Defining a variable (a = 5) makes an instance (object) of class int
It holds the number 5
The variable a is a reference to this object
int has methods defined, for example bit_length()


<a id='datatypes'/>
Standard Data Types
<a href=#content>back</a>

Datatypes are classes $\rightarrow$ Variables are references to instances (objects) of these classes
What do you think are standard data types?
In general we will distinguish between mutable and immutable data types
a mutable object can be changed after it is created, an immutable object can’t


<img src="pics/reference_instance_class.png"  style="width: 70%;"/>
String

String is a sequence of characters
Strings can be single line ( 'This is a String' ) or multiline (''' This is a String...''' )
Indexing can be used to extract elements from a String, e.g. my_string[2] == 'i'
Strings are immutable

```python
    #create string
    typo_str = 'Peeface'
#Oh no... a typo, not a good way to start a book, so change it
typo_str[1] = 'r'


TypeError                                 Traceback (most recent call last)
<ipython-input-18-a40cf4edfc3f> in <module>()
----> 1 typo_str[1] = 'r'
TypeError: 'str' object does not support item assignment
```
End of explanation
"""


print(c)

"""
Explanation: Numerical Data Types

Python has integers, floating point numbers and complex numbers
Python assigns a data type to each variable $\rightarrow$ 1 is an int, 1.0 is a float (duck typing)
Mathematical and Logical Operators can be used, e.g.  
a = 5  
b = 6  
c = a + b
End of explanation
"""


# what is hello_str

# reverse indexing

# stepwise indexing (start:stop:step)

"""
Explanation: Sequence Data Types
List

List is an ordered sequence of items
Items don't have to be of the same type, because actually it's a list of references
Definition of a list: list_a = [5, 3.0, 'Hello']
Indexing starts from 0
Indexing can be used to extract (and set) elements from the list, e.g. list_a[2] would give 'Hello'

```python
    #creating the list
    list_a = [5, 3.0, 'Hello']
#extract third element/object and create reference to it
hello_str = list_a[2]

#mutate list
list_a[2] = 'Good bye'

#print new list
print(list_a)

```
[5, 3.0, 'Good bye']
End of explanation
"""


my_dict = {'one':1, 'two':2, 'three':3}
print(my_dict['one'])

# how to test if certain key is in dict
print('one' in my_dict)
print('four' in my_dict)

"""
Explanation: Tuple

Tuples are immutable lists $\rightarrow$ can't be changed once created
Definition of a tuple: tuple_a = (5 , 3.0, 'Hello')

```python
    #create tuple
    tuple_a = (5, 3.0, 'Hello')
#extract third element/object and create reference to it
hallo_str = tuple_a[2]

#mutate it???
tuple_a[2] = 'Good bye'

python

TypeError                                 Traceback (most recent call last)
<ipython-input-16-2ae0e9084ab6> in <module>()
----> 1 tuple_a[2] = 'Good bye'
TypeError: 'tuple' object does not support item assignment
```
Dictionaries

a dictionary is an unordered collection of key:value pairs
it enables you to map keys and objects
a dictionary is mutable

python
my_dict = {'one':1, 'two':2, 'three':3}
End of explanation
"""


### example immutable
x = 10
y = x
x = x + 1
print('y: ',y)

### example mutable
x_l = ['10']
y_l = x_l
x_l.append('11')
print('y_l: ', y_l)

"""
Explanation: Boolean

A Boolean can only hold the values True or False
Can be compared by logical operators

Mutable vs. Immutable
End of explanation
"""


y = 5
dir(y)

"""
Explanation: <a id='flowcontrol'/>
Operators and Flow control
<a href=#content>back</a>
Operators
Arithmetic Operators

Used for mathematical operations
plus (+), minus (-), multiply (), divide (/), modulus (%), raise (*)

Comparison Operators

Used to compare two values
Returns True or False as result
Greater than (>), lesser than (<), equal (==), not equal (!=)
Attention: = is an assignment, == is the comparison operator

Logical Operators

Used to connect logical statements
and, or and not

Flow Control
for Loop


the for loop is used to iterate over a sequence
python    
for x in y:    
    counter = counter +1


Loop continues until it reaches last item in y

Example: Sum of numbers
```python
        # List of numbers
        numbers = [6, 5, 3, 8, 4, 2, 5, 4, 11]# variable to store the sum
sum = 0

# iterate over the list
for val in numbers:
    sum = sum + val

```


if/elif/else

These are used to make decisions in a program
python
        if x == 2:  # expression
            print(my_string)  # statement
expression is evaluated, if True, statements will be executed
python
        if x == 2:  # expression
            print(my_string)  # body of if
        else:
            print(your_string)  # body of else
expression is evaluated, if True, statement in body of if will be executed, otherwise statement in body of else will be executed
python
        if x == 2:  # 1st expression
            print(my_string)  # body of if
        elif x == 3:  # 2nd expression 
            print(our_string)  # body of elif
        else: 
            print(your_string)  # body of else
elif is short for else if
1st expression is evaluated, if True, statement in body of if will be executed, otherwise 2nd expression will be checked and so on...

while Loop

while iterates over a block of code, as long as a statement is True

Is used when the number of times the loop has to be executed is not known beforehand (compare: for loop)
python
        while x &lt; 2:  # expression
            print(our_string)


expression is checked before entering the loop for the first time



<a id='functions'/>
Functions and Methods
<a href=#content>back</a>
Functions

A function is a group of statements, which perform a specific task
Functions break a program into smaller pieces, making it easier to organize large programs
Make code reusable
python
        def my_statement_printer(statements):
            """This is my docstring:
               Function to print my statements"""
            for statement in statements:
                print('I think ' + statement)
def is the keyword for the function definition
Parameters or arguments are objects which are passed to the function when calling it
A docstring contains a description of what the function does
In the function body are the tasks performed by the function
Function can have a return statement, if no return value is given the function returns None

Example of a Function
python
        def add(num1,num2):
            """This function adds two numbers"""
            return num1 + num2             
* To call this function, we need to type the function name and the arguments
python
print(add(2,3))
* If you don't now what a function does, you can call the docstring
python
print(add.__doc__)
* The return statement exits a function
Parameters inside the Function (Scope)


A variable defined inside a function is not visible outside the function
python
def func():
    x = 10
print(x)
    ```
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-3-fc17d851ef81> in <module>()
    ----> 1 print(x)
NameError: name 'x' is not defined
* Thexinsidefuncis not visible outside, so they can have the same name
*x``` inside func is a local variable inside the function 


Default values
python
        def add(num1,num2=1):
            """This function adds two numbers, if no second number is defined it adds one to num1."""
            return num1 + num2   
Methods

A method is a function inside a class


<a id='classes'/>
Classes, Objects, Instances
<a href=#content>back</a>
As already mentioned everything, that means every thing in python is an object. 
An object is an instance of a class, which defines which attributes and methods an object holds. 

class is the keyword for class definition
a class holds attributes (data and methods)
using python's dir argument one can list all methods of an object
End of explanation
"""


print(y.bit_length())

"""
Explanation: you see: y is not only a number, it has a lot of methods which we can use
End of explanation
"""


import time

class MinimalCake:
    
    def __init__(self, eier=2, mehl=500, milch=250):
        self.eggs = eier
        self.flour = mehl
        self.milk = milch
        self.stirred = False
    
    def stir(self):
        print('stirring...')
        time.sleep(2)
        print('...dough')
        self.stirred = True
        

one_minimal_cake = MinimalCake()
print(one_minimal_cake.eggs, one_minimal_cake.stirred)

one_minimal_cake.stir()
print(one_minimal_cake.stirred)

"""
Explanation: Creating your own class
<img src="pics/cakes.jpg"  style="width: 60%;"/>
which ingredients have cakes in general? $\rightarrow$ data attributes of a class
what can happen with cakes? $\rightarrow$ methods of a class
End of explanation
"""


