Skip to the content.

Εισαγωγή στη Python

© Γιάννης Κωστάρας


Η Python είναι μια από τις πιο δημοφιλής γλώσσες προγραμματισμού. Δημιουργήθηκε το 1989 από τον Guido van Rossum. Το Python Software Insitute – PSF (Ίδρυμα Λογισμικού Python) ελέγχει την ανάπτυξη της γλώσσας ήδη από την έκδοση 2.1. Βασίζεται στην ιδέα ότι ο κώδικας θα πρέπει να εκφράζει ξεκάθαρα μια ιδέα ή μια εργασία. Γι’ αυτό το λόγο, ένα πρόγραμμα Python είναι μικρότερο από το αντίστοιχο πρόγραμμα σε C/C++, C# ή Java. Επίσης, ένα πρόγραμμα Python μπορεί να τρέξει σε οποιαδήποτε πλατφόρμα (MacOS, Linux, Unix, Windows).
Η Python 3 εκδόθηκε το Δεκέμβριο του 2008 και ένα από τα πιο χρήσιμα χαρακτηριστικά της είναι η υποστήριξη unicode χαρακτήρων.

Κατηγορίες γλωσσών προγραμματισμού

Υπάρχουν πολλές κατηγοριοποιήσεις των γλωσσών προγραμματισμού. Ανάλογα με τον τρόπο εκτέλεσης, χωρίζονται σε:

Οι στατικές γλώσσες προγραμματισμού στοχεύουν σε ταχύτερη εκτέλεση και μεγάλες εφαρμογές. Οι δυναμικές γλώσσες στοχεύουν σε ευκολία χρήσης και μικρότερες εφαρμογές. Με βάση τις παραπάνω κατηγορίες, μπορούμε να πούμε ότι η Python είναι μια αντικειμενοστραφής (αλλά και με στοιχεία συναρτησιακής), δυναμική, μεταφραστική γλώσσα προγραμματισμού.

Εγκατάσταση

Δυστυχώς ή ευτυχώς, υπάρχουν δυο βασικές εκδόσεις της Python που δεν είναι τελείως συμβατές μεταξύ τους. Αυτές είναι η Python 2 και η Python 3. Συνήθως το Ubuntu έρχεται προ εγκατεστημένο και με τις δυο αυτές εκδόσεις. Για την έκδοση 2 δώστε:

$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()

ενώ για την έκδοση 3:

$ python3
Python 3.4.3 (default, Sep 14 2016, 12:36:27) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()

Μπορείτε να τερματίσετε την python είτε με την εντολή quit() είτε με Ctrl-D. Αν δεν είναι εγκατεστημένη κάποια ή και δυο εκδόσεις, τότε κατά τα γνωστά:

$ sudo apt-get install python
$ sudo apt-get install python3 

Αν δεν θέλετε να την εγκαταστήσετε, μπορείτε να τη δοκιμάσετε online σε κάποιο online REPL (Read Eval Print Loop) όπως π.χ. Python shell, REPL ή ideone ή codeskulptor.

Άλλες χρήσιμες εντολές:

$ pydoc
pydoc - the Python documentation tool
...

Η ιστορία δεν τελειώνει όμως εδώ. Υπάρχουν κι άλλοι μεταφραστές (interpreters) αλλά και μεταγλωττιστές (compilers) της γλώσσας όπως π.χ. jython, που είναι μια υλοποίηση της Python σε Java και άρα μπορεί να εκτελεστεί στην εικονική μηχανή της Java (Java Virtual Machine), η ironpython για .NET και Mono, η CPython ως βιβλιοθήκη της C, η IPython, PyPy (Just-In-Time compiler) κ.ά.

Ο Μεταφραστής της Python

Όπως είπαμε, η Python είναι μια μεταφραστική γλώσσα προγραμματισμού. Ο μεταφραστής (interpreter) μεταφράζει τον πηγαίο κώδικα σε κώδικα bytes (.pyc) ώστε να μπορεί να εκτελεστεί από την Εικονική Μηχανή Python (Python Virtual Machine – PVM). Η PVM διαθέτει και συλλέκτη σκουπιδιών (garbage collector), όπως κι η Java, για να ελευθερώνει τη μνήμα από αντικείμενα που δε χρησιμοποιούνται πλέον.

Επεξεργαστές κειμένου Python

Προτού συνεχίσουμε, ίσως θα θέλατε να εγκαταστήσετε κάποιους κειμενογράφους που αναγνωρίζουν τη σύνταξη της Python:

Το πρώτο μας πρόγραμμα Python

Μπορούμε να γράψουμε προγράμματα python είτε στο διαδραστικό περιβάλλον (κέλυφος) που μόλις είδαμε, είτε γράφοντας τα προγράμματά μας σε αρχεία κειμένου με κατάληξη .py και εκτελώντας τα. Ας δούμε μερικά παραδείγματα με το αλληλεπιδραστικό περιβάλλον πρώτα:

$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Καλώς ήρθατε στην Python!"
Καλώς ήρθατε στην Python!
>>> quit()

Η εντολή print τυπώνει ότι ακολουθεί την εντολή στην οθόνη. Η εντολή quit() τερματίζει την python.

$ python3
Python 3.4.3 (default, Sep 14 2016, 12:36:27) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Καλώς ήρθατε στην Python!"
File "<stdin>", line 1
    print "Καλώς ήρθατε στην Python!"
                                    ^
SyntaxError: Missing parentheses in call to 'print'
>>> print ("Καλώς ήρθατε στην Python!")
Καλώς ήρθατε στην Python!
>>> quit()

Μόλις είδατε μια βασική διαφορά μεταξύ των δυο εκδόσεων. Στην python3, η εντολή print() είναι μια συνάρτηση, επομένως χρειάζεται η χρήση παρενθέσεων. Στη συνέχεια, όπου υπάρχουν διαφορές στη σύνταξη μεταξύ των δυο εκδόσεων θα το αναφέρουμε.

Μεταβλητές

Οι μεταβλητές είναι αποθήκες μνήμης όπου μπορούμε ν’ αποθηκεύσουμε διάφορες τιμές. Π.χ. (υποθέτουμε Python2):

>>> my_variable = 43
>>> print my_variable
43

Δηλώσαμε μια μεταβλητή με όνομα my_variable και αποθηκεύσαμε σ’ αυτή την τιμή 43 και στην επόμενη γραμμή εκτυπώσαμε την μεταβλητή αυτή. Παρατηρήστε ότι, αντιθέτως με τις στατικές γλώσσες προγραμματισμού, δεν απαιτείται να δηλώσουμε τον τύπο της μεταβλητής my_variable· αυτός εννοείται από τον τύπο δεδομένων της τιμής εκχώρησης (ακέραιος στο παράδειγμά μας). Μάλιστα, οι δυναμικές γλώσσες προγραμματισμού, όπως η Python, επιτρέπουν ν’ αλλάξετε τον τύπο δεδομένων μιας μεταβλητής κατά τη διάρκεια του προγράμματος:

>>> my_variable = 'Hello'
>>> print my_variable
Hello

Η Python υποστηρίζει διάφορους τύπους δεδομένων:

>>> my_int=7
>>> my_float=1.23
>>> my_bool=True
>>> type(my_int)
<type 'int'>
>>> type(my_float)
<type 'float'>
>>> type(my_bool)
<type 'bool'>
>>> type(my_variable)
<type 'str'>
Τύπος Δεδομένων Τιμές Πράξεις
Λογικός (bool) True, False And, & , or, |, xor, ^, not, ~
Ακέραιος (int)   +, -, *, /, //, %, **
Πραγματικός (float)   +, -, *, /, //, %, **
Αλφαριθμητικό (str) Μέσα σε ' ' ή " " +, *

Το % δηλώνει το υπόλοιπο (modulo) μιας διαίρεσης, το ** την ύψωση σε δύναμη, ενώ το // στρογγυλοποιεί προς τα κάτω (αντίστοιχη της floor):

>>> print 5/4   # πηλίκο, python2
1
>>> print(5/4)  # πηλίκο, python3
1.25
>>> print 5//4  # ακέραιο πηλίκο
1
>>> print 5.0/4.0   # πηλίκο, python2
1.25
>>> print 5.0//4.0  # ακέραιο πηλίκο, python2
1.0
>>> print 5%4   # υπόλοιπο
1
>>> print 2**3  # ύψωση σε δύναμη
8
>>> print my_variable + ' Python!'
Hello Python!
>>> print my_variable*3
HelloHelloHello

ενώ μόλις είδατε τι σημαίνουν οι τελεστές + και * για αλφαριθμητικά! Φυσικά, υπάρχει η προτεραιότητα πράξεων και μπορείτε να την αλλάξετε με χρήση παρενθέσεων:

>>> print 3+6*2
15
>>> print (3+6)*2
18

Τώρα πλέον μπορείτε να εξηγήσετε το παρακάτω:

>>> s = '4' 
>>> print s 
4
>>> print s*4 
4444
>>> print int(s) * 4 
16

Η συνάρτηση int() μετατρέπει από έναν τύπο δεδομένων σ’ έναν άλλο, (από str σε int στην προκειμένη περίπτωση). Η συνάρτηση str() κάνει την αντίστροφη μετατροπή (από int σε str). Υπάρχουν επίσης οι oct(), hex() και bin(). Υπάρχει όμως και μια δεύτερη έκδοση της int():

>>> print int('110',2) 
5
>>> int('AE',16)
174
>>> x = 0
>>> x += 1   # είναι ισοδύναμη με x = x + 1
>>> print x
1

Υπάρχουν και οι τελεστές -=, *=, /=, %=, //=, **= που δουλεύουν παρόμοια. Τέλος, οι τελεστές << (αριστερή ολίσθηση) και >> (δεξιά ολίσθηση).

>>> print 014     # οκταδικός (0o14 στην python3)
12
>>> print 0xC     # δεκαεξαδικός
12
>>> print 0b1100  # δυαδικός
12
>>> x << 1  # αριστερή ολίσθηση (left shift)
24
>>> x >> 1  # δεξιά ολίσθηση (right shift)
6

Είδαμε ότι μπορούμε να ορίσουμε ένα αλφαριθμητικό μέσα σε ' ' ή " ". Τι γίνεται όμως αν αυτοί οι δυο χαρακτήρες υπάρχουν μέσα στο αλφαριθμητικό μας;

>>> print 'This isn't a joke.'
  File "<stdin>", line 1
    print 'This isn't a joke.'
                    ^
SyntaxError: invalid syntax

Στην περίπτωση αυτή χρησιμοποιούμε τον χαρακτήρα διαφυγής \ (escape character):

>>> print 'This isn\'t a joke.'
This isn't a joke.

Ας δούμε τώρα πώς μπορούμε να γράψουμε ένα πρόγραμμα Python. Στον αγαπημένο σας κειμενογράφο εισάγετε το παρακάτω:

#!/usr/bin/env python
print 'Hello. I am a python program.'
name = raw_input("What is your name? ")
print "Hello " + name + ". Welcome to Python!"

και αποθηκεύστε το ως π.χ. hello-python.py.

$ chmod +x hello-python.py
$ ./hello-python.py 
Hello. I am a python program.
What is your name? John
Hello John. Welcome to Python!

Η εντολή raw_input() θα εμφανίσει το μήνυμα, που του περνάμε ως όρισμα, στη γραμμή εντολών και θα αποθηκεύσει την είσοδο του χρήστη στη μεταβλητή name. Ας δοκιμάσουμε και την ελληνική έκδοση του προγράμματος (hello-python-el.py):

#!/usr/bin/env python
print 'Γειά σου. Είμαι ένα πρόγραμμα python.'
name = raw_input("Πώς ονομάζεσαι; ")
print "Γειά σου " + name + ". Καλωσήρθες στην Python!"

$ chmod +x hello-python-el.py
$ ./hello-python-el.py 
  File "./hello-python-el.py", line 2
SyntaxError: Non-ASCII character '\xce' in file ./hello-python-el.py on line 2, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

Τζίφος! Αν διαβάσουμε τον υπερσύνδεσμο που μας προτείνει τότε αρκεί να κάνουμε την ακόλουθη αλλαγή για να δουλέψει:

#!/usr/bin/env python
# -*- coding: utf8 -*-
print 'Γειά σου. Είμαι ένα πρόγραμμα python.'
name = raw_input("Πώς ονομάζεσαι; ")
print "Γειά σου " + name + ". Καλωσήρθες στην Python!"

$ ./hello-python-el.py 
Γειά σου. Είμαι ένα πρόγραμμα python.
Πώς ονομάζεσαι; Γιάννης
Γειά σου Γιάννης. Καλωσήρθες στην Python!

Ας δοκιμάσουμε με την python 3 (hello-python-3-el.py):

#!/usr/bin/env python3
# -*- coding: utf8 -*-
print('Γειά σου. Είμαι ένα πρόγραμμα python.')
name = input("Πώς ονομάζεσαι; ")
print("Γειά σου " + name + ". Καλωσήρθες στην Python!")

$ chmod +x hello-python-3-el.py
$ ./hello-python-3-el.py 
Γειά σου. Είμαι ένα πρόγραμμα python.
Πώς ονομάζεσαι; Γιάννης
Γειά σου Γιάννης. Καλωσήρθες στην Python!

Παρατηρήστε ότι στην python3 η raw_input() έχει μετονομαστεί σε input(). Ο χαρακτήρας +, όπως θα δούμε, είναι ο χαρακτήρας συγχώνευσης αλφαριθμητικών. Υπάρχει όμως κι άλλος τρόπος να συγχωνεύσουμε μεταβλητές με αλφαριθμητικά και να τα εμφανίσουμε στην οθόνη. Έτσι η τελευταία εντολή του προγράμματος (python 2) μπορεί να γραφεί και ως εξής:

print "Γειά σου %s. Καλωσήρθες στην Python!" %(name)

Ο τελεστής % στο τέλος του αλφαριθμητικού θα αντικαταστήσει τα %s μέσα στο αλφαριθμητικό με τις μεταβλητές μέσα στις παρενθέσεις (χωρισμένες με κόμμα αν είναι περισσότερες από μια). Φυσικά υπάρχουν και %i ή %d, %f για int, float αντίστοιχα. Π.χ. η παρακάτω εντολή σημαίνει δυο ψηφία μετά την υποδιαστολή:

>>> print "%.2f" % 5.2
5.20

Σχόλια

# Αυτό είναι ένα σχόλιο μιας γραμμής
"""Αυτό είναι ένα σχόλιο
πολλών γραμμών"""

Εντολές αποφάσεων και επανάληψης

Όπως κάθε γλώσσα προγραμματισμού, έτσι και η Python υποστηρίζει εντολές αποφάσεων και επανάληψης. Η εντολή αποφάσεων if συντάσσεται ως εξής:

if συνθήκη1:
    body
elif συνθήκη2:
    body
else:
    body

Προσέξτε να μην ξεχάσετε το : μετά από κάθε συνθήκη. Ένα σημαντικό θέμα σε κάθε γλώσσα προγραμματισμού είναι πώς να καθορίζουμε ποιες εντολές είναι να εκτελεστούν μαζί, ως μπλοκ, και ποιες όχι. Π.χ. στην Java, C/C++, ένα μπλοκ κώδικα ορίζεται μέσα σε { }, στην Pascal μεταξύ των εντολών BEGIN END κλπ. Η Python χρησιμοποιεί τα κενά! Όσες εντολές έχουν εσοχή 4 κενά από την αρχή αποτελούν ένα μπλοκ, 8 κενά αποτελούν ένα εσωτερικό μπλοκ κ.ο.κ. Προσοχή! Μπορείτε να χρησιμοποιήσετε και τον στηλοθέτη (tab) μόνο αν τον έχετε ορίσει στους 4 χαρακτήρες. Ας δούμε ένα παράδειγμα με το παρακάτω πρόγραμμα testif.py:

#!/usr/bin/env python3
answer = input("Σου αρέσει η Python (Ν/ν/Ο/ο);")
if answer == 'Ν' or answer == 'ν':
    print("Καλωσήρθες στη Python!")
elif answer == 'Ο' or answer == 'ο':
    print ("Μήπως να το ξανασκεφτόσουνα;")
else:
    print("Απάντησε με Ν/Ο")

Παρατηρήστε ότι ο έλεγχος για ισότητα γίνεται με == ενώ για ανισότητα με !=.

$ chmod +x testif.py
$ ./testif.py 
Σου αρέσει η Python (Ν/ν/Ο/ο);N
Καλωσήρθες στη Python!
$ ./testif.py 
Σου αρέσει η Python (Ν/ν/Ο/ο);ο
Μήπως να το ξανασκεφτόσουνα;
$ ./testif.py 
Σου αρέσει η Python (Ν/ν/Ο/ο);Μ
Απάντησε με Ν/Ο

Εντολή επανάληψης:

while συνθήκη:
    body

Π.χ.

>>> i = 0
>>> while i < 10: 
...    i += 1
...    print i
... print 'All Done'

εμφανίζει τους ακεραίους από 1-10 και στο τέλος All Done. Ας δούμε άλλο ένα παράδειγμα (testwhile.py):

#!/usr/bin/env python3
answer = input("Σου αρέσει η Python (Ν/ν/Ο/ο); ")
while not (answer == 'Ν' or answer == 'ν' or answer == 'Ο' or answer == 'ο'):
    answer = input("Σου αρέσει η Python; Απάντησε με (Ν/ν/Ο/ο).")
print('Ευχαριστώ για την απάντηση!')

$ chmod u+x testwhile.py
$ ./testwhile.py
Σου αρέσει η Python (Ν/ν/Ο/ο); λ
Σου αρέσει η Python; Απάντησε με (Ν/ν/Ο/ο): ν
Ευχαριστώ για την απάντηση!

Θα μπορούσαμε να γράψουμε τη συνθήκη κι ως εξής, όπως θα μάθουμε παρακάτω: while not answer in ['Ν', 'ν', 'Ο', 'ο']: Θα πρέπει να προσέχετε η συνθήκη να παίρνει κάποια στιγμή την τιμή False, διαφορετικά πέφτετε σε ατέρμονο βρόγχο και το πρόγραμμά σας δεν τελειώνει ποτέ. Υπάρχει και μια άλλη έκδοση της while:

while συνθήκη:
    body1
else:
    body2

Το μπλοκ else θα εκτελεστεί όταν η συνθήκη γίνει False. Π.χ.

#!/usr/bin/env python3
count = 1
answer = input("Σου αρέσει η Python (Ν/ν/Ο/ο); ")
while count < 3 and not answer in ['Ν', 'ν', 'Ο', 'ο']:
    count += 1
    answer = input("Σου αρέσει η Python; Απάντησε με (Ν/ν/Ο/ο): ")
    if answer in ['Ν', 'ν', 'Ο', 'ο']:
        print('Ευχαριστώ για την απάντηση!')    
else:
    print('Ξεπέρασες τον επιτρεπτό αρ. προσπαθειών!')

$ ./testwhile.py
Σου αρέσει η Python (Ν/ν/Ο/ο); α
Σου αρέσει η Python; Απάντησε με (Ν/ν/Ο/ο): σ
Σου αρέσει η Python; Απάντησε με (Ν/ν/Ο/ο): δ
Ξεπέρασες τον επιτρεπτό αρ. προσπαθειών!

Εντολή επανάληψης:

for μεταβλητή in λίστα_τιμών:
    body1
else
    body2

Π.χ.

for i in range(0,10): 
    print i+1
print 'All Done'

Το παραπάνω πρόγραμμα εμφανίζει τους ακεραίους από 1-10 και στο τέλος All Done. Η μεταβλητή i παίρνει τιμές από 0-9. Παρατηρήστε ότι η τελευταία εντολή είναι έξω από το μπλοκ εντολών που εκτελούνται από τη for. Αν κάναμε το λάθος να τη γράψουμε όπως στο παρακάτω:

for i in range(0,10): 
    print i+1
    print 'All Done'

το All Done θα εμφανιζόταν επίσης 10 φορές. Επομένως χρειάζεται μεγάλη προσοχή για το που αρχίζει και που τελειώνει ένα μπλοκ εντολών που ορίζεται με εσοχές. Παρακάτω θα δούμε κι άλλες χρήσεις της for.

Δομές Δεδομένων

Η Python υποστηρίζει τις ακόλουθες δομές δεδομένων:

Λίστες (Lists)

Ορίζονται μέσα σε [ ]. Οι λίστες μπορούν να περιλαμβάνουν οποιονδήποτε τύπο δεδομένων: αριθμούς, αλφαριθμητικά, άλλες λίστες, κλπ. Η σύνταξη μιας λίστας είναι [Element1, Element2, ..., ElementN] και όπως ειπώθηκε, κάθε Element μπορεί να ανήκει σε διαφορετικό τύπο δεδομένων:

>>> months = ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος','Ιούλιος','Αυγούστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος']
>>> print months[0]
Ιανουάριος

Οι λίστες ξεκινάνε από το δείκτη 0.

>>> print months[9:12]
['\xce\x9f\xce\xba\xcf\x84\xcf\x8e\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82', '\xce\x9d\xce\xbf\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82', '\xce\x94\xce\xb5\xce\xba\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82']

Ενώ στην python 3 η παραπάνω εντολή δουλεύει σωστά επιστρέφοντας ['Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος'], στην 2 όχι. Αν και δοκίμασα τα πάντα που βρήκα στο Διαδίκτυο, δεν κατάφερα να βρω πώς να εμφανίσω σωστά την παραπάνω εντολή στην Python 2. Παρατηρήστε ότι η παραπάνω εντολή επιστρέφει τα στοιχεία 9, 10 και 11 της λίστας. Συνεχίζουμε με Python 3. Υπάρχουν διάφορες συναρτήσεις για λίστες:

>>> basket = []
>>> basket.append("πληκτρολόγιο")
>>> basket.append("οθόνη")
>>> basket.append("ποντίκι")
>>> print(basket)
['πληκτρολόγιο', 'οθόνη', 'ποντίκι']
>>> print(len(basket))
3
>>> indx = basket.index("οθόνη")
>>> print(indx)
1
>>> basket.insert(indx, "mousepad")
>>> print(basket)
['πληκτρολόγιο', 'mousepad', 'οθόνη', 'ποντίκι']
>>> for item in basket:
...     print(item)
πληκτρολόγιο
mousepad
οθόνη
ποντίκι
>>> basket.sort()
>>> for i in range(len(basket)):
...     print(basket[i])
mousepad
οθόνη
πληκτρολόγιο
ποντίκι
>>> basket.remove('mousepad')
>>> print(basket)
['οθόνη', 'πληκτρολόγιο', 'ποντίκι']
>>> item = basket.pop() #διαγραφή τελευταίου στοιχείου
>>> print(basket)
['οθόνη', 'πληκτρολόγιο']
>>> del(basket[0])
>>> print(basket)
['πληκτρολόγιο']
>>> basket2 = ['joystick']
>>> print(basket + basket2)  # συγχώνευση
['πληκτρολόγιο', 'joystick']

Αν θέλουμε να προσπελάσουμε μόνο τα στοιχεία που βρίσκονται στις ζυγές θέσης στη λίστα, χρησιμοποιούμε τον τελεστή τεμαχισμού [start:end:step] (Το end δεν περιλαμβάνεται, δηλ. το διάστημα είναι [start, end)):

>>> basket = ['πληκτρολόγιο', 'οθόνη', 'ποντίκι']
>>> print(basket[0::2])
['πληκτρολόγιο', 'ποντίκι']
>>> ae = ['A', 'Β', 'Γ', 'Δ', 'Ε']
>>> print(ae[3:])
['Δ', 'Ε']
>>> print(ae[:2])
['A', 'Β']
>>> print(ae[::2])
['A', 'Γ', 'Ε']

Η συνάρτηση range(start,stop,step) επιστρέφει μια λίστα ακεραίων:

range(6) # => [0,1,2,3,4,5]
range(1,6) # => [1,2,3,4,5]
range(1,6,3) # => [1,4] 

Η χρήση της for για λίστες που είδαμε παραπάνω έχει το μειονέκτημα είναι ότι δεν γνωρίζουμε σε ποια θέση βρισκόμαστε στη λίστα. Θα μπορούσαμε να χρησιμοποιήσουμε έναν μετρητή, αλλά υπάρχει κι ο παρακάτω τρόπος:

>>> basket = ['πληκτρολόγιο', 'οθόνη', 'ποντίκι']
>>> for index, item in enumerate(basket):
...     print("%d: %s" % (index, item))
0: πληκτρολόγιο
1: οθόνη
2: ποντίκι

Επίσης, υποστηρίζονται και iterators όπως και με άλλες γλώσσες προγραμματισμού:

>>> i = iter(basket)
>>> while hasNext(i):
...     print(next(i))
πληκτρολόγιο
οθόνη
ποντίκι
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
StopIteration

Η εξαίρεση που βλέπετε στο τέλος είναι φυσιολογική. Αν θέλουμε να προσπελάσουμε δυο λίστες ταυτόχρονα, τότε η Python παρέχει λύση και γι’ αυτό:

>>> for item1, item2 in zip(basket, basket2):
...     print("%s ή %s;" % (item1, item2))
πληκτρολόγιο ή joystick;

Η zip() σταματάει στο τέλος της μικρότερης λίστας. Φυσικά και υποστηρίζονται n-διάστατες λίστες, π.χ.:

>>> matrix2D = [[3,5],[2,-1]] # πίνακας 2x2
>>> print matrix2D[0]
[3, 5]

Λεξικά (dictionaries)

Ορίζονται μέσα σε { }. Η διαφορά του με τη λίστα είναι ότι αντί για δείκτες για προσπέλαση των τιμών, χρησιμοποιούνται κλειδιά (keys). Ένα κλειδί μπορεί να είναι είτε ακέραιος αριθμός είτε αλφαριθμητικό. Σε άλλες γλώσσες προγραμματισμού ονομάζονται πίνακες κατακερματισμού (hashmaps). Η σύνταξη ενός λεξικού είναι {key1 : value1, key2 : value2, ..., keyN : valueN} και κάθε value μπορεί να ανήκει σε διαφορετικό τύπο δεδομένων:

>>> stock = {'πληκτρολόγια' : 56, 'ποντίκια' : 85, 'mousepads' : 111}
>>> print(stock['mousepads'])
111
>>> stock['πληκτρολόγια'] = 50
>>> stock['οθόνες'] = 13
>>> print(stock)
{'πληκτρολόγια': 50, 'mousepads': 111, 'οθόνες': 13, 'ποντίκια': 85}
>>> print(stock.get('οθόνες'))
13
>>> print(stock.keys())
dict_keys(['πληκτρολόγια', 'οθόνες', 'mousepads', 'ποντίκια'])
>>> print(stock.values())
dict_values([50, 13, 111, 85])
>>> print(stock.items())
dict_items([('πληκτρολόγια', 50), ('οθόνες', 13), ('mousepads', 111), ('ποντίκια', 85)])
>>> del stock['οθόνες']
>>> print(stock)
{'πληκτρολόγια': 50, 'mousepads': 111, 'ποντίκια': 85}
>>> for key, value in stock.items():
...     print(key, value)
πληκτρολόγια: 50
mousepads: 111
ποντίκια: 85

Πλειάδες (tuples)

Ορίζονται μέσα σε ( ). Η πλειάδα είναι μια αμετάβλητη (immutable) λίστα. Μετά τη δημιουργία της, δεν μπορούμε ν’ αλλάξουμε ούτε το μέγεθος ούτε το περιεχόμενό της. Είναι κάτι αντίστοιχο των enumerated types (enum) σε γλώσσες όπως η Java ή οι C/C++/C#. Η σύνταξη μιας πλειάδας είναι (Element1, Element2, ..., ElementN) και κάθε Element μπορεί να ανήκει σε διαφορετικό τύπο δεδομένων:

>>> colors = ('black', 'blue', 'red', 'green', 'yellow')
>>> colors[1]
'blue'
>>> colors[1] = 'cyan'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment 

Προσοχή απαιτείται σε πλειάδες που περιέχουν ένα μόνο στοιχείο:

>>> singleton = (1)
>>> print singleton
1
>>> singleton_tuple = (1,) # το κόμμα απαιτείται
>>> print singleton_tuple
(1,)

Υποστηρίζονται οι τελεστές + και *, όπως και στις λίστες καθώς και ο τεμαχισμός τους:

>>> colors[1:3]
('blue', 'red')
>>> colors[1:3] * 2
('blue', 'red', 'blue', 'red')

Σύνολα (sets)

Ορίζονται μέσα σε { }. Ένα σύνολο περιέχει μη ταξινομημένα στοιχεία τα οποία είναι μοναδικά, δηλ. δεν υπάρχουν διπλότυπα. Η σύνταξη μιας πλειάδας είναι {Element1, Element2, ..., ElementN} και κάθε Element μπορεί να ανήκει σε διαφορετικό τύπο δεδομένων:

>>> s1 = {'black', 'blue', 'red'}
>>> s2 = set(['green', 'yellow'])
>>> print(s2)
{'green', 'yellow'}
>>> s2.add('blue')
>>> s2.add('green')  # υπάρχει ήδη
>>> print(s2)
{'green', 'blue', 'yellow'}
>>> s2.remove('green')
>>> print(s2)
{'blue', 'yellow'}

Τα σύνολα υποστηρίζουν τις ακόλουθες πράξεις:

Πράξη Σύμβολο
Αφαίρεση -
Ένωση |
Τομή &
Υπερσύνολο &gt;
Υποσύνολο &lt;
Ισότητα ==
Ανισότητα !=
>>> print(s1 - s2)  # αφαίρεση
{'red', 'black'}
>>> print(s1 | s2)  # ένωση
{'red', 'blue', 'black', 'yellow'}
>>> print(s1 & s2)  # τομή
{'blue'}
>>> print(s1 > s2)
False
>>> print(s1 < s2)
False
>>> print(s1 == s2)
False
>>> print(s1 != s2)
True
>>> print('black' in s1)
True

Και μια σύνταξη που μπορεί να σας εκπλήξει:

>>> [val * 1.23 for val in stock.values()]
[136.53, 104.55, 61.5]

Σύνταξη List Comprehension: [operation for var in iterable if condition]

>>> [i for i in range(11) if i % 2 == 0]
[0, 2, 4, 6, 8, 10]

Η Python 3 υποστηρίζει και: Set comprehension: {operation for var in set if condition} Dict comprehension: {key:value for key,value in sequence if condition}

Αλφαριθμητικά

Τα αλφαριθμητικά (str) είναι κι αυτά λίστες χαρακτήρων που ξεκινάνε από το δείκτη 0:

>>> day = "Καλημέρα"
>>> print day[0]

>>>

Τζίφος!

$ python3
Python 3.4.3 (default, Sep 14 2016, 12:36:27) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> day = "Καλημέρα"
>>> print(day[0])
Κ

Αν όμως θέλετε να μάθετε πώς να εκτελέσετε τον παραπάνω κώδικα στην Python 2 μπορείτε να δηλώσετε ότι το "Καλημέρα" είναι unicode με έναν από δυο τρόπους:

>>> day = unicode("Καλημέρα",'utf8')
>>> print day[0]
Κ
>>> day = u"Καλημέρα"
>>> print day[1]
α
>>> print day[4:8]
μέρα

Υποστηρίζονται οι ακόλουθες συναρτήσεις:

>>> length = len(day)
>>> print(length)
8
>>> print(day.lower())
καλημέρα
>>> day.islower()
False
>>> print(day.upper())
ΚΑΛΗΜΈΡΑ
>>> day.isupper()
False
>>> print(day.find("μέρα")) # σε ποια θέση;
4
>>> print(day[4:len(day)])  # substring
μέρα
>>> s = "Καλημέρα φίλε!"
>>> print(s.split(' '))
['Καλημέρα', 'φίλε!']
>>> s.replace("!","!!")
'Καλημέρα φίλε!!'
>>> print(s.isalpha())    # δεν περιέχει αριθμούς κλπ.
False
>>> print(day.isalpha())
True
>>> for letter in day:
...     if letter == 'α':
...         print(letter)
α
α

Συναρτήσεις και Βιβλιοθήκες

Οι συναρτήσεις είναι μπλοκ εντολών που εκτελούνται ως σύνολο όταν καλούνται. Οι συναρτήσεις στη Python ορίζονται ως εξής:

def function_name(parameters):
    body

όπου οι παράμετροι μπορεί να είναι οποιονδήποτε τύπου δεδομένων (π.χ. αλφαριθμητικό, λίστα κλπ.) Ας δούμε μια συνάρτηση η οποία βρίσκει αν μια λέξη είναι παλινδρομική. Κατ’ αρχήν, θα πρέπει να βρούμε την αντίστροφη της λέξης (text):

def reverse(text):
    reversedtext = []
    for i in range(len(text)-1, -1, -1):
        reversedtext.append(text[i])
    return ''.join(reversedtext)

Υπάρχουν πολλοί τρόποι για ν’ αντιστρέψουμε μια λέξη, όπως μπορείτε να βρείτε στο διαδίκτυο, π.χ. ένας πιο σύντομος κάνει χρήση της συνάρτησης reversed():

''.join(list(reversed(text)))

ένας άλλος είναι text[::-1]. Ας δούμε όμως αυτήν που γράψαμε παραπάνω. Η λέξη text περνιέται ως παράμετρος στη συνάρτηση reverse(). Η range() επιστρέφει τους αριθμούς από το μήκος της λέξης παρά ένα, μέχρι το -1, δηλ. αντίστροφα. Οι χαρακτήρες ένας-ένας επισυνάπτονται στη λίστα reservedtext ενώ η τελευταία εντολή μετατρέπει τη λίστα σε αλφαριθμητικό. Πλέον, η παλινδρομική συνάρτηση μπορεί να γραφτεί πολύ εύκολα ως:

def isPalindrome(text):
    return text == reverse(text)

Αν θέλουμε να την τεστάρουμε:

>>> print('Is \'cat\' palindrome? ' + str(isPalindrome('cat')))
False
>>> print('Is \'abba\' palindrome? ' + str(isPalindrome('abba')))
True

Προσοχή θέλει αν τα ορίσματα περνούν ως αναφορά ή ως τιμή:

>>> def add1(number, lst):
...     number += 1
...     lst.append(1)
...     print('number= ', number)
...     print('lst= ', lst)
... 
>>> number = 5
>>> lst = ['Hallo']
>>> add1(number, lst)
number=  6
lst=['Hallo',1]
>>> number
5
>>> lst
lst=['Hallo',1]

Όπως και σε άλλες γλώσσες προγραμματισμού, η μεταβλητή λίστας είναι μια διεύθυνση μνήμης όπου μπορεί να βρεθεί η λίστα, άρα περνιέται ως αναφορά και άρα μεταβάλλεται η θέση μνήμης. Αντιθέτως, η number περνιέται ως τιμή, επομένως, παρόλο που και μέσα στη συνάρτηση ορίζεται μια μεταβλητή με το ίδιο όνομα, αυτή δεν έχει καμιά σχέση με την εξωτερική μεταβλητή. Αν θέλουμε όμως σώνει και καλά ν’ αλλάξουμε την τιμή μιας μεταβλητής αμετάβλητου τύπου όπως int, μπορούμε να κάνουμε το εξής:

>>> def add1(number, lst):
...     number += 1
...     lst.append(1)
...     return number, lst
... 
>>> number = 5
>>> lst = ['Hallo']
>>> number, lst = add1(number, lst)
number=  6
lst=['Hallo',1]
>>> number
6
>>> lst
lst=['Hallo',1]

Η σειρά των παραμέτρων έχει σημασία, αλλά μπορούμε να τους αλλάξουμε τη σειρά όπως στο παρακάτω παράδειγμα:

>>> def process(text, word):
    ...
>>> process('Hallo world!', 'world')
>>> process(word='world', text='Hallo world!')

Οι παράμετροι μπορούν να λάβουν και εξ’ ορισμού τιμές, π.χ.

>>> def process(text, word=''):
    ...
>>> process('Hallo world!')  # η word = ''

Αν ο αριθμός των ορισμάτων που περνάμε είναι μεγαλύτερος από τον αριθμό των παραμέτρων, τότε μπορούμε να δηλώσουμε την τελευταία παράμετρο με ένα * ώστε τα υπόλοιπα ορίσματα να αποθηκευθούν σ’ αυτήν ως πλειάδα ή με ** για ν’ αποθηκευθούν ως λεξικό:

>>> def process(*args):
...     return args
>>> process('This', 'is', 'a', 'test')
('This', 'is', 'a', 'test')
>>> watch = ['Seiko', 455, 5]
>>> process(watch)
(['Seiko', 455, 5],)
>>> process(*watch)
('Seiko', 455, 5)
>>> def process(**args):
...     return args
>>> process(brand='Seiko', price=455, guarantee=5)
{'guarantee': 5, 'brand': 'Seiko', 'price': 455}
>>> watch = {'brand': 'Seiko', 'price': 455, 'guarantee': 5}
>>> process(**watch)
{'guarantee': 5, 'brand': 'Seiko', 'price': 455}
>>> process(watch)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: process() takes 0 positional arguments but 1 was given

Οι συναρτήσεις είναι κι αυτές αντικείμενα στην Python, οπότε μπορούν να περαστούν με τη σειρά τους ως ορίσματα σε άλλες συναρτήσεις!

>>> def inGreek():
...     return 'Καλημέρα!'
...
>>> def inFrench():
...     return 'Bonjour!'
...
>>> def sayGoodMorning(lang, f):
...     print('Good morning in ', lang, ' is ', f())
...
>>> sayGoodMorning('Greek!', inGreek)
Good morning in  Greek  is  Καλημέρα!

Φυσικά υποστηρίζεται και η αναδρομή. Μια συνάρτηση (υποπρόγραμμα) λέγεται αναδρομική όταν μπορεί και καλεί τον εαυτό της. Ας δούμε ένα παράδειγμα, τον υπολογισμό του παραγοντικού ενός φυσικού αριθμού n:

Από τα παραπάνω βλέπουμε ότι για να υπολογίσουμε το παραγοντικό του n θα πρέπει πρώτα να υπολογίσουμε το παραγοντικό του n-1. Για να υπολογίσουμε το παραγοντικό του n-1 χρειάζεται πρώτα να υπολογίσουμε το παραγοντικό του n-2 κ.ο.κ. μέχρις ότου φθάσουμε σε μια συνθήκη όπου μπορούμε να υπολογίσουμε το παραγοντικό, η οποία λέγεται συνθήκη διακοπής, και στο παραπάνω παράδειγμα είναι το 0!=1. Σημειώστε ότι χωρίς συνθήκη διακοπής το πρόγραμμα μπαίνει σε ατέρμονα βρόγχο. Δημιουργήστε ένα νέο αρχείο factorial.py:

#!/usr/bin/env python3
def factorial(n):
    if n = 0:
        return 1 
    else:
        return n*factorial(n-1)
print("5!=%d" % factorial(5))
print("0!=%d" % factorial(0))

και εκτελέστε το:

$ chmod u+x factorial.py
$ ./factorial.py
5!=120
0!=1

Η Python υποστηρίζει και συναρτησιακό προγραμματισμό, δηλ. λ-εκφράσεις:

>>> pow = lambda x: x ** 2 
>>> pow(3)
9

Η παραπάνω έκφραση δηλώνει τη συνάρτηση: f(x) = x^2 και της δίνει το όνομα pow. Είναι σα να γράφαμε:

>>> def pow(x):
>>>    return x ** 2
>>> pow(3)
9

Η Python υποστηρίζει και filter-map-reduce. Η συνάρτηση filter() δέχεται μια λ-έκφραση για να φιλτράρει το δεύτερο όρισμά της:

>>> my_list = range(10)
>>> filter(lambda x: x % 2 == 0, my_list)
[0, 2, 4, 6, 8]

Στην Python 2 επιστρέφει λίστα, στην Python 3 όμως επιστρέφει ένα αντικείμενο τύπου filter που θα πρέπει να μετατραπεί σε λίστα:

>>> my_list = range(10)
>>> list(filter(lambda x: x % 2 == 0, my_list))
[0, 2, 4, 6, 8]

Παρατηρήστε ότι η λ-έκφραση που περνάμε στη filter() πρέπει να επιστρέφει τύπο bool. Η map() μετατρέπει κάθε στοιχείο του 2ου ορίσματός της σύμφωνα με τη λ-έκφραση:

>>> map(lambda x: x ** 2, my_list) # python2
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> list(map(lambda x: x**2, my_list) # python3
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Τέλος, η reduce() μετατρέπει τη λίστα σ’ ένα μόνο στοιχείο (στο ακόλουθο παράδειγμα προσθέτει όλα τα στοιχεία της λίστας):

>>> reduce(lambda x,y: x + y, my_list) # python2
45
>>> import functools   # python3
>>> functools.reduce(lambda x,y: x + y, my_list) 
45

Το παραπάνω μοντέλο προγραμματισμού είναι ιδιαίτερα χρήσιμο όπως φαίνεται στο ακόλουθο πιο ρεαλιστικό παράδειγμα. Ας υποθέσουμε ότι τα δεδομένα προέρχονται από μια βάση δεδομένων και αποθηκεύονται στη λίστα από λεξικά data:

>>> data =[
{'προϊόν': 'πληκτρολόγιο', 'τιμή': 26, 'ποσότητα': 2}, 
{'προϊόν': 'ποντίκι', 'τιμή': 12, 'ποσότητα': 2},
{'προϊόν': 'mousepad', 'τιμή': 5, 'ποσότητα': 3} ]

Θα θέλαμε να υπολογίσουμε το συνολικό ποσό που θα πρέπει να πληρώσει ο πελάτης. Κατ’ αρχήν θα θέλαμε να αφήσουμε μόνο τα σχετικά πεδία:

>>> l = list(map(lambda x: [x['τιμή'], x['ποσότητα']], data))
>>> print(l)
[[26, 2], [12, 2], [5, 3]]

Οι βιβλιοθήκες (modules) είναι σαν τα πακέτα (packages) της Java ή οι χώροι ονομασίας (namespaces) της C++. Όπως οι συναρτήσεις μας βοηθούν να οργανώνουμε τον κώδικά μας σε μπλοκ, οι βιβλιοθήκες μας βοηθούν να οργανώνουμε τις συναρτήσεις μας σε βιβλιοθήκες, ακόμα και να επεκτείνουμε την ίδια τη γλώσσα. Μπορούν να είναι υπό τη μορφή πηγαίου κώδικα (.py) ή μεταγλωττισμένου κώδικα (.pyc) ή ακόμα και δυναμικής βιβλιοθήκης (.so). Όπως το PATH και το CLASSPATH, έτσι κι η Python διαθέτει την PYTHONPATH για να αναζητεί βιβλιοθήκες (βλ. βιβλιοθήκες). Η γλώσσα διαθέτει μια μεγάλη γκάμα από βιβλιοθήκες για όλες σχεδόν τις δουλειές όπως μπορείτε να δείτε εδώ. Για να μπορέσετε να χρησιμοποιήσετε τις συναρτήσεις μιας βιβλιοθήκης θα πρέπει πρώτα να την εισάγετε στο πρόγραμμά σας:

>>> import math
>>> print math.sqrt(25)
5.0

Η εντολή import είναι παρόμοια με την import της Java ή την include της C/C++. Η συνάρτηση sqrt() δηλώνεται στη βιβλιοθήκη math το οποίο πρέπει να εισάγουμε στο πρόγραμμά μας με την εντολή import. Μπορούμε όμως να γίνουμε και πιο συγκεκριμένοι, αν θέλουμε μόνο την sqrt():

>>> from math import sqrt
>>> print sqrt(25)
5.0

Ας δούμε μερικά παραδείγματα ακόμα:

>>> max(25, -5, 12, 30)
30
>>> abs(-12)
12

Μπορούμε να ορίσουμε και τα δικές μας βιβλιοθήκες ως εξής (mod1.py):

""" 
A simple module
"""
name = "Simple Module"
def printe(s, count):
    print(s * count)

και το εκτελούμε κατά τα γνωστά:

>>> import mod1
>>> print(mod1.name)
Simple Module
>>> mod1.printe('Hallo Python', 2)
Hallo PythonHallo Python
>>> dir(mod1)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'name', 'printe']

Εδώ είναι μια λίστα με βιβλιοθήκες της Python. Πολύ χρήσιμη είναι η στάνταρ βιβλιοθήκη (standard library) η οποία είναι μια συλλογή από χρήσιμες συναρτήσεις (όχι μέρος της γλώσσας αυτής καθαυτής), όπως:

Ημερομηνία και Ώρα

Η Python διαθέτει φυσικά μια βιβλιοθήκη για διαχείριση ημερομηνίας και ώρας.

>>> from datetime import datetime
>>> now = datetime.now()
>>> print now
2016-10-16 16:03:13.392686
>>> print now.year
2016
>>> print now.month
10
>>> print now.day
16
>>> print '%s/%s/%s' % (now.day, now.month, now.year)
16/10/2016
>>> print '%s:%s:%s' % (now.hour, now.minute, now.second)
16:5:40

Αρχεία

Αν έχετε βαρεθεί να εμφανίζετε τ’ αποτελέσματα στην οθόνη τότε η Python (όπως και οι περισσότερες γλώσσες προγραμματισμού) έχει τη λύση:

>>> f = open("output.txt", "w")
>>> f.write("Από την πόλη έρχομαι\nκαι στην κορυφή κανέλλα.")
>>> f.close()

Στο παραπάνω παράδειγμα ανοίγουμε ένα αρχείο στον τρέχοντα φάκελο για εγγραφή ("w") (το f λέγεται διαχειριστής αρχείου (file handler)), γράφουμε μια πρόταση και δεν ξεχνάμε να το κλείσουμε. Αν ανοίξετε το αρχείο output.txt θα δείτε την παραπάνω παροιμία. Είναι πολύ σημαντικό να μην ξεχάσετε να κλείσετε το αρχείο, καθώς τότε γράφονται τα δεδομένα σ’ αυτό. Επίσης αφήνοντας αρχεία ανοιχτά σπαταλάτε άσκοπα πόρους του συστήματός σας. Αν θέλετε να μεταφέρετε τα δεδομένα από τον buffer στο αρχείο χωρίς όμως να κλείσετε το αρχείο, χρησιμοποιήστε την flush(). Μπορούμε να ανοίξουμε ένα αρχείο με διάφορους τρόπους: "r" (ανάγνωση), "w" (εγγραφή), "r+" (ανάγνωση και εγγραφή), "a" (επισύναψη). Για δυαδικό αρχείο προσθέτετε "b", π.χ. "wb".

>>> f = open("output.txt", "r")
>>> print f.read()
Από την πόλη έρχομαι
και στην κορυφή κανέλλα.
>>> f.close()

Η read() διαβάζει ολόκληρο το αρχείο και το επιστρέφει ως ένα αλφαριθμητικό. Αν θέλουμε να το διαβάσουμε γραμμή-γραμμή τότε χρησιμοποιούμε τη readline(). Μπορούμε επίσης να χρησιμοποιήσουμε την readlines() η οποία το επιστρέφει ως λίστα από αλφαριθμητικά (κάθε γραμμή αποτελεί ένα στοιχείο της λίστας). Η rstrip(), τέλος, διαγράφει το χαρακτήρα '\n' αν αυτός περιέχεται στο αλφαριθμητικό. Αντίστοιχα, για να γράψουμε σ’ ένα αρχείο χρησιμοποιούμε είτε την write(), που είδαμε πιο πάνω, είτε την writelines() που γράφει μια λίστα αλφαριθμητικών στο αρχείο. Για να μην ξεχνάτε να κλείνετε τα αρχεία, χρησιμοποιήστε την ακόλουθη σύνταξη η οποία κλείνει αυτόματα το αρχείο για σας:

with open("output.txt", "w") as f:
    f.write("Μια πάπια μα ποια πάπια!")

Μπορούμε να τσεκάρουμε αν ένα αρχείο είναι ανοικτό με την ιδιότητα closed (π.χ. f.closed).

with open("output.txt", "r") as f:
    for line in f:
        line.rstrip()  

Κάθε φορά που διαβάζουμε ή γράφουμε σ’ ένα αρχείο μετακινεί τη θέση ενός δρομέα μέσα στο αρχείο (μετριέται σε bytes από την αρχή του αρχείου). Η μέθοδος tell() επιστρέφει την τρέχουσα θέση του δρομέα σε bytes από την αρχή του αρχείου, ενώ η seek(n, start) μετακινεί το δρομέα n bytes από τη θέση start η οποία μπορεί να έχει μια από τις παρακάτω τιμές: 0 (os.SEEK_SET): αρχή του αρχείου, 1 (os.SEEK_CUR) τρέχουσα θέση, 2 (os.SEEK_END) τέλος του αρχείου. Η οθόνη και το πληκτρολόγιο μπορούν να θεωρηθούν κι αυτά “αρχεία”:

Κλάσεις

Όπως είπαμε, η Python είναι και μια αντικειμενοστραφής γλώσσα προγραμματισμού, δηλ. υποστηρίζει κλάσεις κι αντικείμενα. Μια κλάση αποτελείται από μεταβλητές και συναρτήσεις (που καλούνται μέθοδοι) ως μια οντότητα. Ο αντικειμενοστραφής προγραμματισμός μας βοηθάει να αντιστοιχίσουμε μια αφαίρεση των αντικειμένων της πραγματικότητας στη γλώσσα προγραμματισμού. Η σύνταξη έχει ως εξής:

class name(superclass):
    def __init__(παράμετροι):
    ...
    def method(παράμετροι):
    ...

Ας δούμε ένα παράδειγμα:

class Car(object):
    def __init__(self, mark, maxspeed, ccm, color, doors):
        self.mark = mark
        self.maxspeed = maxspeed
        self.ccm = ccm        
        self.color = color
        self.doors = doors
        self.speed = 0    
    
    def __str__(self):
        return "%s: %d km/h, %d ccm, %s, %d θύρες" % (self.mark, self.maxspeed, self.ccm, self.color, self.doors)

Όλες οι κλάσεις μπορούν να κληρονομούν από την κλάση object (οπότε μπορεί και να παραληφθεί, δηλ. class Car:). Η συνάρτηση __init__() ονομάζεται κατασκευαστής (constructor) και είναι η πρώτη που καλείται όταν πρόκειται να κατασκευάσουμε ένα αντικείμενο της κλάσης μας. Για να καταλάβουμε ποια η διαφορά μεταξύ κλάσης και αντικειμένου ας δούμε το παρακάτω τμήμα κώδικα:

>>> toyota_yaris = Car('Toyota Yaris', 180, 999, 'white', 5)
>>> subaru_impreza = Car('Subaru Impreza', 220, 1989, 'blue', 2)

Ορίζουμε δυο αντικείμενα τύπου Car, το toyota_yaris και το subaru_impreza. Μπορούμε να πούμε ότι η κλάση Car είναι μια μήτρα από την οποία μπορούμε να δημιουργήσουμε όσα αντικείμενα τύπου Car θέλουμε. Όταν γράφουμε την παραπάνω εντολή, καλείται ο κατασκευαστής της κλάσης, δηλ. η συνάρτηση __init__(). Όλες οι μέθοδοι στη Python δέχονται ως πρώτη παράμετρο την self η οποία δηλώνει το αντικείμενο που δημιουργούμε κάθε φορά και χρησιμοποιείται και για να ξεχωρίσουμε τις μεταβλητές (ιδιότητες) του αντικειμένου από τις παραμέτρους όταν έχουν το ίδιο όνομα. Παρατηρήστε ότι δε χρειάζεται να περάσουμε την παράμετρο self ως όρισμα στις παραπάνω μεθόδους από τα αντικείμενα. Μπορούμε να εμφανίσουμε τις ιδιότητες του αντικειμένου ως εξής:

>>> print("Ταχύτητα: %d km/h" % toyota yaris.speed)
Ταχύτητα: 0 km/h
>>> print(toyota_yaris)
Toyota Yaris: 180 km/h, 999 ccm, white, 5 θύρες

Η τελευταία εντολή καλή την ειδική συνάρτηση __str__() η οποία είναι παρόμοια με την toString() της Java, δηλ. επιστρέφει μια αναπαράσταση του αντικειμένου ως αλφαριθμητικό. Μπορούμε επίσης να ορίσουμε κι άλλες συναρτήσεις (ονομάζονται μέθοδοι) στην κλάση Car:

class Car:
...
    def accelerate(self, speed_factor):
        if speed_factor > 0 and (self.speed + speed_factor) <= self.maxspeed:
            self.speed += speed_factor
        elif speed_factor < 0 and (self.speed + speed_factor) >= 0:
            self.speed += speed_factor
        else:
            print("Λάθος επιτάχυνση: %d km/h" % speed_factor)  

Η μέθοδος accelerate() επιτρέπει στο αυτοκίνητο να επιταχύνει ή να επιβραδύνει ανάλογα του αν η παράμετρος που του περνάμε είναι θετική ή αρνητική:

>>> toyota_yaris.accelerate(20)
>>> print("Ταχύτητα: %d km/h" % toyota_yaris.speed)
Ταχύτητα: 20 km/h
>>> toyota_yaris.accelerate(-10)
>>> print("Ταχύτητα: %d km/h" % toyota_yaris.speed)
Ταχύτητα: 10 km/h
>>> toyota_yaris.accelerate(-20)
Λάθος επιτάχυνση -20 km/h
>>> print("Ταχύτητα: %d km/h" % toyota_yaris.speed)
Ταχύτητα: 10 km/h

Οι ιδιότητες κλάσης ή στατικές ιδιότητες μιας κλάσης ορίζονται ως:

class Car:
...
    availableColors = ('black', 'blue', 'red', 'white')
...

Αυτές είναι κοινές για όλα τα αντικείμενα της κλάσης. Αντίστοιχα, οι μέθοδοι κλάσης ή στατικές μέθοδοι ορίζονται περνώντας cls ως πρώτη παράμετρο:

class Car:
... 
    counter = 0
    def productionCounter(cls, n):
        cls.counter = n
...

Ας υποθέσουμε τώρα ότι η εφαρμογή μας αντί μόνο για αυτοκίνητα θα πρέπει να διαχειρίζεται και φορτηγά και λεωφορεία. Επειδή όλες αυτές έχουν κάποια κοινά χαρακτηριστικά, και λόγω της αρχής του να μην επαναλαμβάνεσαι (DRY – Don’t Repeat Yourself) που ισχύει στον προγραμματισμό, μπορούμε να εφαρμόσουμε ένα χαρακτηριστικό του αντικειμενοστραφούς προγραμματισμού που λέγεται κληρονομικότητα (inheritance). Δημιουργούμε λοιπόν την κλάση Vehicle:

class Vehicle:
    def __init__(self, type, mark, maxspeed, ccm, color, doors, speed):
        self.mark = mark
        self.type = type
        self.maxspeed = maxspeed
        self.ccm = ccm        
        self.color = color
        self.doors = doors
        self.speed = 0    
    
    def __str__(self):
        return "%s (%s): %d km/h, %d ccm, %s, %d θύρες" % (self.mark, self.type, self.maxspeed, self.ccm, self.color, self.doors)

    def accelerate(self, speed_factor):
    ...

οπότε η κλάση Car μπορεί να γραφτεί ως:

class Car(Vehicle):
    def __init__(self, mark, maxspeed, ccm, color, doors):
        Vehicle.__init__(self, "car", mark, maxspeed, ccm, color, doors, 0)   
    
    def __str__(self):
        return Vehicle.__str__(self)

Μέσα στις παρενθέσεις δηλώνουμε την υπερ-κλάση (super class) από την οποία κληρονομεί η κλάση μας. Επίσης, όταν θέλουμε να καλέσουμε μια μέθοδο της υπερ-κλάσης μας, φροντίζουμε να γράφουμε και την κλάση πριν, π.χ. Vehicle.__init__(). Η υπο-κλάση κληρονομεί όλες τις ιδιότητες και τις μεθόδους της υπερ-κλάσης (δεν υπάρχουν περιορισμοί όπως σε άλλες γλώσσες). Όταν ξανα-υλοποιούμε μια μέθοδο στην υποκλάση, λέμε ότι την υπερκαλύπτουμε (override) και αυτό είναι μια ιδιότητα των αντικειμενοστραφών γλωσσών που λέγεται πολυμορφισμός.

vehicles = [ Vehicle('Hybrid', 'bicycle', 25, 0, 'green', 0, 0), Car('Toyota Yaris', 180, 999, 'white', 5)]
for v in vehicles:
    print(v)

και το αποτέλεσμα:

$ ./vehicle.py 
...
bicycle (Hybrid): 25 km/h, 0 ccm, green, 0 θύρες
Toyota Yaris (car): 180 km/h, 999 ccm, white, 5 θύρες

Η print() καλεί, όπως είπαμε, την σωστή __str__() κάθε φορά, ανάλογα με τον τύπο του αντικειμένου. Μια κλάση μπορεί να υπερκαλύψει οποιαδήποτε από τις ειδικές μεθόδους όπως π.χ. __str__(), __repr__(), η οποία είναι παρόμοια με την __str__(), ή __add__() η οποία αντιστοιχεί στην πράξη +. Π.χ. (MyList.py)

#!/usr/bin/env python3
class MyList:
    def __init__(self, aList):
        self.aList = aList
        
    def __add__(self, value):
        retList = []
        for e in self.aList:
            retList.append(e + value)
        return retList
        
    def __mul__(self, value):
        retList = []
        for e in self.aList:
            retList.append(e * value)
        return retList

lst = [20, 30, 40]
mylst = MyList(lst)
print(lst, '+ 5 = ', mylst + 5)
print(lst, '* 5 = ', mylst * 5)

υπερκαλύπτει την εξ’ ορισμού συμπεριφορά των τελεστών + και * για λίστες:

$ ./MyList.py 
[20, 30, 40] + 5 =  [25, 35, 45]
[20, 30, 40] * 5 =  [100, 150, 200]

Μπορούμε να ορίσουμε και αφηρημένες (abstract) κλάσεις αφήνοντας κάποιες μεθόδους προς υλοποίηση από τις υποκλάσεις, π.χ.:

class Vehicle():
...
    def accelerate(self, speed_factor):
        pass

Αν θέλουμε να καλέσουμε κάποια μέθοδο της υπερκλάσης από την υποκλάση, τότε χρησιμοποιούμε την παραπάνω σύνταξη:

class Car(Vehicle):
    ...
    def acc(self):
        return super(Car,self).accelerate(10) 

η οποία στην Python3 μπορεί να γραφτεί και πιο απλά:

    def acc(self):
        return super().accelerate(10)

Το πλεονέκτημα με το να γράψουμε: return Vehicle.accelerate(10) είναι ότι αν αργότερα αλλάξουμε την υπερκλάση από Vehicle σε κάποια άλλη δεν χρειάζεται ν’ αλλάξουμε τη μέθοδο. Η Python, τέλος, υποστηρίζει πολλαπλή κληρονομικότητα, π.χ.

class Amphibian(Vehicle, Boat):
...

Ασκήσεις

  1. Γράψτε μια συνάρτηση skip_vowels(text) η οποία θα επιστρέφει τη φράση που της περνάμε χωρίς φωνήεντα, π.χ.
    >>> print skip_vowels('Όλα καλά;')
    λ κλ;
    
  2. Το Σκραμπλ (Scrabble) είναι ένα παιχνίδι όπου οι παίκτες παίρνουν πόντους συλλαβίζοντας λέξεις. Το σκορ κάθε λέξης υπολογίζεται προσθέτοντας τα σκορ καθενός γράμματος. Γράψτε μια συνάρτηση scrabble_score() που παίρνει ως παράμετρο μια λέξη και επιστρέφει το ισοδύναμο σκραμπλ σκορ γι’ αυτή τη λέξη. Τα σκορ για τα ελληνικά γράμματα (ξεχάστε τους τόνους) δίνονται παρακάτω:
    score = {"α":1,"β":8,"γ":4,"δ":4,"ε":1,"ζ":10, 
          "η":1,"θ":10,"ι":1,"κ":2,"λ":3,"μ":3, 
          "ν":1,"ξ":10,"ο":1,"π":2,"ρ":2,"σ":1,"ς":1, 
          "τ":1,"υ":2,"φ":8,"χ":8,"ψ":10,"ω":3}
    
  3. Γράψτε τη δική σας ναυμαχία. Ο παίχτης έχει 10 προσπάθειες για να βυθίσει το πλοίο που βρίσκεται σε μια τυχαία θέση μιας μήτρας 5x5. Χρησιμοποιήστε τη συνάρτηση randint(start, stop) από τη βιβλιοθήκη random. Θα πρέπει να προσέξετε ώστε ο παίκτης να μην εισάγει τις ίδιες συντεταγμένες περισσότερες από μια φορές καθώς και να εισάγει έγκυρες συντεταγμένες.
    O O O O O
    O O O O O
    O O O O O
    O O O O O
    O O O O O
    
    Γραμμή: 2
    Στήλη: 3
    Αστόχησες! Έχεις ακόμα 9 προσπάθειες...
    
    O O O O O
    O O O O O
    O O O X O
    O O O O O
    O O O O O
    
    Γραμμή: 4
    Στήλη: 2
    Συγχαρητήρια! Βύθισες το πλοίο!
    
  4. Δημιουργήστε μια συνάρτηση replace(text, word) η οποία αντικαθιστά όσες φορές βρει τη word στο text με *.
  5. Δημιουργήστε μια κλάση Triangle με μια στατική μεταβλητή number_of_sides = 3, τη μέθοδο κατασκευής να δέχεται ως ορίσματα τις 3 γωνίες του τριγώνου και μια μέθοδο check_angles() η οποία να επιστρέφει True αν το άθροισμα των γωνιών είναι 180, διαφορετικά False. Επίσης μια υποκλάση της, Equilateral με μια στατική μεταβλητή angle = 60 στη μέθοδο κατασκευής της οποίας θα καλείται την μέθοδο κατασκευής της υπερκλάσης περνώντας τρεις φορές τη γωνία angle. Προσθέστε μεθόδους για να υπολογίσετε την περίμετρο και το εμβαδό των παραπάνω.
  6. Βρείτε το μεγαλύτερο κοινό αλφαριθμητικό που περιέχεται σ’ έναν αριθμός από αλφαριθμητικά. Τα δοθέντα αλφαριθμητικά δεν θα έχουν περισσότερα από ένα κοινό αλφαριθμητικό. Αν δεν υπάρχει κοινό αλφαριθμητικό, τότε θα επιστρέφει 0. Π.χ.
    ορχήστρα
    σφυρίχτρα
    χαρτορίχτρα
    

    επιστρέφει τρα.

  7. Προσπαθήστε να λύσετε όσες περισσότερες ασκήσεις μπορείτε από το Project Euler σε Python.

Επίλογος

Σ’ αυτό το άρθρο δώσαμε μια σύντομη περιγραφή της γλώσσας προγραμματισμού Python. Η Python είναι μια αντικειμενοστραφής, δυναμική, μεταφραστική γλώσσα προγραμματισμού. Είδαμε πως μπορούμε να γράψουμε προγράμματα τόσο στην Python 2 όσο και στην Python 3. Αν θέλετε να γράψετε προγράμματα που θα χρησιμοποιούν ελληνικούς χαρακτήρες, προτιμήστε την έκδοση 3.

Μέχρι τώρα είδαμε τα πολύ βασικά χαρακτηριστικά της γλώσσας. Αν θέλετε να εντρυφήσετε περαιτέρω θα πρέπει να μάθετε για τις πολλές βιβλιοθήκες της γλώσσας π.χ. για πρόσβαση στο σύστημα αρχείων είτε στις βάσεις δεδομένων κ.ά. Μπορείτε να δημιουργήσετε γραφικά περιβάλλοντα με χρήση του wxPython ή του Tkinter καθώς και εφαρμογές ιστού με το Django που ίσως δούμε σε μελλοντικά άρθρα.

Ο ενδιαφερόμενος αναγνώστης καλείται να ανατρέξει στην ιδιαίτερα πλούσια βιβλιογραφία για να εντρυφήσει πάνω στο αντικείμενο και ιδιαίτερα στο διαδραστικό περιβάλλον εκμάθησης της Codecademy. Ο καλύτερος τρόπος όμως ίσως θα ήταν να παρακολουθήσετε τα μαθήματα Python στα ελληνικά από το ελληνικό site εκμάθησης Mathesis.

Πηγές:

  1. The Python Tutorial.
  2. A Byte of Python στα ελληνικά ή στα αγγλικά
  3. Python course.
  4. Αβούρης Ν., Εισαγωγή στην Python, Mathesis.
  5. A Gentle Introduction to Programming Using Python, MIT Open Courseware.
  6. Learn Python, Codecademy.
  7. Dive Into Python
  8. Google’s Python Class
  9. Intro to Computer Science, Udacity.
  10. An Introduction to Interactive Programming in Python, Part 1 & Part 2, Coursera.
  11. Python Programming: A Concise Introduction, Coursera.
  12. Programming for Everybody (Getting Started with Python), Coursera.
  13. Learn Python the Hard Way
  14. Learn Python Programming In Detail.
  15. Barry P. (2011), Head First Python, O’Reilly.
  16. Barry P. & Griffiths D. (2009), Head First Programming, O’Reilly.
  17. Briggs A. (2012), Hello Python, Manning.
  18. Lutz M. (2013), Learning Python, 5th Ed., O’Reilly.
  19. Lutz M. (2014), Python Pocket Reference, O’Reilly.
  20. Matthes E. (2016), Python Crash Course, No Starch Press.
  21. Payne J. (2010), Beginning Python, Wrox, Wiley.
  22. Sweigart A. (2015), Automate the Boring Stuff with Python, No Starch Press.
  23. Walters G. (2016-2017), “The Python Collection, Full Circle Magazine Python Special Editions”, Full Circle.