Συναρτήσεις
Εντολή def
Εισαγωγή. Πολλά προγράμματα τα οποία φτιάξαμε μέχρι τώρα θα μπορούσαμε να τα δούμε και ως ολοκληρωμένες μεθόδους οι οποίες παίρνουν δεδομένα και πετυχαίνουν ένα αποτέλεσμα. Για παράδειγμα, μπορούμε να βρούμε τον μεγαλύτερο μεταξύ δύο αριθμών ως εξής:
x = 5.0
y = 6.0
if x >= y:
maxx = x
else
maxx = y
print(maxx)
Το τμήμα του παραπάνω προγράμματος το οποίο κάνει τον υπολογισμό του μεγίστου μπορούμε να το διαχωρίσουμε ως εξής:
def maximum(x,y):
if x >= y:
maxx = x
else
maxx = y
return maxx
Η λέξη def
είναι δεσμευμένη, είναι μία εντολή της python
και ορίζει μία συνάρτηση.
- Η πρώτη γραμμή περιέχει το όνομα της συνάρτησης (η παραπάνω λέγεται
maximum
), επίσης τα ορίσματα σε παρένθεση και η γραμμή τελειώνει με την άνω-κάτω τελεία. Το όνομα μιας συνάρτησης ακολουθεί τους συνηθισμένους κανόνες της Python για τα ονόματα μεταβλητών. - Όλες τις εντολές που περιέχονται στη συνάρτηση βρίσκονται σε εσοχή (tab).
- Η συνάρτηση τελειώνει με την εντολή
return
η οποία καθορίζει ποιά είναι η τιμή της συνάρτησης.
Το αρχικό πρόγραμμα μπορεί να εκτελεστεί τώρα με τις εντολές.
result = maximum(5.0,6.0)
print(result)
Δείτε ότι το πρόγραμμά μας αποτελείται τώρα από δύο τμήματα: τη συνάρτηση και το κύριο πρόγραμμα (το οποίο ακολουθεί τη συνάρτηση και περιέχει μία γραμμή για τη χρήση της συνάρτησης.)
Ας δούμε τι ακριβώς συμβαίνει όταν στο πρόγραμμά μας περιέχεται μία συνάρτηση
(π.χ. maximum
) και γράφουμε maximum(a,b)
.
- Λέμε ότι η συνάρτηση
maximum
καλείται με τις πραγματικές παραμέτρους (ή ορίσματα)a,b
. Αυτές μπορεί να είναι αριθμοί (π.χ.,maxx=maximum(5.0,6.0)
) αλλά μπορεί να είναι και μεταβλητές οι οποίες έχουν τιμές (π.χ.,a=3.0; b=4.0; maxx=maximum(a,b)
). - Με την κλήση της συνάρτησης συμβαίνουν δύο πράγματα:
Οι τυπικές παράμετροι της συνάρτησης παίρνουν τιμές
(
x=5.0; y=6.0
είτεx=a; y=b
) και το πρόγραμμα συνεχίζει με τις εντολές εντός της συνάρτησης. - Όταν βρεθεί εντολή
return
ο έλεγχος επιστρέφει στο κύριο πρόγραμμα. - Η τιμή της μεταβλητής που βρίσκεται δίπλα στην
return
(δηλαδή,maxx
) είναι η τιμή της συνάρτησης. Αυτή δίδεται στο κύριο πρόγραμμα (στη μεταβλητήresult
) αριστερά της ισότητας στην κλήση της συνάρτησης. - Ο έλεγχος έχει τώρα επιστρέψει στο κύριο πρόγραμμα και εκτελούνται οι εντολές μετά της κλήση της συνάρτησης.
Παράδειγμα. Γράψτε μία συνάρτηση η οποία να υπολογίζει την τιμή της $f(x) = x^2 - 2x + 1$. Καλέστε την από το κύριο πρόγραμμα για μία τιμή του $x$ και τυπώστε τα $x, f(x)$.
def f(x):
fvalue = x**2 - 2*x + 1
return fvalue
x = 3.0
result = f(x)
print(x,result)
Παράδειγμα.
Γράψτε μία συνάρτηση η οποία να ελέγχει αν το όνομά μας τελειώνει σε "ακης" (akis).
Σε αυτή την περίπτωση η τιμή της θα είναι True
, αλλιώς η τιμή της συνάρτησης θα είναι False
.
def name_end(s):
if s[-4:] == 'akis':
return True
else:
return False
name = input("Give a name: ")
print(name_end(name))
Εντολή return
.
Σημειώστε ότι η εμφάνιση της εντολής return σε οποιοδήποτε σημείο στο σώμα μιας συνάρτησης τερματίζει την εκτέλεση των εντολών της συνάρτησης και επιστρέφει τη ροή του προγράμματος στο σημείο αμέσως μετά την κλήση της. Η χρήση της εντολής return είναι προαιρετική. Αν αυτή δεν εμφανίζεται ή η εμφάνισή της δεν ακολουθείται από κάποια έκφραση, τότε η συνάρτηση επιστρέφει την τιμή None.
Παράδειγμα. [Πηγή: Σημειώσεις Μ. Πλεξουσάκη.] Ας ορίσουμε μία συνάρτηση η οποία τυπώνει το μήνυμα Hello! όποτε κληθεί:
def sayHello():
print('Hello!')
Ας την καλέσουμε:
>>> sayHello()
Hello!
Αν όμως είχαμε γράψει print(sayHello(), 'Maria')
θα βλέπαμε το μήνυμα None Maria
γιατί None
είναι η τιμή η οποία επιστρέφει η συνάρτηση sayHello
.
Δείτε ακόμα ότι η συνάρτηση αυτή δεν έχει τυπικά ορίσματα και γι' αυτό η λίστα των τυπικών ορισμάτων της είναι κενή, αλλά η κλήση της συνάρτηση διατηρεί την κενή λίστα των ορισμάτων.
Παρατήρηση. Το κεντρικό πλεονέκτημα των συναρτήσεων είναι ότι μπορούμε να τις καλούμε επανειλημμένα από το κύριο πρόγραμμα. Ο κώδικας που περιέχεται στη συνάρτηση εκτελείται σε κάθε κλήση της από το κύριο πρόγραμμα.
Γραφική επανάληψη
Ενσωματωμένες συναρτήσεις (built-in functions)
Πρέπει να παρατηρήσουμε ότι έχουμε ήδη δει συναρτήσεις σε προηγούμενα μαθήματα,
όπως αυτές τις οποίες παρέχει το πακέτο math
.
math.sin(x), math.cos(x), math.abs(x),
etc.
Παρατηρήστε ότι όλες οι παραπάνω παίρνουν ένα όρισμα και επιστρέφουν μία τιμή,
όπως ακριβώς οι συναρτήσεις που ορίζονται με την εντολή def
.
Επίσης, έχουμε δει ενσωματωμένες συναρτήσεις της python.
type(a), print(), len(s)
etc.
Παρατήρηση. Η χρήση συναρτήσεων είναι ιδαίτερα διαδεδομένη σε μία γλώσσα προγραμματισμού (όπως η python). Αυτό ισχύει και για τις ενσωματωμένες συναρτήσεις και για αυτές τις οποίες γράφει ο προγραμματιστής. Και τα δύο είδη συναρτήσεων χρησιμοποιούνται με τον ίδιο τρόπο, όπως είδαμε.
Εμβέλεια μεταβλητών
Παράδειγμα. [Πηγή: Σημειώσεις Μ. Πλεξουσάκη.] Ας γράψουμε μια συνάρτηση η οποία, δεδομένου του φυσικού αριθμού $n$, υπολογίζει το άθροισμα $1^2 + 2^2 + \cdots + n^2$.
def sumsq(n):
if n <= 0:
return 0
s = 0
for i in range(1, n+1):
s += i*i
return s
print('Sum of the squares of the first four integers =', sumsq(4))
Το σώμα μιας συνάρτησης μπορεί να περιέχει οποιαδήποτε εντολή της Python, συμπεριλαμβανομένης, φυσικά, και της εντολής ανάθεσης. Το σώμα της παραπάνω συνάρτησης sumsq
κάνει χρήση δύο μεταβλητών, των i και s. Η πρώτη είναι η μεταβλητή της ανακύκλωσης for
και η δεύτερη περιέχει το τρέχων άθροισμα.
Είναι σημαντικό να καταλάβουμε ότι αυτές οι μεταβλητές είναι "τοπικές" με την έννοια ότι είναι άγνωστες στο υπόλοιπο μέρος του προγράμματός μας.
Αν, για παράδειγμα, προσπαθούσαμε να τυπώσουμε και την τιμή του μετρητή της ανακύκλωσης, εκτός του σώματος της συνάρτησης, θα παίρναμε το μήνυμα σφάλματος
NameError: name 'i' is not defined.
Το ίδιο ακριβώς συμβαίνει και με τα τυπικά ορίσματα μιας συνάρτησης: συμπεριφέρονται ως τοπικές μεταβλητές, είναι άγνωστες δηλαδή εκτός του σώματος της συνάρτησης. Το γεγονός αυτό μας επιτρέπει να γράψουμε τον κώδικα για τη συνάρτηση sumsq
ως εξής:
def sumsq(n):
if n <= 0: return 0
s = 0
while n > 0:
s += n*n
n -= 1
return s
print('Sum of the squares of the first four integers =', sumsq(4))
Επιπλέον, εκτός του σώματος της συνάρτησης sumsq
μπορούμε να χρησιμοποιήσουμε το όνομα n ως όνομα μεταβλητής και η οποία δεν έχει καμμία απολύτως σχέση με το τυπικό όρισμα της sumsq
με το ίδιο όνομα. Ίσα-ίσα, αυτό τονίζει τη σχέση με το τοπικό όρισμα της sumsq
.
def sumsq(n):
if n <= 0: return 0
s = 0
while n > 0:
s += n*n
n -= 1
return s
n = 7
print('Sum of the squares of the first', n, 'integers =', sumsq(n))
Παρατήρηση. Η Python, κατά τον ορισμό μιας συνάρτησης δημιουργεί τον λεγόμενο χώρο ονομάτων (namespace) ο οποίος περιέχει τόσο τα τυπικά ορίσματα της συνάρτησης αλλά και μεταβλητές τις οποίες χρησιμοποιεί, για τις ανάγκες της η συνάρτηση. Τα ονόματα αυτών των μεταβλητών είναι άγνωστα έξω από το χώρο ονομάτων. Αναφερόμαστε στις μεταβλητές που εμφανίζονται στο χώρο ονομάτων μιας συνάρτησης ως τοπικές μεταβλητές. Τα τυπικά ορίσματα συμπεριφέρονται κι αυτά ως τοπικές μεταβλητές μέσα στο σώμα της συνάρτησης.
Παράδειγμα. Ας δούμε τη συνάρτηση:
def f(x):
y = 1
x = x + y
print('x =', x, 'y =', y)
return x
x = 3
y = 2
z = f(x)
print('x =', x)
print('y =', y)
print('z =', z)
Παρατηρούμε ότι το όνομα x εμφανίζεται τόσο ως τυπικό όρισμα της συνάρτησης f αλλά και στον κώδικα ο οποίος περιέχει την κλήση της συνάρτησης (κύριο πρόγραμμα). Επίσης, το σώμα της συνάρτησης περιέχει την μεταβλητή y η οποία εμφανίζεται επίσης και εκτός του σώματος της συνάρτησης.
Αν εκτελέσουμε το πρόγραμμα θα δούμε τα παρακάτω αποτελέσματα
x = 4 y = 1
x = 3
y = 2
z = 4
τα οποία δείχνουν ότι οι μεταβλητές x, y
εντός του σώματος της συνάρτησης είναι διαφορετικές από τις μεταβλητές x, y
στο κύριο πρόγραμμα
(βρίσκονται σε διαφορετικούς χώρους ονομάτων (namespace).):
Καθολικές μεταβλητές
Σε πολλές περιπτώσεις το προβλημά μας περιέχει παραμέτρους (ή μεταβλητές) οι οποίες θα θέλαμε να χρησιμοποιηθούν τόσο στο κύριο πρόγραμμα όσο και σε συναρτήσεις.
Μπορούμε να καθορίσουμε ότι αναφερόμαστε σε μία συγκεκριμένη μεταβλητή σε διαφορετικά τμήματα του προγράμματος (π.χ., στο κύριο πρόγραμμα και σε μία συνάρτηση) δηλώνοντάς την με την εντολή global
.
Παράδειγμα. (Φυσικές σταθερές) Ας υπολογίσουμε, με τη βοήθεια συνάρτησης, τη θέση σώματος σε ελεύθερη πτώση.
# function
def height(t):
global g
y = 0.5*g*t**2
return y
# Main program
global g
g = 10.0 # give value to parameter
time = float(input("Give time: ")
print(time,height(time))
Ας υπολογίσουμε επίσης τη θέση σώματος σε ελεύθερη πτώση με αρχική ταχύτητα $v_0$. Θα οργανώσουμε το πρόγραμμα ώστε όλες οι φυσικές σταθερές να παίρνουν τιμές μέσω μίας νέας συνάρτησης. [κώδικας]
# Functions
def physicalParams():
global g,v0
g = 10.0
v0 = 10.0
def height(t):
global g,v0
y = v0*t-0.5*g*t**2
return y
# Main program
global g,v0
physicalParams()
time = float(input("Give time: "))
print(time,height(time))
Ερώτηση. Θα μπορούσαμε να παραλείψουμε κάποια από τις εντολές global στο παραπάνω πρόγραμμα; (ποιά;)
Προδιαγραφές
Εισαγωγή.
Για κάθε συνάρτηση μπορούμε να πάρουμε ένα κείμενο το οποίο αναφέρει τις προδιαγραφές της, δηλαδή, βασικές πληροφορίες γι' αυτήν: τον τύπο και τη σημασία των τυπικών ορισμάτων καθώς και την πληροφορία που επιστρέφει η συνάρτηση. Αυτά μπορούμε να τα ανακαλέσουμε με την εντολή help
.
Παράδειγμα. Για τις ενσωματωμένες συναρτήσεις έχουμε:
>>> help(len)
Help on built-in function len in module builtins:
>>> help('math.exp')
Help on built-in function exp in math:
math.exp = exp(...)
exp(x)
Return e raised to the power of x.
Όταν γράφουμε μία συνάρτηση μπορούμε να καθορίσουμε τις προδιαγραφές της σε κείμενο το οποίο γράφουμε στις επόμενες γραμμές μετά την εντολή Παράδειγμα. Ας συμπληρώσουμε τη συνάρτηση την οποία δώσαμε νωρίτερα, με τις προδιαγραφές της.
Μπορούμε τώρα να ανακαλέσουμε τις προδιαγραφές της συνάρτησης:
"""
.
(Το κείμενο αυτό λέγεται docstring.)
def organizeName(firstName, lastName, reverse = False):
"""firstName, lastName are strings, reverse is a boolean
if reverse==False returns firstName lastName
if reverse==True returns lastName, firstName"""
if reverse == True:
s = lastName + ', ' + firstName
else:
s = firstName + ' ' + lastName
return s
>>> help(organizeName)
organizeName(firstName, lastName, reverse=False)
firstName, lastName are strings, reverse is a boolean
if reverse==False returns firstName lastName
if reverse==True returns lastName, firstName
Γραφική επανάληψη
Μελέτη
Βιβλιογραφία
- Δημήτριος Καρολίδης, Μαθαίνετε εύκολα python (Εκδόσεις Καρολίδη, 2016).
- Κ. Μαγκούτης, Χ. Νικολάου, Εισαγωγή στον αντικειμενοστραφή προγραμματισμό με Python, (Αποθετήριο "Κάλλιπος", 2016) - Κεφάλαιο 4. Συναρτήσεις και εκτέλεση υπό συνθήκη.
- J.V. Guttag, Υπολογισμοί και προγραμματισμός με την python, Κεφάλαιο 4.