flowchart LR
A["ορίσματα<br>double(7)"] --> F["double<br>(result = 2 * x)"]
F --> R["επιστρεφόμενη τιμή<br>14"]
Πληροφορική Ι
Εβδομάδα 6 · Συναρτήσεις (Μέρος Α΄)
(Οδηγίες χρήσης του διαδραστικού κώδικα: δείτε την αρχική σελίδα.)
1 Συναρτήσεις (Μέρος Α΄): Ορισμός, Παράμετροι, Επιστροφή Τιμών
1.1 Ορισμός και κλήση
Μια συνάρτηση είναι ένα τμήμα κώδικα που εκτελεί μια συγκεκριμένη διεργασία και καλείται από ένα πρόγραμμα ή από άλλη συνάρτηση. Μας βοηθούν να:
- οργανώσουμε λογικά ένα πρόγραμμα σε κομμάτια·
- αποφύγουμε την επανάληψη κώδικα, και να τον επαναχρησιμοποιήσουμε αλλού·
- σκεφτόμαστε σε επίπεδο «μαύρου κουτιού» — μας ενδιαφέρει τι κάνει μια συνάρτηση, όχι πώς.
def όνομα_συνάρτησης(παράμετρος_1, παράμετρος_2):
εντολές
return αποτέλεσμα # προαιρετικόΜια συνάρτηση είναι ένα «μαύρο κουτί»: δίνουμε ορίσματα, παίρνουμε πίσω μια τιμή, και δεν χρειάζεται να ξέρουμε τι γίνεται μέσα:
Ο κώδικας μιας συνάρτησης δεν εκτελείται όταν ορίζεται, παρά μόνο όταν κληθεί. Η σειρά ορισμού των συναρτήσεων μέσα σε ένα αρχείο δεν έχει σημασία, αρκεί να έχουν οριστεί πριν κληθούν.
Συνηθίζεται το κυρίως τμήμα ενός προγράμματος να μπαίνει σε μια συνάρτηση main, η οποία καλείται ρητά στο τέλος του αρχείου.
1.2 Είσοδος και έξοδος συναρτήσεων
Οι τιμές που δέχεται μια συνάρτηση λέγονται παράμετροι στον ορισμό της και ορίσματα στην κλήση της. Στην Python, τα ορίσματα μεταβιβάζονται με τιμή (pass-by-value): μια αλλαγή σε μια παράμετρο μέσα στη συνάρτηση δεν επηρεάζει τη μεταβλητή που χρησιμοποιήθηκε ως όρισμα στην κλήση.
Η επικοινωνία προς την “αντίθετη κατεύθυνση” — από τη συνάρτηση προς το σημείο κλήσης — γίνεται με την εντολή return, η οποία μπορεί να επιστρέψει και πολλαπλές τιμές ταυτόχρονα, χωρισμένες με κόμμα:
Μια συνάρτηση χωρίς return (ή με return χωρίς τιμή) επιστρέφει την ειδική τιμή None.
Πώς περνούν οι λίστες ως ορίσματα: μεταβίβαση με τιμή μιας αναφοράς
Είδαμε ότι μια επανεκχώρηση σε μια παράμετρο δεν επηρεάζει το όρισμα της κλήσης, αφού η Python μεταβιβάζει ορίσματα με τιμή (pass-by-value).
Με μεταβλητά (mutable) αντικείμενα, όπως οι λίστες (Εβδομάδα 4), χρειάζεται προσοχή. Το όνομα μιας λίστας είναι μια αναφορά (reference) στη θέση μνήμης των στοιχείων της (Εβδομάδα 1) — και αυτό ακριβώς που αντιγράφεται στην παράμετρο είναι η αναφορά, όχι ολόκληρη η λίστα. Δύο συνέπειες:
- Αν η συνάρτηση τροποποιήσει στοιχεία της λίστας (π.χ. με
append, ή με εκχώρησηlst[i] = ...), η αλλαγή είναι ορατή και έξω από τη συνάρτηση, αφού το όνομα του ορίσματος και η τοπική παράμετρος δείχνουν στην ίδια ακριβώς λίστα. - Αν όμως η συνάρτηση επανεκχωρήσει μια εντελώς νέα λίστα στην παράμετρο (π.χ.
lst = [...]), αυτό απλώς δίνει στο τοπικό όνομα μια νέα αναφορά, χωρίς να επηρεάζει καθόλου τη λίστα που είχε ο καλών.
Στην κλήση modify_list(data), το όρισμα data και η παράμετρος lst δείχνουν στην ίδια λίστα:
flowchart LR
data(["data (καλών)"]) --> L["[1, 2, 3]"]
lst(["lst (παράμετρος)"]) --> L
Το lst.append(100) αλλάζει αυτό το κοινό αντικείμενο (το βλέπει και το data). Το lst = [10, 20, 30] όμως στρέφει μόνο το lst σε νέα λίστα:
flowchart LR
data(["data (καλών)"]) --> L["[1, 2, 3, 100]"]
lst(["lst (παράμετρος)"]) --> N["[10, 20, 30] (νέα, τοπική)"]
Παρατηρήστε ότι το data “θυμάται” το append(100) (τροποποίηση στοιχείων), αλλά όχι την επανεκχώρηση lst = [10, 20, 30], ακριβώς επειδή μόνο το τοπικό όνομα lst άλλαξε αναφορά, όχι το ίδιο το αντικείμενο. Η ίδια ακριβώς λογική ισχύει και για κάθε άλλο μεταβλητό αντικείμενο (π.χ. πίνακες, Εβδομάδα 8).
1.3 Προεπιλεγμένες τιμές και ορίσματα με λέξη-κλειδί
Μια παράμετρος μπορεί να γίνει προαιρετική, ορίζοντας μια προεπιλεγμένη τιμή στον ορισμό της συνάρτησης (οι κανονικές παράμετροι πρέπει πάντα να προηγούνται):
Τα ορίσματα μπορούν επίσης να δοθούν με το όνομά τους (keyword arguments), οπότε η σειρά τους στην κλήση δεν έχει σημασία:
Συνηθισμένο λάθος: μεταβλητά προεπιλεγμένα ορίσματα
Μια ιδιαιτερότητα της Python που εκπλήσσει πολύ κόσμο: η προεπιλεγμένη τιμή μιας παραμέτρου υπολογίζεται μία φορά μόνο, τη στιγμή που ορίζεται η συνάρτηση — όχι σε κάθε κλήση.
Αν λοιπόν είναι μεταβλητό αντικείμενο (μια λίστα), το ίδιο αντικείμενο επαναχρησιμοποιείται σε κάθε κλήση χωρίς ρητό όρισμα — και οι τροποποιήσεις του «επιβιώνουν» από κλήση σε κλήση:
Η καθιερωμένη λύση είναι να χρησιμοποιήσουμε None ως προεπιλεγμένη τιμή, και να δημιουργήσουμε μια καινούρια λίστα μέσα στη συνάρτηση, μόνο όταν χρειάζεται:
2 Σύνοψη
Σε αυτή την εβδομάδα είδαμε:
- Τον ορισμό και την κλήση συναρτήσεων: παραμέτρους, ορίσματα, και την εντολή
return(και επιστροφή πολλαπλών τιμών). - Πώς περνούν πραγματικά τα ορίσματα στην Python: μεταβίβαση με τιμή μιας αναφοράς, και τη διαφορά ανάμεσα σε τροποποίηση και επανεκχώρηση για μεταβλητά ορίσματα.
- Προεπιλεγμένες τιμές και ορίσματα με λέξη-κλειδί.
- Την παγίδα των μεταβλητών προεπιλεγμένων ορισμάτων.
⤺ Πίσω στην αρχική σελίδα / πρόγραμμα μαθήματος · Διαφάνειες αυτής της εβδομάδας