Foundations of programming

Lecture ten - Python - introduction

Work Plan

  1. Introduction, types of programming languages, pseudocode
  2. Variables, data types
  3. Simple instructions and tricks
  4. Pointers and arrays
  5. Functions and Procedures
  6. Input / Output
  7. Data Structures
  8. Modern C++
  9. Error Types /Debug
  10. Python
  11. Python II
  12. Software development in XXI century
  13. Final exam / Test

Python

image

Python's name is derived from the British comedy group Monty Python, (as a tribute from the Python creator Guido van Rossum).

Python

Python is a high level language suitable for rapid development

Features:
A multiparadigm language - multiple programming styles are supported (procedural, object-oriented, functional, etc.)
Interpreted rather than compiled
Dynamically typed (easy for generics)

Python has become one of the core languages of scientific / AI computing.

Python history

Guido van Rossum started to work on Python worked in the late 1980s as a "project for fun".

First version of Python (version 0.9.0) was published in February 1991. This release included already exception handling, functions, and the core data types of list, dict, str and others. It was also object oriented and had a module system

Python version 1.0 was released in January 1994 - added functional programming tools lambda, map, filter and reduce.

Python 2.0 was introduced in October 2000 - added list comprehensions, a full garbage collector and unicode support.

Python history

Next major release was Python 3.0 (also known as "Python 3000" and "Py3K") from 2008.

Python 3 is not backwards compatible with Python 2.x.

The emphasis in Python 3 had been on the removal of duplicate programming constructs and modules.

Python 2 vs Python 3

For beginners there is no real difference between Python 2 & 3. Basic are the same (except for print, and raw_input).

Python 2.x is legacy, Python 3.x is the present and future of the language.

The official end-of-life date for the Python 2 series is 2020.

Many programs and applications still use Python 2.x, so it is very much "alive". However, nowadays 344 of the 360 top packages for Python support 3.x.

Choose language according to libraries you want to use in your program.

Python 3

Most important changes in Python 3.0:
> Print is now a function (not a statement)
> Views and iterators instead of lists ( d.iteritems() -> iter(d.items()) )
> The rules for ordering comparisons have been simplified.
> There is only one integer type left, there is no long integer anymore
> The division of two integers returns a float instead of an integer. "//" can be used to have the "old" behaviour.
> Text Vs. Data Instead Of Unicode Vs. 8-bit (All text is Unicode; however encoded Unicode is represented as binary data. The type used to hold text is str, the type used to hold data is bytes)

Some of Python 3 features have been backported to the backward-compatible Python 2.6.x and 2.7.x version series.

Philosophy

Core philosophy of Python is summarized in the document The Zen of Python:
Beautiful is better than ugly
Explicit is better than implicit
Simple is better than complex
Complex is better than complicated
Readability counts

Python

Python looks like a pseudocode.

Goal: express concepts in fewer lines of code than might be used in languages such as C++ or Java.

Python code is usually stored in text files with the file ending ".py".

To run our Python program from the command line we use:

$ python myprogram.py

In Linux we can add the following

#!/usr/bin/env python

to the top to make it runnable.

We can also use interactive interpreter (shell) to execute commands "as we type them".

Python pros and cons

Positives:
Clean, readible code,
Productivity,
Integrates easy with other languages.
Extensive Support Libraries
Negatives:
Weak in mobile computing,
Slower than compiled languages.
Require more testing to find errors.

Blocks, indents

A code block is a group of statements that, together, perform a task.

Python programs get structured through indentation, i.e. code blocks are defined by their indentation.

Exemplary error:

IndentationError: expected an indented block (<string>, line XXX)

All statements with the same distance to the right belong to the same block of code, i.e. the statements within a block line up vertically.

image

This principle makes it easier to read and understand other people's Python code.

Tabs or Spaces?

Spaces are the preferred indentation method.

Tabs should be used solely to remain consistent with code that is already indented with tabs.

In most of the editors there's a default to put 4 spaces on pressing the TAB button. It is a custom to use 4 spaces as indents in Python codes.

Python 3 disallows mixing the use of tabs and spaces for indentation.

Python 2 code indented with a mixture of tabs and spaces should be converted to using spaces exclusively.

Indents

Example, what is wrong about such a code checking whether the number is prime?

def is_prime(number):
    for divisor in range(2,number):
        if (number % divisor) == 0:
            return False
        return True

Notice that neither semicolons or curly brackets are necessary in Python.

PEP 8 - Style Guide for Python Code

Good practices

Variable names in Python can contain alphanumerical characters a-z, A-Z, 0-9 and some special characters such as _.

Normal variable names must start with a letter.

By convention, variable names start with a lower-case letter, and Class names start with a capital letter.

Keywords list:

and, as, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, while, with, yield

Input

Example of reading the data (Python 2.x):

name = raw_input("What is your name? ")
city = raw_input("What city do you live in? ")
state = raw_input("What state is that in? ")

print name, "from", city, state

Input

Python has two key functions to deal with end-user input, one called raw_input() and one called input().

When a program is running and these functions are called, the system will freeze, waiting for the end-user to enter something.

When the user enters something and hits 'enter', a string is returned from these functions. So on execution of the statement:

result = raw_input()

Python will wait for the end-user to enter something. If the user types in "abc", then the variable result will have 'abc' in it.

Raw_input

The function raw-input() always returns a string. So if the user enters 7, Python interprets it as the string '7'.

Sometimes this is fine, but often we want to perform computations on numbers, and as far as the computer is concerned, '7' is a symbol and not a number.

If you want to 'interpret' input as an integer, you need to convert it. Python provides some type conversion functions to do so, such as int and float.

x=int('7') # puts the integer 7 into x.
f=float('7.7') #puts the floating point number 7.7 into f.

Input

The function input() converts things automatically.

'input()' basically looks at what the user enters, and automatically determines the correct type.

age = input('enter your age:')
doubleAge = age*2

The only problem with 'input' is you have to assume the user will enter what you are expecting. If they don't, your program will crash.

Input

Wrong:

age = raw_input("Pardon my rudeness, but how old are you? ")
print "Wow! You look like you could be", age - (0.15*age), "!!"

As raw_input returns string.

age = input("Pardon my rudeness, but how old are you? ")

input() evaluates the input as Python code.

int(argument) forces the argument to be an integer by rounding down.

print "Wow! You look like you could be", int(age - (0.15*age)), "!!"

Input Python 3

The input function behaves like the raw_input function from Python 2.

eval(input()) works like input() in Python 2.

The eval functions takes a string as argument and evaluates this string as a Python expression. The result of an expression is an object.

Input Python 3

Example, input:

x = input()
>> 12
print(x)

x = x + 2

x = eval(x)
x = x + 2
print(x)

Output:

12

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must be str, not int

14

Output

In Python, the print statement is used for command-line output:

>>print 45                      # just prints the number 45
>>print 'my mother said'        # prints the words without the 
>>print interestRate+.2         # prints the evaluated expression, 0.6

In Python 3 print is a function!

Old: print "The answer is", 2*2
New: print("The answer is", 2*2)

Output

Example of printing the data on the screen (Python 3.x):

String formatting examples
print("str1", "str2", "str3")  # The print statement concatenates strings with a space

print("str1", 1.0, False, -1j)  # The print statements converts all arguments to strings

print("str1" + "str2" + "str3") # strings added with + are concatenated without space

print("value = %f" % 1.0)       # we can use C-style string formatting

# this formatting creates a string
s2 = "value1 = %.2f. value2 = %d" % (3.1415, 1.5)
print(s2)

# alternative, more intuitive way of formatting a string 
s3 = 'value1 = {0}, value2 = {1}'.format(3.1415, 1.5)
print(s3)

Output:

str1 str2 str3
str1 1.0 False (-0-1j)
str1str2str3
value = 1.000000
value1 = 3.14. value2 = 1
value1 = 3.1415, value2 = 1.5

Notice that # begins the comment in Python

Methods

Methods on objects are functions attached to the object's class; the syntax:

instance.method(argument)

stands for normal methods and functions execution.

There are two flavors: built-in methods (such as append() on lists) and class instance methods. Built-in methods are described with the types that support them.

Example, methods on integers:

x = 1

# type x. and press TAB
x.bit_length(  x.denominator  x.imag         x.real         
x.conjugate(   x.from_bytes(  x.numerator    x.to_bytes( 

Modules

Modules are functions and variables defined in separate files (sth. like headers in C++).

Items are imported using keywords from or import.

Modules are namespaces in Python, we access function by the name of the module followed by a dot and name of the function. It helps preventing to use two functions with the same name.

Most of the functionality in Python is provided by modules. The Python Standard Library is a large collection of modules that provides cross-platform implementations of common facilities such as access to the operating system, file I/O, string management, network communication, and much more.

Import

import math

This includes the whole module and makes it available for use later in the program. For example, we can do:

import math

x = math.cos(2 * math.pi)

print(x)

Alternatively, we can chose to import all symbols (functions and variables) in a module to the current namespace (so that we don't need to use the prefix "math." every time we use something from the math module:

from math import *

x = cos(2 * pi)

print(x)

Import

Once a module is imported, we can list the symbols it provides using the dir function:

import math
print(dir(math))

Output:

['__doc__', '__file__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']

Operators

The boolean operators are spelled out as the words and, not, or.

Bitwise operators (~,^,|,&,<<,>>) are like in C/C++.

The power operators in python are two asterisks:

>> a = 2 ** 2
4

Variables in Python

In Python (interpreted languages) the type of a variable can change during the execution of the script:

i = 42             # data type is implicitly set to integer
i = 42 + 0.11      # data type is changed to float
i = "forty"        # and now it will be a string  

Python automatically takes care of the physical representation for the different data types, i.e. an integer values will be stored in a different memory location than a float or a string.

Memory representation

Unlike in C for interpreted languages variables can change a place in the memory they are assign to :

>>> x = 3
>>> y = x
>>> y = 2

First y points to the same place as x then it changes its pointer.

image

Which means that variable is not a place in the memory but a pointer to a place in the memory.

Variables

How can we prove that x and y really reference the same object after the assignment y = x ?

The identity function id() can be used for this purpose.

Every instance (object or variable) has an identity, i.e. an integer which is unique within the script or program, i.e. other objects have different identities.

Input:

x = 42
print(id(x))

y = x
print(id(x), id(y))

y = 78
print(id(x), id(y))

Output:

10107136
10107136, 10107136
10107136, 10108288

Immutable

Mutable objects can be changed in place Immutable objects cannot be modified once created

Simple types in Python are immutable objects and it is not possible to modify its value. What we can do is to create new element from an original one.

Input:

a = "hello, world!"
a[2] = 'z'  

a.replace('l', 'z', 1)

Output:

File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

'hezlo, world!'

Types

Operations on an object may fail, signifying that the given object is not of a suitable type.

Python is strongly typed, forbidding operations that are not well-defined (for example, adding a number to a string) rather than silently attempting to make sense of them.

Typecasting

Input:

x = 1.5

print(x, type(x))


isinstance(x, float)

x = int(x)
print(x, type(x))

Output:

1.5 <class 'float'>
True
1 <class 'int'>    

Typecasting

The / operator always performs a floating point division in Python 3.x. This is not true in Python 2.x, where the result of / is an integer.

Input:

x = 7
print 1/x
print 1./x
print 1/float(x)

Output:

0
0.14285714285714285
0.14285714285714285

== vs is

Operator == is used to compare values while is compare references:

Input:

a = [1,2]
b = [1,2]
c = a
a is b
a is c
a == b

Output:

False
True
True

In given example c can be interpreted as an alias for variable a.

If statement

General format:

if <condition is True>:

<code to execute if condition is True>

else:

<code to execute if condition is False>

Example:

# Get user's height
height = input("How tall are you? ")

if height > 180:
    print "wow you're tall!"

if height >= 156:
    print "ok"    
else:
    print "too short"

For in

General format:

for some_variable in range:

do_something

Example:

for x in [1,2,3]:
    print(x)

string = "Hello World"
for x in string:
    print x   

For loop examples using range. Range with 1 argument goes from 0 through n-1:

for num in range(10):
    print num       

For with range

Range with 2 arguments goes from the first number through the last-1:

for num in range(7, 15):
    print num

Range with 3 arguments goes from the first number through the second-1, in increments determined by the third number:

for num in range(2, 12, 2): 
    print num

The ''range'' is seen so often in for statements that you might think range is part of the for syntax. It is not: it is a Python built-in function which returns a sequence, which meets the requirement of providing a sequence for the for statement to iterate over.

While

A loop that will be repeated until a given condition changes:

count = 1
print "Count is initially", count

while count < 100:
    count = count * 9   
    print "Now count is", count     

Same as in C++ only difference is the use of :.

While, else

while/else, the else clause is only executed when your while condition becomes false. If you break out of the loop, or if an exception is raised, it won't be executed.

while n >= 0:
    print n
    n -= 1
else:
    print "You've failed to enter a nonnegative number."        

Functions

Functions are first-class objects, which means they can be:
assigned to a variable
an item in a list (or any collection)
passed as an argument to another function.
return values of functions

You can define default values for argument in functions.

All functions in Python have a return value. Functions without a return return the special value None.

def ret_5():
    print 5

print ret_5()

Output:

5
None

Functions

To define function we use keyword def

def <name>(arg1, arg2, ..., argN):

<statements> return <value>

Return sends a result back to the caller.

Arguments are passed by assignment. Assignment to argument names don't affect the caller unless argument is mutable.

Arguments and return types are not declared.

Functions

Example:

base = 10
exp = 4

def hello_world():
    base = 20
    print "inside of helloworld base is", base
    return "Hello, world!"

print hello_world()
print "outside of helloworld base is", base

Output:

inside of helloworld base is 20
Hello, world!
outside of helloworld base is 10

Global / local variables

Variables declared outside the function can be referenced within the function.

But these “global” variables cannot be modified within the function, unless declared global in the function.

y = 0
z = 0

def setx(y):
    global x
    x = y
    global z
    z = 99
    print('x is %d' % x)

print(z)    
print(y)    
setx(10)
print(x)
print(y)
print(z)
0
0
x is 10
10
0
99

Function overloading

There is no function overloading in Python.

The number, order, names, or types of its arguments cannot be used to distinguish between two functions with the same name.

Two different functions can’t have the same name, even if they have different numbers of arguments.

But operator overloading – overloading +, ==, -, etc. is possible using special methods on various classes.

Arrays in Python

Python doesn't have a native array data structure.

Default ordered collection of items is a list.

Definition:

>>> myList=[1,2,3,4,5,6]
>>> myList[2]=100
>>> myList
[1, 2, 100, 4, 5, 6]
>>> myList[2:5]
#sublist from 3 to 6th element
[100, 4, 5]
>>> myList[0:2]=[0,1]
>>> myList
[0, 1, 3, 4, 5, 6]

Basic List operation

Python Expression Results Description
len([1,2,3])
3
Length
[1,2,3]+[1,2,3] [1,2,3,1,2,3] Concatenation
['Hi!'] * 4 [Hi!','Hi!','Hi!','Hi!'] Repetition
3 in [1,2,3] True Membership
for x in [1,2,3]: print x 1,2,3 Iteration

Mutable objects

Some objects contain references to other objects; these are called containers. Examples of containers are tuples, lists and dictionaries. The references are part of a container’s value.

>>> a = [1,2]
>>> b = a
>>> b
[1, 2]
>>> b[0] = 10
>>> a
[10, 2]

String in Python

Python does not support a character type; these are treated as strings of length one, thus also considered a substring.

To access substrings, use the square brackets for slicing along with the index or indices to obtain your substring.

>>> sentence='hello world'
>>> sentence[0]
'h'
>>> sentence[0:5]
'hello'   

Value or reference?

Parameters to functions are reference to objects, which are passed by value.

When you pass a variable to a function, python passes the reference to the object to which the variable refers (the value), not the variable itself.

If the value is immutable, the function does not modify the caller’s variable. If the value is mutable, the function may modify the caller’s variable in-place:

def try_to_modify(x, y, z):
    x = 23
    y.append(42)
    z = [99] # new reference
    print(x)
    print(y)
    print(z)

a = 77    # immutable variable
b = [99]  # mutable variable
c = [28]
try_to_modify(a, b, c)
>> 23
>> [99, 42]
>> [99]
print(a)
>> 77
print(b)
>> [99, 42]
print(c)
>> [28]

Variable-Length Argument Lists

Python allows you to declare two special arguments which allow you to create arbitrary-length argument lists.

This means that each time you call the function, you can specify any number of arguments above a certain number.

def function(first,second,*remaining):
    statement1
    statement2

When calling the above function, you must provide value for each of the first two arguments.

However, since the third parameter is marked with an asterisk, any actual parameters after the first two will be packed into a tuple and bound to "remaining."

def print_tail(first,*tail):
    print tail

print_tail(1, 5, 2, "omega")
print_tail(5, 2, 'omega')

Python files

The io module provides Python’s main facilities for dealing with various types of I/O.

There are two main types of I/O: text I/O, binary I/O.

A concrete object belonging to any of these categories is called a file object.

Text I/O

Text I/O expects and produces string objects.

The easiest way to create a text stream is with open(), optionally specifying an encoding:

f = open("myfile.txt", "r", encoding="utf-8")
In-memory text streams are also available as StringIO objects:

Binary I/O

Binary I/O (also called buffered I/O) expects bytes-like objects and produces bytes objects. No encoding, decoding, or newline translation is performed.

This category of streams can be used for all kinds of non-text data, and also when manual control over the handling of text data is desired.

The easiest way to create a binary stream is with open() with 'b' in the mode string:

f = open("myfile.jpg", "rb")

Close()

When we are done with operations to the file, we need to properly close the file.

Closing a file will free up the resources that were tied with the file and is done using Python close() method.

References

https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-189-a-gentle-introduction-to-programming-using-python-january-iap-2011/lectures/

https://en.wikipedia.org/wiki/Python_(programming_language)

https://github.com/jrjohansson/scientific-python-lectures/blob/master/Lecture-1-Introduction-to-Python-Programming.ipynb

http://www.scipy-lectures.org/language/first_steps.html

https://www.python-course.eu/python3_blocks.php

https://lectures.quantecon.org/py/about_py.html

http://sebastianraschka.com/Articles/2014_python_2_3_key_diff.html

http://www.seas.upenn.edu/~cis391/Lectures/python-tutorial.pdf

http://tdc-www.harvard.edu/Python.pdf