1. Intro
1.1. The problem with learning Python
Learning Python is terrible.
All tutorials start with the amazement that you can have variables (WOW!) to
which you can assign values(Hurray!!). And, although I forced myself to start a number
of those courses, I just cannot spend hours going through that kind of
basics anymore.
Most courses will stop at some point stop, inviting you to do your
own coding to learn further. And that is mostly the point that it gets interesting.
So, none of the tutorials work and all stop where it gets interesting.
Furthermore, Python has a number of inconsistencies and bizarre concepts that
make the language harder to learn. Did I just say language? I meant languages,
because the changes between version 2 and 3 make it often impossible to
exchange programs between them.
As a tutorial exercise, I'll be rewriting my TCL/Tk application for
image administration in Python.
1.2. Quick language overview
1.2.1. Basic concepts
Python is an Object language. So most of the code will be in
classes or will be calling classes.
Python uses an indent to create blocks, in stead of { }, like in C/C++, Perl,
go, java, PHP, Scala etcetera or do/done or the likes. Python is very sensitive
to spacing. A block is ended with an empty line.
Comments are marked with #, which is normal for a scripting language.
Python has all the normal flow controls, while, for if-then-else. The syntax
is, that an indented block is started with a colon, for example:
for item in iterable_collection: # do something
Associative arrays (hashes in Perl) are called dictionaries
and behave more or less that same as Perl's hashes:
plaatjes = { 'molen' = 'mooi', 'straat' = 'lelijk', 'cavia' = 'lief', } for key, value in plaatjes.iteritems(): print key, value molen mooi straat lelijk cavia lief
1.2.2. Let's have an argument
Python allows two types of arguments:
-
positional parameters
-
named parameters (called keyword parameters in Python)
Positional parameters are what every language uses. Keyword parameters in general get
an initial value and they are optional. As an example:
def hello (greet='hi',dest='all the people'): print greet, " to ", dest hello() hello(dest='you')
If you do not know (or care) how many positional parameters and/or keyword
parameters you get, you can use the c-style pointers:
def print_args(*args, **kwargs): print 'Positional:', args print 'Keyword: ', kwargs for key in kwargs.keys(): print "Key=",key," Value=",kwargs[key] if key == 'foo' : print "JA HOOR" print_args(1, 2, foo='bar', stuff='meep')
Obviously, it's nothing like c's pointers, but it's easier to remember like that.
1.2.3. Lists and references
A special place in hell should be reserved for the one who invented references in Python.
Consider the following:
a = [1, 2, 3] b = a a = [] print(a) print(b) a = [1, 2, 3] b = a del a[:] print(a) print(b) a = [1, 2, 3] b = a[:] del a[:] print(a) print(b)
Which gives as output:
[] [1, 2, 3] [] [] [] [1, 2, 3]
Obviously.
This can only be explained by the fact that
a = [1, 2, 3]
assigns a reference to the list
[1, 2, 3]
to the variable
a
and the line
b = a
assigns the value of a to b. That means that now,
a
and
b
both have a reference to the same
[1, 2, 3]
So when we do
a = []
a will be a reference to an empty list and b will still have a reference to the original list.
However, if I start doing operations on a list with
del a[:]
it affects the
list
and not the reference
to
the list. So that means that
b
(which is a reference to the same list) will now also point to the empty list.
Finally,
b = a[:]
forces a copy of a. So, because it is a copy, emptying a
will not empty b.
Pythons garbage collector for orphans seems effective enough, so you don't have to worry
about lists that are unrefferencable.
1.2.4. Tuples
Tuples are lists that you cannot change. Because they are static, they are faster.
And they use different parentheses.
That is all there is to know about them.
Many Python zealots will start talking about mutable and immutable objects. They will
also point to semantics, for example:
import time time.localtime() (2008, 2, 5, 11, 55, 34, 1, 36, 0)
where, if you delete the days, the minutes become hours. So this is why you
have time in tuples instead of lists.
1.2.5. Variable scoping
Because Python does not allow you to scope variables explicitly (PEP 20:
Explicit is better than implicit), Python uses the following rules:
-
If a variable is declared global it is assumed to be part of the global namespace.
-
If a variable is declared nonlocal it is part of the parent namespace.
-
If you assign a value to a variable, it is assumed to be part of the local namespace, from the beginning of that context.
-
If you do not assign anything to a variable, it assumed implicitly to be part of the parent namespace
-
Mutating an object (for example deleting parts of a list) is not considered as an assignment
The real fun starts when there are multiple nested namespaces...
1.3. Input Output
In the previous sections, al number of
print
statements have been used.
Reading stdin is a bit more difficult. If you want to read a number,
you can use:
value=input('prompt')
However, if you need a string as input, you must use: