Created on 18 Oct 2018 ;    Modified on 24 Mar 2019 ;    Translationitalian

edX: course Introduction to Computer Science and Programming Using Python

I like to win easy, so I followed the course Introduction to Computer Science and Programming Using Python that MITx delivers trought edX. Here are some observations concerning it ...

and its shining certificate :-).

Type of content

Since it is an Introduction ..., I expected more a higher school content than from university.

And indeed, on one hand I have to confirm this first sensation. I didn't found very complex contents [1].

On the other hand, the rigor of the exposition of concepts is definitely good: although without being formal, it is precise, concrete and effective.

So we start practically from scratch, to give the student the base tools needed to grow up in the IT world.

The outline program is as follows:

  • Python basics;
  • simple programs;
  • structured types;
  • good programming practices;
  • object oriented programming;
  • algorithmic complexity;
  • plotting.

The use of Python is not the purpose of the course, but the tool to learn the basic concepts. And this is understood by noting titles such as: good programming practices, and algorithmic complexity.

The part related to the exercises is also well structured.

All the exercises are good to deal with, and are also proposed in fairly complex contexts.

At first sight they can be intimidating, but if you continue without being discouraged, you can observe that the context is organized appropriately to propose affordable exercises. And to point out how it is possible to divide complex problems in simpler units, which cooperate with each other.

Some goodies

Although accustomed to the subject, here and there I found some sympathetic notions. Here I report them.

Physical capacity of a processing system

Regarding the calculation speed. Current computers are capable to run billions of operations per second.

I know this.

What I have never noticed is how high this calculation capacity is. The example reported by prof. Eric Grimson is interesting:

... if you have a lamp at a distance of about 30 cm, when you turn it on, in the time when the light starts from the bulb and reaches you, your computer performed two operations ...

About the dimension of memory. The fact that in 100 GByte is possible to record about one and a half million books of medium length, it is impressive.

The computer I am using to write this article has a memorization capability over 500 GBytes: 7.5 million books! Be surrounded by 7.5 million books is my heavenly dream.

Types of knowledge

I know the fact that exists descriptive [2] and imperative [3] knowledge from the time of the university thesis.

But hear it after so many years of work with imperative procedures has earned me a nostalgic dip into the past.

Equivalence of programming languages

Turing has shown that with six fundamental operations (I emphasize: six), it is possible to execute any algorithm to solve calculable problems [4].

Modern programming languages ​​provide many more of six operations. But they are all equivalent to the basic language invented by Turing. And, as a result, they all solve the same class of problems.

After that: some are more effective in one context than in another, but the potential does not change.

In input it may be necessary to do casting

Maybe I do not use the input statement very often, but I always forget that its output is always a string, even when the user is asked to type in a number. Therefore the need to make casting when needed.

The float equality test can give problems

This is a concept that knows anyone who has some experience, but highlighting it from the first steps is not bad. So do not run float1 == float2, but based on abs(float2-float1) <epsilon.

Use docstrings as specific of the function

This surprised me. The importance of using docstring to document the function is highlighted by everyone.

However I haven't realized I can use docstring to document a usage specification of the function itself. But it makes perfect sense!

So, indicate:

  • the assumptions that the designer makes for the function call;
  • the consequent guarantees regarding behaviour and values ​​returned by function, if called correctly.

It's a real contract.

Recursion and Tower of Hanoi

Definitely , prof. Grimson is a fan of recursion.

Personally I find this instrument very elegant but usually not useful, as it stresses the use of the stack.

However it exists a context in which it is truly remarkable: the solution of the problem of the Tower of Hanoi. Without the use of recursion, it's really hard :-)

List mutation operations

This is a clear concept for those coming from c language, but for beginners it has to be well digested. And sometimes it makes mistakes even those who are not beginners (i.e. the writer). So:

  • sorted (aList) returns an ordered copy of aList;
  • aList.sort () changes in place list aList, sorting it in ascending order;
  • also aList.reverse () changes in place aList, sorting it in descending order.

Also beware of the concept of alias. This is the bind to another name, which becomes synonymous of the list.

For example: anotherList = aList, causes anotherList to see the same memory area as aList.

Mutation, alias (== synonym) and cloning (that is: aList[:]) are three concepts to hold strictly under control.

In particular do not change a list while you are iterating over it. Rather use a copy of the list to make the iteration, changing the original.

A last note about an operation seldom viewed on lists:

for i in range(dim):
    aList += [i]

it creates a list with dim elements, each with value as dim. I.e. with dim == 10:

>>> print(aList)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Apply a function repeatedly

It is not a usual operation, but in certain areas (data science) it is common.

In practice it is a matter of applying a function to all the elements of a list, returning the list of the return values ​​of the function.

But it is also possible to do the opposite: apply an argument to a list of functions.

These games are known as higher order programming (HOP for friends), and are easily implemented using Python [5].

However Python allows you to do this and more with the map function, which produces an iterable.

Hunting for errors ...

... using the bisection of the code! This is new to me.

In practice it is about dividing the code in half and checking if the error occurs before or after the chosen point. Then proceeding accordingly, as if you are searching an element in an ordered list using bisection.

Use of assertions as defensive programming

Also this is new to me, and it's interesting.

The prof. Grimson suggests to use assert to verify that:

  • the types, and possibly the range, of the input parameters of the functions are respected;
  • similarly for the output of the functions, in order to avoid the propagation of the error.
Using the class to launch an instance method

It is not usual, but it can be done. For example:

>   class Animal (object):
...     def __init __ (self, name):
...         self.name = name
...     def __str __ (self):
...         return "I am "+ self.name
...
> prince = Animal (" Prince ")
> print (Animal (__ str __ (prince))
I am Prince

in which we called the prince.__ str__() method passing by the class of the instance.

Generators

Finding this topic surprised me. In my opinion generators aren't matter for beginners. On the other hand, I have to say that it makes sense to immediately understand what they consist of, and what are the pros (and cons).

However, as usual, the explanation, is direct and clear.

Conclusion

A course ab initio, which I would recommend to those who want to approach the world of computer science, without having pre-established specialized bases.

The only disadvantage I see: it is in English language. And at the time of writing, there aren't Italian subtitles.


[1]At least this was my impression. But I'm working in IT for many years. So it's possible a beginner coud feel a little different.
[2]Declarative knowledge exposes a fact. For example the phrase "Albert Einstein was German" is declarative knowledge .
[3]An imperative knowledge explains how to do something. For example, the phrase "Break the egg shell and pour the contents into a bowl" is a piece of iterative procedure to make an omelette.
[4]There are problems that can not be solved in a finite number of operations. These are the non-calculable problems.
[5]As shown in the course: there are several examples of this type.