5 + 5

x = 5
y = 'Hello There'
z = 10.5

x + 5

"""
Explanation: Quick note about Jupyter cells
When you are editing a cell in Jupyter notebook, you need to re-run the cell by pressing &lt;Shift&gt; + &lt;Enter&gt;. This will allow changes you made to be available to other cells.
Use &lt;Enter&gt; to make new lines inside a cell you are editing.
Code cells
Re-running will execute any statements you have written. To edit an existing code cell, click on it.
Markdown cells
Re-running will render the markdown text. To edit an existing markdown cell, double-click on it.
<hr>

Common Jupyter operations
Near the top of the https://try.jupyter.org page, Jupyter provides a row of menu options (File, Edit, View, Insert, ...) and a row of tool bar icons (disk, plus sign, scissors, 2 files, clipboard and file, up arrow, ...).
Inserting and removing cells

Use the "plus sign" icon to insert a cell below the currently selected cell
Use "Insert" -> "Insert Cell Above" from the menu to insert above

Clear the output of all cells

Use "Kernel" -> "Restart" from the menu to restart the kernel
click on "clear all outputs & restart" to have all the output cleared



Save your notebook file locally

Clear the output of all cells
Use "File" -> "Download as" -> "IPython Notebook (.ipynb)" to download a notebook file representing your https://try.jupyter.org session

Load your notebook file in try.jupyter.org

Visit https://try.jupyter.org
Click the "Upload" button near the upper right corner
Navigate your filesystem to find your *.ipynb file and click "open"
Click the new "upload" button that appears next to your file name
Click on your uploaded notebook file

<hr>

References

https://try.jupyter.org
https://docs.python.org/3/tutorial/index.html
https://docs.python.org/3/tutorial/introduction.html
https://daringfireball.net/projects/markdown/syntax

<hr>

Python is interpreted


Python is an interpreted language, in contrast to Java and C which are compiled languages.


This means we can type statements into the interpreter and they are executed immediately.
End of explanation
"""


x = 1
print ('The value of x is ', x)

x = 2.5
print ('Now the value of x is ', x)

x = 'hello there'
print ('Now it is ', x)

"""
Explanation: Assignments versus equations


In Python when we write x = 5 this means something different from an equation $x=5$.


Unlike variables in mathematical models, variables in Python can refer to different things as more statements are interpreted.
End of explanation
"""


print (round(3.14))

help(round)

import builtins
dir(builtins)

"""
Explanation: Calling Functions
We can call functions in a conventional way using round brackets
End of explanation
"""


print (y)

y + 5

"""
Explanation: Later we will discuss how to built our own function
Types


Values in Python have an associated type.


If we combine types incorrectly we get an error.
End of explanation
"""


type(1)

type('hello')

type(2.5)

type(True)

type(y)

"""
Explanation: The type function

We can query the type of a value using the type function.
End of explanation
"""


result = None

"""
Explanation: Null values


Sometimes we represent "no data" or "not applicable".  


In Python we use the special value None.


This corresponds to Null in Java or SQL.
End of explanation
"""


print(result)

type(result)

"""
Explanation: When we fetch the value None in the interactive interpreter, no result is printed out.
End of explanation
"""


result is None

x = 5
x is None

"""
Explanation: We can check whether there is a result or not using the is operator:
End of explanation
"""


x = 100
print (type(x))
print (x)

y = float(x)
print (type(y))
print (y)

print (int(y))

"""
Explanation: Converting values between types


We can convert values between different types.


To convert an integer to a floating-point number use the float() function.

To convert a floating-point to an integer use the int() function.
End of explanation
"""


print (ord('a'))

print (chr(97))

"""
Explanation: Converting to and from ASCII values

The functions chr() and ord() can be used to convert characters from and to ASCII.
End of explanation
"""


y = 'hello'
print ('The type of the value referred to by y is ', type(y))
y = 5.0
print ('And now the type of the value is ', type(y))

"""
Explanation: Variables are not typed

Variables themselves, on the other hand, do not have a fixed type.
It is only the values that they refer to that have a type.
This means that the type referred to by a variable can change as more statements are interpreted.
End of explanation
"""


1//5

1/5

1.0 / 5.0

1 + 1

'a' + 'b'

'1' + '1'

"""
Explanation: Polymorphism

The meaning of an operator depends on the types we are applying it to.
End of explanation
"""


x = 5
if x > 0:
    print ('x is strictly positive')
    print (x)
    
print ('finished.')

x = 0
if x > 0:
    print ('x is strictly positive')
print (x)
    
print ('finished')

"""
Explanation: Conditional Statements and Indentation


The syntax for control structures in Python use colons and indentation.


Beware that white-space affects the semantics of Python code.
End of explanation
"""


l = ['first', 'second', 'third']
print (l)

"""
Explanation: Lists
We can use lists to hold an ordered sequence of values.
End of explanation
"""


another_list = ['first', 'second', 'third', 1, 2, 3]
print (another_list)

"""
Explanation: Lists can contain different types of variable, even in the same list.
End of explanation
"""


l.append('fourth')
print (l)

"""
Explanation: Mutable Datastructures
Lists are mutable; their contents can change as more statements are interpreted.
End of explanation
"""


X = [1, 2, 3]
Y = X

"""
Explanation: References


Whenever we bind a variable to a value in Python we create a reference.


A reference is distinct from the value that it refers to.


Variables are names for references.
End of explanation
"""


X.append(4)
print(X)

print(Y)

"""
Explanation: The above code creates two different references (named X and Y) to the same value [1, 2, 3]


Because lists are mutable, changing them can have side-effects on other variables.


If we append something to X what will happen to Y?
End of explanation
"""


X = [1, 2]
Y = [1]
Y.append(2)

X == Y

X is Y

Y.append(3)
X


X = Y

X is Y

"""
Explanation: State and identity


The state referred to by a variable is different from its identity.


To compare state use the == operator.


To compare identity use the is operator.


When we compare identity we check equality of references.


When we compare state we check equality of values.
End of explanation
"""


for i in l:
    print (i)

"""
Explanation: Iteration

We can iterate over each element of a list in turn using a for loop:
End of explanation
"""


for i in [0, 1, 2, 3]:
    print ("Hello!")

"""
Explanation: To perform a statement a certain number of times, we can iterate over a list of the required size.
End of explanation
"""


for i in range(4):
    print ("Hello!")

"""
Explanation: For loops with the range function

To save from having to manually write the numbers out, we can use the function range() to count for us.  As in Java and C, we count starting at 0.
End of explanation
"""


print (l[0])

print (l[1])

"""
Explanation: List Indexing

Lists can be indexed using square brackets to retrieve the element stored in a particular position.
End of explanation
"""


print (l[0:2])

"""
Explanation: List Slicing


We can also a specify a range of positions.  


This is called slicing.


The example below indexes from position 0 (inclusive) to 2 (exclusive).
End of explanation
"""


print (l[:2])

"""
Explanation: If we leave out the starting index it implies the beginning of the list:
End of explanation
"""


print (l[2:])

"""
Explanation: If we leave out the final index it implies the end of the list:
End of explanation
"""


print (l[-1])

print (l[:-1])

"""
Explanation: Negative Indexing

Negative indices count from the end of the list:
End of explanation
"""


tuple1 = (50, 'hello')
print(tuple1)

print(tuple1[0])

type(tuple1)

"""
Explanation: Collections


Lists are an example of a collection.


A collection is a type of value that can contain other values.


There are other collection types in Python:

tuple
set
dict



Tuples


Tuples are another way to combine different values.


The combined values can be of different types.


Like lists, they have a well-defined ordering and can be indexed.


To create a tuple in Python, use round brackets instead of square brackets
End of explanation
"""


tuple1.append(2)

tuple1[0] = 5

"""
Explanation: Tuples are immutable

Unlike lists, tuples are immutable.  Once we have created a tuple we cannot add values to it.
End of explanation
"""


X = set([1, 2, 3, 3, 4])
print(X)

type(X)

"""
Explanation: Sets


Lists can contain duplicate values.


A set, in contrast, contains no duplicates.


Sets can be created from lists using the set() function.
End of explanation
"""


X = {1, 2, 3, 4}
type(X)

"""
Explanation: Alternatively we can write a set literal using the { and } brackets.
End of explanation
"""


X.add(5)
print(X)

"""
Explanation: Sets are mutable

Sets are mutable like lists:
End of explanation
"""


X.add(5)
print(X)

"""
Explanation: Duplicates are automatically removed
End of explanation
"""


X[0]

"""
Explanation: Sets are unordered


Sets do not have an ordering.


Therefore we cannot index or slice them:
End of explanation
"""


X = {1, 2, 3}
Y = {4, 5, 6}
X.union(Y)

"""
Explanation: Operations on sets

Union: $X \cup Y$
End of explanation
"""


X = {1, 2, 3, 4}
Y = {3, 4, 5}
X.intersection(Y)

"""
Explanation: Intersection: $X \cap Y$:
End of explanation
"""


X - Y

"""
Explanation: Difference $X - Y$:
End of explanation
"""


person = {'name':'sofian','gender':'male', 'age':17}
person['new'] = 'new'
print (person.keys())
print (person.values())
print (person['name'])
print (person)

"""
Explanation: Dictionary

Key Value list
End of explanation
"""


def squared(x):
    return x ** 2

print (squared(5))

"""
Explanation: Defining new functions
End of explanation
"""


def squared(x):
    result = x ** 2
    return result

print (squared(5))

print (result)

"""
Explanation: Local Variables


Variables created inside functions are local to that function.


They are not accessable to code outside of that function.
End of explanation
"""


print(squared)

y = squared
print (y)

print (y(5))

"""
Explanation: Functional Programming


Functions are first-class citizens in Python.


They can be passed around just like any other value.
End of explanation
"""


list(map(squared, [1, 2, 3, 4]))

"""
Explanation: Mapping the elements of a collection


We can apply a function to each element of a collection using the built-in function map().


This will work with any collection: list, set, tuple or string.


This will take as an argument another function, and the list we want to apply it to.


It will return the results of applying the function, as a list.
End of explanation
"""


[squared(i) for i in [1, 2, 3, 4]]

"""
Explanation: List Comprehensions

Because this is such a common operation, Python has a special syntax to do the same thing, called a list comprehension.
End of explanation
"""


{squared(i) for i in [1, 2, 3, 4]}

"""
Explanation: If we want a set instead of a list we can use a set comprehension
End of explanation
"""


A = {'x', 'y', 'z'}
B = {1, 2, 3}
{(a,b) for a in A for b in B}

"""
Explanation: Cartesian product using list comprehensions
<img src="files/220px-Cartesian_Product_qtl1.svg.png">
The Cartesian product of two collections $X = A \times B$ can be expressed by using multiple for statements in a comprehension.
End of explanation
"""


first_names = ('Steve', 'John', 'Peter')
surnames = ('Smith', 'Doe')

[(first_name, surname) for first_name in first_names for surname in surnames]

"""
Explanation: Cartesian products with other collections

The syntax for Cartesian products can be used with any collection type.
End of explanation
"""


list(map(lambda x: x ** 2, [1, 2, 3, 4]))

"""
Explanation: Anonymous Function Literals

We can also write anonymous functions.
These are function literals, and do not necessarily have a name.
They are called lambda expressions (after the $\lambda-$calculus).
End of explanation
"""


list(filter(lambda x: x > 0, [-5, 2, 3, -10, 0, 1]))

"""
Explanation: Filtering data


We can filter a list by applying a predicate to each element of the list.


A predicate is a function which takes a single argument, and returns a boolean value.


filter(p, X) is equivalent to ${ x : p(x) \; \forall x \in X }$ in set-builder notation.
End of explanation
"""


list(map(ord, 'hello world'))

''.join(list(filter(lambda x: x != 'l' , 'hello world')))

"""
Explanation: We can use both filter() and map() on other collections such as strings or sets.
End of explanation
"""


data = [-5, 2, 3, -10, 0, 1]
[x for x in data if x > 0]

"""
Explanation: Filtering using a list comprehension


Again, because this is such a common operation, we can use simpler syntax to say the same thing.


We can express a filter using a list-comprehension by using the keyword if:
End of explanation
"""


