Creative Commons Attribution-ShareAlike 4.0 International License

Παράρτημα Α: Πληροφορίες για την Python3

Στο παράρτημα αυτό θα βρείτε τα βασικά στοιχεία για να δουλέψετε τοπικά στον υπολογιστή σας με την Python3 στο εργαστήριο των Μεταγλωττιστών. Επειδή θα χρειαστεί να εγκαταστήσετε τις βιβλιοθήκες Python του μαθήματος συνιστάται η χρήση virtual environments για να μην πειράξετε την κεντρική εγκατάσταση Python.

Εγκατάσταση της Python3

Linux

Εάν το λειτουργικό σας σύστημα είναι Linux, έχετε κατά πάσα πιθανότητα τη γλώσσα διαθέσιμη ήδη. Βεβαιωθείτε ότι τρέχετε την 3η έκδοση της γλώσσας -συχνά πρέπει να δώσετε την εντολή python3 (η απλή εντολή python συνήθως εκτελεί την προηγούμενη έκδοση 2). Δεν απαιτείται πολύ πρόσφατη έκδοση της γλώσσας, οτιδήποτε μεγαλύτερο από την 3.6 είναι αρκετό.

Για παράδειγμα, μπορείτε να μπείτε στο interactive shell της python3 ως εξής (βγείτε με exit() ή Ctrl-D όταν τελειώσετε):

$ python3
Python 3.8.10 (default, Nov 14 2022, 12:59:47)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Για να εκτελέσετε κώδικα που βρίσκεται σε ένα αρχείο (έστω ότι είναι το myprogram.py στον τρέχοντα φάκελο), δώστε:

$ python3 myprogram.py

Windows

Εάν δεν έχετε ήδη εγκαταστήσει την Python3 στο σύστημά σας, πηγαίνετε στη σελίδα της Python για download. Βεβαιωθείτε ότι διαλέγετε την πιο πρόσφατη έκδοση 3, κατεβάστε και εκτελέστε τον installer. Θυμηθείτε να ενεργοποιήσετε κατά την εγκατάσταση τις δύο προτεινόμενες επιλογές:

  • Την προσθήκη της Python στο PATH

  • Την επίτρεψη μεγάλων paths

Μπορείτε τώρα να εκτελέσετε το Command Prompt για την εμφάνιση της κονσόλας. Ξεκινήστε ένα interactive shell (βγείτε με exit() ή Ctrl-Ζ και μετά ENTER όταν τελειώσετε):

C:\Users\Testuser>python
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 22:45:29) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Για να εκτελέσετε κώδικα που βρίσκεται σε ένα αρχείο (έστω ότι είναι το myprogram.py στον τρέχοντα φάκελο), δώστε:

C:\Users\Testuser>python myprogram.py

Με την εγκατάσταση της Python έχετε επίσης στη διάθεσή σας το περιβάλλον IDLE για την εκτέλεση προγραμμάτων. Ξεκινήστε το από το μενού όπως κάθε άλλη εφαρμογή.

Εναλλακτικά μπορείτε να ξεκινήσετε το IDLE από την κονσόλα:

C:\Users\Testuser>python -m idlelib

Python virtual environments

Στην Python, ένα virtual environment επιτρέπει την εγκατάσταση πακέτων σε προστατευμένα περιβάλλοντα, χωρίς να επεμβαίνετε στην κύρια εγκατάσταση της Python του υπολογιστή σας. Μπορείτε να έχετε διαφορετικά virtual environments ανά project, με διαφορετικές εκδόσεις της Python και άλλων βιβλιοθηκών, χωρίς το ένα να επηρεάζει τα άλλα.

Συνοπτικά, τα βήματα για τη χρήση των virtual environments:

  1. Την πρώτη φορά (και μόνο) δημιουργούμε ένα virtual environment.

  2. Κάθε φορά, πριν τη χρήση ενός virtual environment, το ενεργοποιούμε.

  3. Με ενεργοποιημένο το environment μπορούμε να εγκαταστήσουμε βιβλιοθηκες τοπικά σαν απλοί χρήστες και να τρέξουμε τα προγράμματά μας.

  4. Στο τέλος, μπορούμε να απενεργοποιήσουμε το virtual environment.

Το βήμα (1) γίνεται μόνο μια φορά. Το βήμα (2) πρέπει να γίνεται πάντα πριν ξεκινήσουμε την εργασία μας στο επιλεγμένο περιβάλλον. Το βήμα (4) είναι προαιρετικό: μπορούμε απλά να κλείσουμε το terminal/command prompt.

Προσοχή: Αν τρέχετε την Python σε κάποιο IDE (αυτό δεν καλύπτεται στο εργαστήριο), θα πρέπει να φροντίσετε να ξεκινήσει μέσα από το ενεργοποιημένο virtual environment!

Οδηγίες για Linux

1. Δημιουργία ενός virtual environment

Ανοίξτε ένα τερματικό και μετακινηθείτε στον φάκελο που θέλετε να φτιάξετε το virtual environment (έστω ότι ο φάκελος λέγεται test-folder).

Δώστε την εντολή:

python3 -m venv my-venv

Αν όλα πάνε καλά, η εντολή θα επιστρέψει χωρίς μήνυμα λάθους. Στο σημείο που είσαστε θα πρέπει να υπάρχει υποφάκελος my-venv με την python3 εγκατεστημένη τοπικά. Προχωρήστε κατευθείαν στο βήμα 2.

Στην αντίθετη περίπτωση, θα χρειαστεί να εγκαταστήσετε το package venv (είναι το μοναδικό που πρέπει να γίνει με δικαιώματα superuser). Το παράδειγμα που ακολουθεί είναι για Debian/Ubuntu, αντικαταστήστε με τα αντίστοιχα του δικού σας συστήματος/διανομής:

sudo apt-get update
sudo apt-get install python3-venv

2. Ενεργοποίηση του virtual environment

Θα πρέπει να γίνεται κάθε φορά, πριν ξεκινήσετε να δουλεύετε στο virtual environment. Όντας στο test-folder, δώστε την εντολή:

source my-venv/bin/activate

Θα παρατηρήσετε ότι το prompt του terminal αλλάζει με την προσθήκη του (my-venv):

(my-venv) myuser@mypc:~/test-folder$

Το virtual environment έχει ενεργοποιηθεί. Από το σημείο αυτό μπορείτε να χρησιμοποιείτε εξίσου την εντολή python που πλέον είναι ισοδύναμη με το python3.

Την πρώτη φορά μόνο, καλό είναι να ενημερώσετε τα διάφορα εργαλεία εγκατάστασης της Python:

python -m pip install --upgrade pip setuptools wheel

3. Απενεργοποίηση του virtual environment

Δεν απαιτείται συνήθως (μπορείτε απλά να κλείσετε το terminal) αλλά γίνεται ως εξής:

deactivate

Οδηγίες για Windows

1. Δημιουργία ενός virtual environment

Βεβαιωθείτε ότι έχετε εγκαταστήσει μια πρόσφατη έκδοση (3.3+) της Python στον υπολογιστή σας.

Ανοίξτε ένα command prompt και μετακινηθείτε στο σημείο που θέλετε να φτιάξετε το virtual environment. Για παράδειγμα, φτιάξτε έναν φάκελο test-folder στον φάκελο του χρήστη σας:

C:\Users\Myuser>md test-folder
C:\Users\Myuser>cd test-folder

Δώστε την εντολή:

python -m venv my-venv

Αν όλα πάνε καλά, η εντολή θα επιστρέψει χωρίς μήνυμα λάθους. Στο σημείο που είσαστε θα πρέπει να υπάρχει υποφάκελος my-venv με την python3 εγκατεστημένη τοπικά.

2. Ενεργοποίηση του virtual environment

Θα πρέπει να γίνεται κάθε φορά, πριν ξεκινήσετε να δουλεύετε στο virtual environment.

Όντας στον φάκελο test-folder, δώστε την εντολή:

my-venv\Scripts\activate.bat

Θα παρατηρήσετε ότι το prompt του terminal αλλάζει με την προσθήκη του (my-venv):

(my-venv) C:\Users\Myuser\test-folder>

Το virtual environment έχει ενεργοποιηθεί.

Την πρώτη φορά μόνο, καλό είναι να ενημερώσετε τα διάφορα εργαλεία εγκατάστασης της Python:

python -m pip install --upgrade pip setuptools wheel

3. Απενεργοποίηση του virtual environment

Δεν απαιτείται συνήθως (μπορείτε απλά να κλείσετε το command prompt) αλλά γίνεται ως εξής:

deactivate

Εγκατάσταση βιβλιοθηκών εργαστηρίου

Τα επόμενα πρέπει να γίνουν με το virtual environment ενεργοποιημένο.

  1. Για να δουλέψετε με jupyter notebooks (παρόμοια με το online mybinder) εγκαταστήστε το jupyter:

pip install --upgrade jupyter

(Σημ.: για να ξεκινήσετε τα notebooks δώστε την εντολή jupyter-notebook)

  1. Στη συνέχεια εγκαταστήστε τις βιβλιοθήκες του εργαστηρίου:

pip install --upgrade plex compilerlabs -f https://mixstef.github.io/courses/compilers/packages/

Βασικά παραδείγματα χρήσης της Python3

Στη συνέχεια παρουσιάζονται ορισμένα ενδιαφέροντα στοιχεία και παραδείγματα χρήσης της Python3. Αυτό που ακολουθεί δεν είναι tutorial, αν θέλετε κάτι τέτοιο μπορείτε να βρείτε εξαιρετικά κείμενα on-line.

Strings

Η Python προσφέρει τους κλασσικούς τύπους δεδομένων (int, string κλπ). Τα αντικείμενα των τύπων αυτών είναι immutable, δηλαδή δεν αλλάζουν τιμή (μπορούν όμως να δημιουργηθούν νέα αντικείμενα ανά πάσα στιγμή).

Τα strings αποτελούν έναν πολύ εύχρηστο τύπο δεδομένων και μερικά χαρακτηριστικά τους δίνονται στη συνέχεια:

Οι σταθερές string εισάγονται με μονά ή διπλά εισαγωγικά

s = "abcd"
s2 = 'abcd' # ισοδύναμο με προηγούμενο

Τα strings ανήκουν στην κατηγορία τύπων sequence (διατεταγμένης ακολουθίας), άρα μπορούμε να πάρουμε επιμέρους τμήματα

>>> s = "abcdefg"
>>> s[0]
'a'
>>> s[3]
'd'
>>> s[-1]
'g'
>>> s[1:4]
'bcd'
>>> s[:-1]
'abcdef'
>>> s[2:]
'cdefg'

Για να καταλάβετε καλύτερα το πώς λαμβάνονται τα τμήματα μιας sequence (slicing), μπορείτε να σκεφτείτε ότι ο δείκτης i βρίσκεται ανάμεσα στα (i-1) και i στοιχεία (κι όχι πάνω στο στοιχείο i):

[a|b|c|d|e|f|g]
^ ^ ^ ^ ^ ^ ^ ^
0 1 2 3 4 5 6 7

το s[1:4] είναι ίσο με "bcd"

Θυμηθείτε όμως ότι δεν μπορούμε να αλλάξουμε περιεχόμενα σε ένα string (είναι immutable):

>>> s = "abcdefg"
>>> s[3] = 'x'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Μπορούμε όμως πάντοτε να δημιουργήσουμε ένα νέο string. Για παράδειγμα, για να επιτύχουμε το προηγούμενο:

>>> s = "abcdefg"
>>> s = s[:3]+'x'+s[4:]
>>> s
'abcxefg'

Τα αντικείμενα τύπου string διαθέτουν μια μεγάλη σειρά από χρήσιμες μεθόδους.

Σύνθετα Αντικείμενα

Το δυνατό σημείο της Python είναι τα σύνθετα αντικείμενα που παρέχει, τα οποία χρησιμοποιούμε για όλες τις δομές που θέλουμε να υλοποιήσουμε. Τα δύο βασικότερα είναι οι λίστες (lists) και τα λεξικά (dictionaries). Και οι δύο αυτοί τύποι αντικειμένων είναι mutable, τα αντικείμενά τους δηλαδή μπορούν να αλλάξουν περιεχόμενα.

Λίστες (Lists)

Οι λίστες ανήκουν στην κατηγορία sequence (όπως και τα strings) και υλοποιούν μια διατεταγμένη συλλογή αντικειμένων. Τα αντικείμενα που περιέχονται στη λίστα μπορούν να είναι οποιουδήποτε τύπου (ακόμα και άλλες λίστες). Εφόσον μια λίστα είναι sequence, μπορούμε να πάρουμε μέρος της, όπως σε ένα string:

>>> li = [1,2,'abcd','ef']
>>> li[1]
2
>>> li[-1]
'ef'
>>> li[:-1]
[1, 2, 'abcd']

Μπορούμε ακόμα να προσπελάσουμε ένα προς ένα τα στοιχεία της λίστας με την επαναληπτική δομή for <item> in <sequence>:

>>> for item in li:
...     print(item)
...
1
2
abcd
ef

Σε αντίθεση με τα strings, μπορούμε να αλλάξουμε τιμή σε ένα (υπάρχον) στοιχείο μιας λίστας:

>>> li = [1,2,'abcd','ef']
>>> li[0] = 33
>>> li
[33, 2, 'abcd', 'ef']

Μπορούμε να προσθέσουμε δυναμικά νέα στοιχεία σε μια λίστα:

>>> li = [1,2,3,'ab','cd']
>>> li += [11,22]
>>> li
[1, 2, 3, 'ab', 'cd', 11, 22]
>>> li.append(33)
>>> li
[1, 2, 3, 'ab', 'cd', 11, 22, 33]

Οι λίστες είναι δομές ειδικά βελτιστοποιημένες για ταξινόμηση (sorting). Εάν θέλουμε να ταξινομήσουμε πολύ γρήγορα μια σειρά στοιχείων, η χρήση λίστας είναι MUST!!!

>>> l = [6,8,-1,11]
>>> l.sort()
>>> l
[-1, 6, 8, 11]

Λεξικά (Dictionaries)

Τα λεξικά (dictionaries) είναι τύπου mapping: ζεύγη αντιστοιχιών (κλειδιού-τιμής).

  • Κάθε κλειδί πρέπει να είναι μοναδικό, αλλά όχι απαραίτητα του ίδιου τύπου με τα άλλα.

  • Δεν μπορείτε να χρησιμοποιήσετε λίστες ή λεξικά ως κλειδιά.

  • Η τιμή που αντιστοιχεί σε ένα κλειδί μπορεί να είναι οποιουδήποτε τύπου.

Οι πιο κοινές λειτουργίες σε λεξικά δίνονται στη συνέχεια.

Δημιουργήστε ένα κενό ή ένα αρχικοποιημένο με μερικά στοιχεία λεξικό:

>>> d = {}
>>> da = { 'mike': 32, 'nick': 43 }

Προσθέστε ένα νέο ζεύγος κλειδιού-τιμής (αν υπάρχει το κλειδί, παίρνει τη νέα τιμή):

>>> da['stef'] = 67
>>> da['mike'] = 'oops'
>>> da
{'mike': 'oops', 'stef': 67, 'nick': 43}

Ελέγξτε αν ένα κλειδί υπάρχει στο λεξικό:

>>> if 'stef' in da:
...     print('found')
...
found

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

>>> da = { 'mike': 32, 'nick': 43 }
>>> da['stef']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'stef'

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

>>> for k,v in da.items():
...     print(k,v)
...
mike 32
stef 67

Τα λεξικά είναι δομές ειδικά βελτιστοποιημένες για αναζήτηση (searching). Εάν θέλουμε να αναζητήσουμε πολύ γρήγορα ένα στοιχείο μέσα σε ένα μεγάλο σύνολο, η χρήση λεξικού είναι MUST!!!

Διαβάζοντας ένα ολόκληρο αρχείο κειμένου

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

Ο πιο απλός τρόπος για να διαβάσουμε ένα ολόκληρο αρχείο κειμένου στη μεταβλητή text σε μία μόνο γραμμή:

text = open('testpage.txt','r').read()

Στο προηγούμενο παράδειγμα η open() ανοίγει το αρχείο για ανάγνωση και επιστρέφει ένα αντικείμενο-αρχείο, του οποίου τη μέθοδο read() καλούμε στη συνέχεια. Η read() χωρίς ορίσματα θα διαβάσει το σύνολο του αρχείου.

Διαβάζοντας ένα αρχείο κειμένου γραμμή προς γραμμή

Σε πολλές περιπτώσεις, η επεξεργασία αρχείων κειμένου γίνεται γραμμή προς γραμμή. Αυτό συμβαίνει όταν κάθε γραμμή του κειμένου (και η επεξεργασία της) είναι ανεξάρτητη από τις υπόλοιπες γραμμές. Ιδιαίτερα σημαντική είναι η επεξεργασία γραμμή προς γραμμή σε πολύ μεγάλα αρχεία (δισεκατομμύρια γραμμές).

Σε αντίθεση με την ανάγνωση του συνόλου του αρχείου, εδώ έχουμε μια δομή επανάληψης for .. in .. που μας παρέχει το περιεχόμενο κάθε γραμμής ανά επανάληψη. Στο παράδειγμα που ακολουθεί, τοποθετούμε το for μέσα σε μια δομή with:

with open('sample1.txt','r') as fp:

  for line in fp:

    print(line,end='')

Η δομή with ... : της Python είναι ένας context manager. Θα φροντίσει να κλείσει το αρχείο στο τέλος της, ακόμα και αν ο κώδικας μέσα σε αυτήν προκαλέσει σφάλματα εκτέλεσης.

Στο προηγούμενο παράδειγμα, κάθε επανάληψη του for τοποθετεί μια νέα γραμμή κειμένου από το αρχείο στη μεταβλητή line. Η ανάγνωση αυτή διατηρεί το newline στο τέλος της γραμμής. Στο παράδειγμα, χρησιμοποιούμε το όρισμα end='' στην print() για να αποφύγουμε την προσθήκη ενός δεύτερου newline (κάτι που κάνει εξ’ ορισμού η print()).

Κλάσεις στην Python3: μια μικροσκοπική εισαγωγή

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

class Test:
        """ a class without parent """

        # put class code here
class Test2(Parent):
        """ a class having as parent the class Parent """

        # put class code here

Για να δημιουργήσουμε αντικείμενα μιας κλάσης χρησιμοποιούμε τη σύνταξη:

testobj = Test()

Οι μέθοδοι μέσα στις κλάσεις δηλώνονται με πρώτη παράμετρο το self που συμβολίζει το ίδιο το αντικείμενο της κλάσης. Το self χρησιμοποιείται για να αναφερθούμε τόσο σε μεταβλητές όσο και σε μεθόδους του αντικειμένου της κλάσης. Προσοχή! Το όρισμα self το παρέχει κατά την κλήση κάθε μεθόδου η Python, έτσι δεν πρέπει να το δώσουμε εμείς:

class Test:
        """ a test class """

        def testmethod(self,a,b):    # declaration of method "testmethod"
                self.t = a+b         # "self.t" is a class member variable

        def testmethod2(self):       # declaration of method "testmethod"
                self.testmethod(3,4) # call of class method "testmethod"

Η συνάρτηση __init__() έχει ειδικό ρόλο: καλείται κατά την αρχικοποίηση ενός αντικειμένου και μπορεί να δεχτεί αρχικές παραμέτρους για το νέο αντικείμενο:

class Test:
        """ a test class """

        def __init(self,size):
                self.size = size     # "self.size" is a class member variable


# elsewhere in program
t = Test(34)    # create a new Test instance with size = 34
print(t.size)   # print member variable "size" of instance "t" (will print 34)

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