Η έννοια της συνάρτησης στην Python

Η έννοια της συνάρτησης

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

Θα ήταν ωραίο στον προγραμματισμό να γράφαμε το μπλοκ μια φορά και να αναφερόμαστε σε αυτό μέσα στο πρόγραμμα μας στην κατάλληλη θέση χωρίς να χρειαστεί να το ξαναγράφουμε.

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

Δημιουργώντας μια συνάρτηση

Για να δημιουργήσουμε μια συνάρτηση στην Python χρησιμοποιούμε τη λέξη κλειδί def ακολουθούμενο από το όνομα της συνάρτησης με παρενθέσεις, όπως: def name():

Σημειώστε την ύπαρξη της άνω και κάτω τελείας. Τώρα μπορούμε να τοποθετήσουμε το σώμα της συνάρτησης σε εσοχή κάτω από αυτή την πρόταση.

def myfunction():
    entoli1
    entoli2

Όταν τελειώσουμε με την καταχώρηση των εντολών της συνάρτησης, απλά γράφουμε τις επόμενες εντολές του κυρίως προγράμματος αριστερά.

Χρησιμοποιώντας συναρτήσεις

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

def func1():
    print('Αυτό είναι ένα παράδειγμα συνάρτησης')
count=1
while count<=4 :
    func1()
    count=count+1
print('Αυτό είναι το τέλος του βρόγχου')
print('Αυτό είναι το τέλλος του προγράμματος')

Όταν τρέξεις το πρόγραμμα θα πάρεις την ακόλουθη έξοδο:

Αυτό είναι ένα παράδειγμα συνάρτησης
Αυτό είναι ένα παράδειγμα συνάρτησης
Αυτό είναι ένα παράδειγμα συνάρτησης
Αυτό είναι ένα παράδειγμα συνάρτησης
Αυτό είναι το τέλος του βρόγχου
Αυτό είναι το τέλος του προγράμματος

Η δήλωση μιας συνάρτησης δεν χρειάζεται να είναι το πρώτο πράγμα σε ένα πρόγραμμα Python. Προσέξτε αν προσπαθήσετε να χρησιμοποιήσετε μια συνάρτηση πριν την δηλώσετε, τότε θα πάρετε ένα μήνυμα λάθους.

Επίσης χρειάζεται να προσέξετε με τα ονόματα συναρτήσεων. Κάθε όνομα συνάρτησης θα πρέπει να είναι μοναδικό αλλιώς θα δημιουργηθούν προβλήματα. Εάν ξαναορίσεις μια συνάρτηση, ο νέος ορισμός θα επικαλύψει την αρχική συνάρτηση χωρίς να παρουσιαστούν μηνύματα λάθους. Για παράδειγμα δίνεται το ακόλουθο απόσπασμα κώδικα:

def func1():
    print('Αυτός είναι ο αρχικός ορισμός της συνάρτησης')
func1()
def func1():
    print('Αυτό είναι η επικάλυψη της αρχικής συνάρτησης')
func1()
print('Αυτό είναι το τέλος του προγράμματος')

Όταν τρέξεις τον παραπάνω κώδικα θα πάρεις την ακόλουθη έξοδο:

Αυτός είναι ο αρχικός ορισμός της συνάρτησης
Αυτό είναι η επικάλυψη της αρχικής συνάρτησης
Αυτό είναι το τέλος του προγράμματος

Επιστρέφοντας μια τιμή

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

Η εντολή return θα πρέπει να είναι η τελευταία εντολή της συνάρτησης. Στην περίπτωση που η συνάρτηση δεν επιστρέφει τιμή, η ύπαρξη της εντολής return είναι προαιρετική. Μελετήστε την ακόλουθη σύνταξη όταν η συνάρτηση επιστρέφει μια τιμή.

def func2():
     entoli1
     entoli2
     return value

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

def db1():
    value = int(input('Enter a value: '))
    print('doubling the value')
    result = value*2
    return result
x = db1()
print('The new value is ', x)

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

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

Enter a value: 10
doubling the value
The new value is  20

Παρατήρηση: σε αυτό το πρόγραμμα η συνάρτηση επιστρέφει ένα ακέραιο αριθμό. Όμως μπορεί να επιστρέψει μια συμβολοσειρά, ένα αριθμό κινητής υποδιαστολής και κάθε άλλο αντικείμενο Python.

Περνώντας τιμές σε μια συνάρτηση

Μια άλλη κατηγορία συναρτήσεων είναι εκείνες που παίρνουν δεδομένα από το κυρίως πρόγραμμα και τα επεξεργάζονται κατάλληλα. Οι τιμές που περνάμε σε μια συνάρτηση κατά την κλίση της ονομάζονται ορίσματα. Π.χ. result = func3(20, 30)

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

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

>>> def addem(a, b):
         result = a + b
         return result
>>>

Η συνάρτηση addem() δηλώνεται με δυο παραμέτρους a και b. Η μεταβλητή a παίρνει το πρώτο όρισμα, ενώ η μεταβλητή b παίρνει το δεύτερο όρισμα. Μετά από αυτό μπορούμε να χρησιμοποιήσουμε τις μεταβλητές a και b οπουδήποτε μέσα στο σώμα της συνάρτησης.

Τώρα αν καλέσουμε την συνάρτηση addem() μέσα από το κυρίως πρόγραμμα, πρέπει να περάσουμε δυο ορίσματα.

>>> total = addem(20, 60)
>>> print(total)
80
>>>

Μπορούμε να χρησιμοποιήσουμε μεταβλητές και να τις περάσουμε σαν ορίσματα όταν καλούμε μια συνάρτηση, όπως φαίνεται παρακάτω:

>>> x = 200
>>> y = 300
>>> total = addem(x, y)
>>> print(total)
500
>>>

Μέσα στη συνάρτηση addem() η Python παίρνει την τιμή που είναι αποθηκευμένη στη μεταβλητή x του κυρίους προγράμματος και την αποθηκεύει στη μεταβλητή a μέσα στη συνάρτηση. Όμοια η Python παίρνει την τιμή της y μεταβλητής του κυρίους προγράμματος και την αποθηκεύει στη μεταβλητή b μέσα στη συνάρτηση.

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

>>> def addem(a, b):
        result = a + b
        return result

>>> print(addem(10, 15))
25
>>> print(addem(10))
    Traceback (most recent call last):
      File "<pyshell#15>", line 1, in <module>
      print(addem(10))
    TypeError: addem() missing 1 required positional argument: 'b'
>>> print(addem(10, 15, 20))
    Traceback (most recent call last):
      File "<pyshell#16>", line 1, in <module>
      print(addem(10, 15, 20))
    TypeError: addem() takes 2 positional arguments but 3 were given

Θέτοντας προκαθορισμένες τιμές στις παραμέτρους συνάρτησης

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

>>> def area(width=10, height=20):
        area = width * height
        return area

Εάν καλέσουμε την συνάρτηση area περνώντας ορίσματα, η Python χρησιμοποιεί αυτά τα ορίσματα αντί τις προεπιλεγμένες τιμές.

>>> total = area(15, 30)
>>> print(total)
450
>>>

Εάν καλέσουμε την συνάρτηση χωρίς ορίσματα, αντί να πάρουμε μήνυμα λάθους, η Python χρησιμοποιεί τις προκαθορισμένες τιμές στις παραμέτρους:

>>> total2 = area()
>>> print(total2)
200
>>>

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

>>>area(15)
300
>>>

Εάν θέλουμε να περάσουμε μια τιμή για τη δεύτερη παράμετρο, αλλά όχι για την πρώτη, πρέπει να δηλώσουμε την τιμή του ορίσματος με το όνομα, όπως:

>>> area(height=15)
150
>>>

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

>>> def area2(width, height=20):
       area2 = width*height
       print('The width is:  ', width)
       print('The height is:  ', height)
       print('The area is:  ', area2)

Σε αυτή τη συνάρτηση το πέρασμα ορίσματος στην παράμετρο with_m είναι υποχρεωτική ενώ στην παράμετρο height_m είναι προαιρετικό. Εάν καλέσουμε την συνάρτηση area2 με ένα όρισμα η Python το εκχωρεί στη μεταβλητή with_m όπως φαίνεται στο ακόλουθο παράδειγμα:

>>> area2(10)
>>> The width is: 10
>>> The height is: 20
>>> The area is: 200

Εάν καλέσουμε την συνάρτηση area2 χωρίς ορίσματα η Python θα δώσει μήνυμα λάθους.

Πέρασμα μεταβλητού αριθμού ορισμάτων σε συνάρτηση

Σε ορισμένες περιπτώσεις θέλουμε να περάσουμε διαφορετικό πλήθος ορισμάτων σε μια συνάρτηση. Η Python μας παρέχει αυτή την δυνατότητα με την ακόλουθη μορφή:

def func3(*args)

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

Μπορούμε να ανακτάμε κάθε όρισμα ξεχωριστά χρησιμοποιώντας δείκτες. Στο παράδειγμα η Python εκχωρεί το πρώτο όρισμα στη μεταβλητή args[0], το δεύτερο όρισμα στη μεταβλητή args[1] κ.τ.λ. έτσι ώστε όλα τα ορίσματα να εκχωρηθούν στη συνάρτηση.

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

def perimeter(*args):
    sides = len(args)
    print('There are', sides, 'sides to the object')
    total = 0
    for i in range(0, sides):
       total = total + args[i]
    return total

object1=perimeter(2, 3, 4)
print('The perimeter of object1 is:', object1)
object2=perimeter(10, 20, 10, 20)
print('The perimeter of object2 is:', object2)
object3=perimeter(10, 10, 10, 10, 10, 10, 10, 10)
print('The perimeter of object3 is:', object3)

Σε αυτό το πρόγραμμα Python, η συνάρτηση perimeter χρησιμοποιεί την παράμετρο *args για πάρει τα ορίσματα που περνούμε στη συνάρτηση. Επειδή δεν γνωρίζουμε πόσα ορίσματα θα χρησιμοποιηθούν όταν η συνάρτηση κλιθεί, χρησιμοποιούμε τη συνάρτηση len() για να βρούμε πόσες τιμές έχει η πλειάδα args. Χρησιμοποιούμε το βρόγχο for για να απαριθμήσουμε  από το 0 μέχρι τον αριθμό των στοιχείων της πλειάδας και μετά κάνουμε χρήση της μεταβλητής args[i] για να γίνει αναφορά σε κάθε όρισμα ξεχωριστά.

Αυτό το παράδειγμα χρησιμοποιεί τη συνάρτηση perimeter() με διαφορετικό αριθμό ορισμάτων. Τρέχοντας το πρόγραμμα παίρνουμε την έξοδο:

There are 3 sides to the object
The perimeter of object1 is: 9
There are 4 sides to the object
The perimeter of object2 is: 60
There are 8 sides to the object
The perimeter of object3 is: 80

Τοπικές και καθολικές μεταβλητές

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

Ένα παράδειγμα κώδικα Python που χρησιμοποιεί τοπικές μεταβλητές είναι το ακόλουθο:

def area3(width, height):
   total = width * height
   print('Inside the area3() function, the value of width is: ', width)
   print('Inside the area3() function, the value of height is: ', height)
object1 = area3(10, 40)
print('Outside the function, the value of width is: ', width)
print('Outside the function, the value of height is: ', height)
print('The area is:', object1)

Το πρόγραμμα ορίζει την συνάρτηση area() με δυο παραμέτρους στην κεφαλίδα της και μια μέσα στο σώμα της οι οποίες χρησιμοποιούνται στον υπολογισμό του εμβαδού. Εάν προσπαθήσεις να αναφερθείς σε αυτές τις μεταβλητές έξω από την συνάρτηση θα πάρεις μήνυμα λάθους.

Inside the area3() function, the value of width is:  10
Inside the area3() function, the value of height is:  40
Traceback (most recent call last):
  File "C:/Users/Click/Desktop/test_eisagogi/test_python_14.py", line 6, in <module>
    print('Outside the function, the value of width is: ', width)
NameError: name 'width' is not defined

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

width = 10
height = 60
total = 0
def area4():
   total = width * height
   print('Inside the function the total is:', total)
area4()
print('Outside the function the total is:', total)

Στο πρόγραμμα ορίζουμε τρεις καθολικές μεταβλητές τις width, height και total. Η συνάρτηση area4() διαβάζει αυτές τις μεταβλητές με τιμή, αλλά υπάρχει μια ιδιαιτερότητα. Εάν διαβάσουμε την τιμή της total μετά που θα καλέσουμε την συνάρτηση area(), θα πάρουμε την τιμή της total που έχει πριν την κλήση της συνάρτηση area().

Inside the function the total is: 600
Outside the function the total is: 0

Μπορούμε να πούμε στην Python η συνάρτηση area() να έχει πρόσβαση στην total και κατά την έξοδο από την συνάρτηση να διατηρήσει την τιμή της. Μπορούμε να το κάνουμε προσθέτοντας την λέξη κλειδί global μπροστά από τον ορισμό της μεταβλητής. Δείτε το ακόλουθο απόσπασμα κώδικα:

width = 10
height = 60
total = 0
def area4():
   global total
   total = width * height
   print('Inside the function the total is:', total)
area4()
print('Outside the function the total is:', total)

Προσθέτοντας την λέξη κλειδί global πριν τη δήλωση της μεταβλητής, ο κώδικας τρέχει κανονικά, όπως:

Inside the function the total is: 600
Outside the function the total is: 600