Γλώσσες Προγραμματισμού Εφαρμογών - ΜΕΠΒ20 Διάλεξη 3 Συναρτήσεις, Εμβέλεια, Πακέτα Παπαϊωάννου Αθανάσιος Π.Μ.Σ. «Εφαρμοσμένη Πληροφορική» Χειμερινό Εξάμηνο 20 16-20 17
Αποθηκευμένα (και επαναχρησιμοποιούμενα) Βήματα def thing() print 'Zip' thing() hello(): print 'Hello' print 'Fun' Πρόγραμμα: def thing(): print('hello') print('fun') thing() print ('Zip') thing() Έξοδος: Hello Fun Zip Hello Fun Ονομάζουμε αυτά τα επαναχρησιμοποιούμενα κομμάτια κώδικα συναρτήσεις.
Συναρτήσεις στη Python Υπάρχουν δύο ειδών συναρτήσεις στη Python. Οι ενσωματωμένες συναρτήσεις οι οποίες μας παρέχονται σαν ένα κομμάτι της Python - input(), type(), float(), int()... Συναρτήσεις τις οποίες προσδιορίζουμε εμείς και μετά χρησιμοποιούμε. Συμπεριφερόμαστε στα ονόματα των ενσωματωμένων συναρτήσεων σαν νέες κατειλημμένες λέξεις (δηλ., τις αποφεύγουμε σαν ονόματα μεταβλητών).
Προσδιορισμός Συναρτήσεων Στη Python μία συνάρτηση είναι ένας επαναχρησιμοποιούμενος κώδικας ο οποίος παίρνει κάποιες παραμέτρους σαν είσοδο, κάνει κάποιο υπολογισμό, και επιστρέφει ένα αποτέλεσμα ή αποτελέσματα. Προσδιορίζουμε μία συνάρτηση χρησιμοποιώντας την κατειλημμένη λέξη def. Καλούμε / επικαλούμαστε τη συνάρτηση χρησιμοποιώντας το όνομά της, παρένθεση και τις παραμέτρους ως εκφράσεις.
Παράμετρος big = max('hello world') Εκχώρηση 'w' Αποτέλεσμα >>> big=max('hello world') >>> print(big) w >>> tiny=min('hello world') >>> print(tiny) >>>
Η Συνάρτηση Max >>> big = max('hello world') >>> print(big) w Μία συνάρτηση είναι αποθηκευμένος κώδικας που χρησιμοποιούμε. Μία συνάρτηση παίρνει κάποια είσοδο και παράγει ένα αποτέλεσμα. 'Hello world' (σειρά) max() εντολή 'w' (σειρά) Ο Guido έγραψε αυτόν τον κώδικα
Η Συνάρτηση Max >>> big = max('hello world') >>> print(big) w 'Hello world' (συμβολοσειρά σειρά) def max(inp): blah blah for x in y: blah blah Μία συνάρτηση είναι αποθηκευμένος κώδικας που χρησιμοποιούμε. Μία συνάρτηση παίρνει κάποια είσοδο και παράγει ένα αποτέλεσμα. 'w' (σειρά) Ο Guido έγραψε αυτόν τον κώδικα
Μετατροπές Τύπων Όταν βάζεις έναν ακέραιο και έναν αριθμό με κινητή υποδιαστολή σε μία έκφραση, ο ακέραιος εμμέσως μετατρέπεται σε αριθμό με κινητή υποδιαστολή. Αυτό μπορείς να το ελέγξεις με τις ενσωματομένες εντολές int() και float() >>> print float(99) / 100 0.99 >>> i = 42 >>> type(i) <class'int'> >>> f = float(i) >>> print(f) 42.0 >>> type(f) <class 'float'> >>> print(1 + 2 * float(3) / 4 5) -2.5 >>>
Μετατροπές Σειρών Μπορείς επίσης να χρησιμοποιήσεις την int() και την float() για μετατροπές μεταξύ σειρών και ακεραίων. Θα λάβεις ένα σφάλμα εαν η σειρά δεν περιλαμβάνει αριθμητικούς χαρακτήρες. >>> sval = '123' >>> type(sval) <class 'str'> >>> print sval + 1 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot concatenate 'str' and 'int' >>> ival = int(sval) >>> type(ival) <class 'int'> >>> print ival + 1 124 >>> nsv = 'hello bob' >>> niv = int(nsv) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int()
Δημιουργώντας τις Δικές μας Συναρτήσεις Δημιουργούμε μία καινούργια συνάρτηση χρησιμοποιώντας τη λέξη κλειδί def ακολουθούμενη από προαιρετικές παραμέτρους μέσα σε παρένθεση. Δημιουργούμε εσοχή στο σώμα της εντολής. Αυτό καθορίζει την εντολή αλλά δεν εκτελεί το σώμα της εντολής. def print_lyrics(): print("i'm a lumberjack, and I'm okay.") print('i sleep all night and I work all day.')
print_lyrics(): print "I'm a lumberjack, and I'm okay." print 'I sleep all night and I work all day.' x = 5 print('hello') def print_lyrics(): print("i'm a lumberjack, and I'm okay.") print('i sleep all night and I work all day.') print('yo') x = x + 2 print(x) Hello Yo 7
Ορισμός και Κλήση Όταν ορίσουμε μία συνάρτηση, μπορούμε να την καλέσουμε (ή να την επικαλεστούμε) όσες φορές θέλουμε. Αυτό είναι το μοτίβο της αποθήκευσης και επαναχρησιμοποίησης.
x = 5 print 'Hello' def print_lyrics(): print "I'm a lumberjack, and I'm okay." print 'I sleep all night and I work all day.' print 'Yo' print_lyrics() x = x + 2 print x Hello Yo I'm a lumberjack, and I'm okay. I sleep all night and I work all day. 7
Παράμετροι-Επιχειρήματα Ένα επιχείρημα είναι μία τιμή που βάζουμε σε μία εντολή σαν είσοδο όταν καλούμε την εντολή. Χρησιμοποιούμε επιχειρήματα έτσι ώστε να μπορούμε να κατευθύνουμε την εντολή να κάνει διαφορετικού είδους δουλειά όταν την καλούμε σε διαφορετικές στιγμές. Βάζουμε τα επιχειρήματα σε παρένθεση μετά το όνομα της εντολής. big = max('hello world') Επιχείρημα
Παράμετροι Μία παράμετρος είναι μία μεταβλητή την οποία μπορούμε να χρησιμοποιήσουμε μέσα στον ορισμό της εντολής. Πρόκειται για μια χειρολαβή που επιτρέπει στο κώδικα μέσα στην εντολή να προσεγγίσει τα επιχειρήματα για μία συγκεκριμένη εντολή επίκλησης. >>> def greet(lang):... if lang == 'es':... print 'Hola'... elif lang == 'fr':... print 'Bonjour'... else:... print 'Hello'... >>> greet('en')hello >>> greet('es')hola >>> greet('fr')bonjour >>>
Επιστρεφόμενες Τιμές Συχνά μία εντολή πέρνει τα επιχειρήματα, κάνει κάποιο υπολογισμό, και επιστρέφει μία τιμή για να χρησιμοποιηθεί σαν τιμή μίας εντολής επικαλούμενη την έκφραση επίκλησης. Η λέξη κλειδί return χρησιμοποιείται γι αυτό το σκοπό. def greet(): return "Hello" print(greet(), "Glenn") print(greet(), "Sally") Hello Glenn Hello Sally
Επιστρεφόμενη Τιμή Μία γόνιμη συνάρτηση είναι μία η οποία παράγει ένα αποτέλεσμα (ή επιστρέφει μία τιμή). Η δήλωση επιστροφής σταματάει την εκτέλεση της εντολής και επιστρέφει το αποτέλεσμα της εντολής. >>> def greet(lang):... if lang == 'es':... return 'Hola'... elif lang == 'fr':... return 'Bonjour'... else:... return 'Hello'... >>> print(greet('en'),'glenn ) Hello Glenn >>> print(greet('es'),'sally ) Hola Sally >>> print(greet('fr'),'michael ) Bonjour Michael >>>
Επιχειρήματα, Παράμετροι, και Αποτελέσματα >>> big = max('hello world') >>> print big w Παράμετροι Επιχείρημα 'Hello world' def max(inp): blah blah for x in y: blah blah return 'w' 'w' Αποτέλεσμα
Πολλαπλές-α Παράμετροι / Επιχειρήματα Μπορούμε να προσδιορίσουμε περισσότερες από μία παράμετρους στην εντολή def. Απλά βάζουμε περισσότερα επιχειρήματα όταν καλούμε τη συνάρτηση. Ταιριάζουμε τον αριθμό και την τάξη των επιχειρημάτων και των παραμέτρων. def addtwo(a, b): added = a + b return added x = addtwo(3, 5) print(x)
Παράμετροι Συγκεκριμένος αριθμός παραμέτρων. def printme(s): print("s") Παράμετροι λέξεις-κλειδιά. Αυτό μας επιτρέπει να παρακάμπτουμε παραμέτρους ή να αλλάζουμε τη σειρά τους, γιατί ο διερμηνέας θα αντιστοιχίσει τη λέξη κλειδί της παραμέτρου με την τιμή της. def printme(int,a): print(int, a) print("-------") printme(a="goals",int=2) print("-------")
Παράμετροι Παράμετροι με δεδομένες τιμές def printinfo(name,age=35): print("name:", name) print("age:", age) printinfo("guido") Δυναμικός αριθμός παραμέτρων def printinfo(*vartable,name="thanasis"): print("name:", name) for var in vartable: print(var) printinfo(10,20,30,name="guido")
Κλήση με Αναφορά Όλες οι παράμετροι στην Python περνώνται με αναφορά (by reference). Αυτό σημαίνει ότι αν αλλάξει κανείς την τιμή της μεταβλητής μέσα σε μια συνάρτηση, τότε η αλλαγή αυτή θα είναι ορατή και στην καλούσα συνάρτηση. def changeme(str): """This changes a passed list into this function""" str = str + " is changed"; print("values inside the function: ", str) return myworld= World changeme(myworld) print("values outside the function: ", mylist)
Κενές (μη-γόνιμες) Συναρτήσεις Όταν μία εντολή δεν επιστρέφει καμία τιμή, την αποκαλούμε κενή (void) συνάρτηση επέχουν θέση «διαδικασιών». Συναρτήσεις οι οποίες επιστρέφουν τιμές είναι γόνιμες συναρτήσεις. Οι κενές συναρτήσεις είναι μη γόνιμες.
Επιστρεφόμενες τιμές διαφορετικού τύπου def multi_return(*vartable): if len(vartable) == 1: return 1 elif len(vartable) == 2: return "dyo" else: return {"name":35} print(multi_return(1))
Να γράφουμε συνάρτηση ή όχι; Ναι για Organize your code into paragraphs - capture a complete thought Επαναλαμβανόμενους υπολογισμούς and name it Λογικά ανεξάρτητες διαδικασίες Don t Αφαίρεση repeat yourself λεπτομερειών - make it υλοποίησης work once and then reuse it Όχι για If something gets too long or complex, break it up into logical chunks Διαχωρισμό and put those ακολουθιών chunks in συναφών functions εντολών Ακολουθίες εντολών που εκτελούνται μια Make a library of common stuff that you do over and over - perhaps φορά share this with your friends...
Άσκηση Γράψτε μια συνάρτηση υπολογισμού του μισθού που να λέγεται computepay με 2 παραμέτρους ( hours και rate), εάν η υπερωρία πληρώνεται με 150 % του βασικού ωρομισθίου. Η συνάρτηση για τις παραμέτρους 45, 10 θα τυπώνει τα παρακάτω: Enter Hours: 45 Enter Rate: 10 Pay: 475.0 475 = 40 * 10 + 5 * 15
Σχεδιασμός Συναρτήσεων Πρέπει να διαλέξουμε παραμέτρους. Τι πρέπει να γνωρίζει η συνάρτηση; Όλα όσα πρέπει να ξέρει η συνάρτηση θα πρέπει να περάσουν σαν παράμετροι. Μη βασίζεστε στις καθολικές μεταβλητές! Θα πρέπει να επιλέξουμε αν θα επιστρέψουμε ή όχι τιμή. Οι συναρτήσεις που τυπώνουν κάτι ή εμφανίζουν κάτι στο χρήστη συνήθως δεν επιστρέφουν τιμή.
Εμβέλεια Η Python έχει τοπικές και καθολικές μεταβλητές. Οι τοπικές μεταβλητές ορίζοναι μέσα σε συναρτήσεις, ενώ οι καθολικές ορίζόνται έξω από τις συναρτήσεις. Τι γίνεται όταν μια τοπική μεταβλητή έχει το ίδιο όνομα με μια καθολική? total = 0; # This is global variable. # Function definition is here def sum( arg1, arg2 ): # Add both the parameters and return them. total = arg1 + arg2; # Here total is local variable. print("inside the function local total : ", total) return total; # Now you can call sum function sum( 10, 20 ); print("outside the function global total : ", total)
Γενικά, η Python... Αρχικά, ελέγχει τις τοπικές μεταβλητές που έχουν οριστεί μέσα σε μια συνάρτηση. Έπειτα, ελέγχει τις τοπικές μεταβλητές σε μια περικλείουσα συνάρτηση. Οπότε, όταν καλέσουμε f(g(4)), τότε πρώτα θα ελέγξει τις τοπικές μεταβλητές της συνάρτησης g, και έπειτα τις τοπικές μεταβλητές της συνάρτησης f. Έπειτα, θα ελέγξει τις καθολικές μεταβλητές. Τέλος, θα ελέγξει τις ενσωματωμένες μεταβλητές.
Χώροι Ονομάτων (Namespaces) Ένας χώρος ονομάτων είναι ένα λεξικό (dictionary) ονομάτων μεταβλητών (κλειδιά) και των αντικειμένων (τιμές) που αντιστοιχούν. Κάθε συνάρτηση έχει δικό της χώρο ονομάτων. Αν μια τοπική μεταβλητή και μια καθολική έχουν το ίδιο όνομα, η τοπική μεταβλητή επισκιάζει την καθολική. Η εντολή global VarName λέει στην Python ότι η VarName είναι καθολική μεταβλητή. Η Python σταματά να ψάχνει για τη μεταβλητή στον τοπικό χώρο ονομάτων. Οι εντολές globals() και locals() επιστρέφουν τα λεξικά των αντίστοιχων χώρων ονομάτων. Money = 2000 def AddMoney(): # Uncomment the following line to fix the code: # global Money Money = Money + 1 print(money) AddMoney() print(money)
Τεκμηρίωση (documentation) Συνάρτησης Όπως είδαμε, μπορούμε να χρησιμοποιήσουμε την ενσωματωμένη συνάρτηση help() για να πάρουμε πληροφορία για συναρτήσεις ή πρωτότυπα (modules). Αυτό μπορούμε να το κάνουμε και στις συναρτήσεις που ορίζουμε εμείς, αλλά δε μας βοηθάει ιδιαίτερα Εκτός κι αν προσθέσουμε σε αυτές χρήσιμη πληροφορία με τα docstrings (συμβολοσειρά τεκμηρίωσης). Ένα docstring περικλείεται από και πρέπει να αποτελεί την πρώτη γραμμή ένος module ή συνάρτησης (PEP 257). Μετά συνήθως αφήνουμε μια κενή γραμμή.
Γιατί τεκμηρίωση; Αν γράφει κανείς πρώτα το docstring, κάνει και μια γρήγορη επιβεβαιώση του σκοπού της συνάρτησης που γράφει. Η τεκμηρίωση κάνει τη φορητότητα του κώδικα και τη βελτίωσή του πιο εύκολές. Επιτρέπει στους άλλους να μάθουν τι κάνουν οι συναρτήσεις σου και πώς να τις χρησιμοποιήσουν χωρίς να κοιτάξουν τον κώδικα. Επιτρέπει τον κατακερματισμό του προβλήματος.
Γράφοντας Καλή Τεκμηρίωση Περιγράφουμε τι κάνει η συνάρτηση. Όχι, το πώς το κάνει. Εξηγούμε το σκοπό κάθε παραμέτρου και αναφερόμαστε σε αυτές με το όνομά τους. Ξεκαθαρίζουμε αν η συνάρτηση επιστρέφει τιμή και τι τύπου. Αναφέρουμε ρητά πιθανές υποθέσεις που κάνει η συνάρτηση. Είμαστε σύντομοι και γραμματικά σωστοί.
Docstrings def is_odd(x): """Return True iff int x is odd""" return (x%2)==1 def fib(n): """Returns the result of Fibonacci function for argument n""" if n==1 or n==2: return 1 elif n>2: return fib(n-1)+fib(n-2) print("wrong input") return None
Ανώνυμες Συναρτήσεις lambda [παραμ1[,παραμ2,...παραμν]]:έκφραση Οι συναρτήσεις lambda μπορούν να πάρουν οσεσδήποτε παραμέτρους αλλά επιστρέφουν μόνο μια τιμή. Δεν μπορούν να περιέχουν εντολές ή πολλαπλές εκφράσεις. Δεν πρέπει να καλέσουν απευθείας την print() Έχουν τοπικό χώρο ονομάτων (namespace) Δεν είναι ισοδύναμες με τις inline συναρτήσεις της C ή C++ sum = lambda arg1, arg2: arg1 + arg2; print( Value of total :, sum(10,20))
Γιατί lambda; Επιστροφή συνάρτησης από άλλη συνάρτηση. functional programming : μπορεί κανείς να περάσει σαν παραμέτρους συναρτήσεις σε άλλες συναρτήσεις. def transform(n): return lambda x: x + n f = transform(3) f(4) l=[1,2,3,4,5] l.sort(key=lambda x:abs(x-3)) print(l)
Πακέτα (Packages) Ένα πακέτο (package) είναι μια ιεραρχική δομή καταλόγων αρχείων που ορίζει το περιβάλλον μιας εφαρμογής Python και αποτελείται από modules και υποπακέτα (subpackages) και υπο-υποπακέτα (sub-subpackages) και ούτω καθεξής. init.py: Το μόνο αρχείο που διαβάζεται όταν κάνουμε import ένα πακέτο. $ cd Phones $ cat init.py import iphone import Samsung $ def print_name(): print( iphone phone ) def print_name(): print( Samsung phone ) >>>import Phones >>>iphone.print_name() iphone phone >>>Samsung.print_name() Samsung phone >>>
Περίληψη Μιλήσαμε για συναρτήσεις Arguments Για την παραμετροποίησή τους Για την τεκμηρίωσή τους Για ανώνυμες συναρτήσεις Για πακέτα Python Results (fruitful functions) Void (non-fruitful) functions Why use functions?