Συναρτήσεις

Εντολή 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 και ορίζει μία συνάρτηση.

Το αρχικό πρόγραμμα μπορεί να εκτελεστεί τώρα με τις εντολές.


result = maximum(5.0,6.0)
print(result)

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

Ας δούμε τι ακριβώς συμβαίνει όταν στο πρόγραμμά μας περιέχεται μία συνάρτηση (π.χ. maximum) και γράφουμε maximum(a,b).

Παράδειγμα. Γράψτε μία συνάρτηση η οποία να υπολογίζει την τιμή της $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. Δείτε ακόμα ότι η συνάρτηση αυτή δεν έχει τυπικά ορίσματα και γι' αυτό η λίστα των τυπικών ορισμάτων της είναι κενή, αλλά η κλήση της συνάρτηση διατηρεί την κενή λίστα των ορισμάτων.

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

Γραφική επανάληψη

Function form
Σχήμα. Η γενική μορφή μιας συνάρτησης και η κλήση της από το κύριο πρόγραμμα.

Ενσωματωμένες συναρτήσεις (built-in functions)

Πρέπει να παρατηρήσουμε ότι έχουμε ήδη δει συναρτήσεις σε προηγούμενα μαθήματα, όπως αυτές τις οποίες παρέχει το πακέτο math.

Παρατηρήστε ότι όλες οι παραπάνω παίρνουν ένα όρισμα και επιστρέφουν μία τιμή, όπως ακριβώς οι συναρτήσεις που ορίζονται με την εντολή def.

Επίσης, έχουμε δει ενσωματωμένες συναρτήσεις της python.

Παρατήρηση. Η χρήση συναρτήσεων είναι ιδαίτερα διαδεδομένη σε μία γλώσσα προγραμματισμού (όπως η 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.

Όταν γράφουμε μία συνάρτηση μπορούμε να καθορίσουμε τις προδιαγραφές της σε κείμενο το οποίο γράφουμε στις επόμενες γραμμές μετά την εντολή def και το οποίο περιέχεται ανάμεσα σε σύμβολα """. (Το κείμενο αυτό λέγεται 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

Γραφική επανάληψη

Function form
Σχήμα. Η γενική μορφή μιας συνάρτησης.

Μελέτη

Βιβλιογραφία

  1. Δημήτριος Καρολίδης, Μαθαίνετε εύκολα python (Εκδόσεις Καρολίδη, 2016).
  2. Κ. Μαγκούτης, Χ. Νικολάου, Εισαγωγή στον αντικειμενοστραφή προγραμματισμό με Python, (Αποθετήριο "Κάλλιπος", 2016) - Κεφάλαιο 4. Συναρτήσεις και εκτέλεση υπό συνθήκη.
  3. J.V. Guttag, Υπολογισμοί και προγραμματισμός με την python, Κεφάλαιο 4.