Python

ΕΝΟΤΗΤΑ 21 - Classes (Part 2)

image description

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

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

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

Ο παραπάνω ορισμός κάνει πολύ εύκολη την δουλεία μας όσο αφορά το γεγονός το πως γράφονται τα methods αφού στην ουσία είναι functions γραμμένα μέσα σε κλάσεις. Όμως τα methods που ανήκουν σε μια κλάση δεν θα μπορέσουμε να τα καλέσουμε μόνο με το όνομα τους αλλά πρέπει πρώτα να δημιουργήσουμε ένα αντικείμενο και μετά να τα καλέσουμε, ακριβώς όπως κάναμε και με τις μεταβλητές. Για να μπορέσει όμως ένα αντικείμενο να έχει πρόσβαση στην method θα πρέπει να χρησιμοποιήσουμε την self παράμετρο στον ορισμό της method. Χωρίς το self, η method θα είναι προσβάσιμη μόνο από την κλάση και όχι από το αντικείμενο.

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

App.py

<span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">():</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> id</span><span class="pun">=</span><span class="lit">0</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> id


    </span><span class="kwd">def</span><span class="pln"> paySalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'A check will be sent to {self.name}'</span><span class="pun">)</span><span class="pln">

mike </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">(</span><span class="str">"Michail"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">paySalary</span><span class="pun">()</span><span class="pln">
      </span>   

Output

<span class="pln">
A check will be sent to </span><span class="typ">Michail</span><span class="pln">
 </span>	 

Στο παράδειγμα μας, βλέπουμε ότι με την χρήση του self, μπορούμε να έχουμε πρόσβαση στις μεταβλητές του αντικειμένου. Μην ξεχνάτε ότι το self αναφέρεται στο αντικείμενο της κλάσης. Με πιο απλά λόγια, αν δεν βάλουμε το self σαν παράμετρο στην method τότε θα είναι προσβάσιμη από την κλάση και όχι από το αντικείμενο. Οπότε για να την εκτελέσουμε θα χρησιμοποιήσουμε το όνομα της κλάσης και την μέθοδο, αντί για το αντικείμενο και την μέθοδο. Για να καταλάβουμε την διαφορά, ας δούμε ένα παράδειγμα.

App.py

<span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">():</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> id</span><span class="pun">=</span><span class="lit">0</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> id


    </span><span class="kwd">def</span><span class="pln"> paySalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'A check will be sent to {self.name}'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> companyInformation</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'All employees are working for the company ABC'</span><span class="pun">)</span><span class="pln">

mike </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">(</span><span class="str">"Michail"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Employee</span><span class="pun">.</span><span class="pln">companyInformation</span><span class="pun">()</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">paySalary</span><span class="pun">()</span><span class="pln">
      </span>   

Output

<span class="pln">
</span><span class="typ">All</span><span class="pln"> employees are working </span><span class="kwd">for</span><span class="pln"> the company ABC
A check will be sent to </span><span class="typ">Michail</span><span class="pln">
 </span>	 

Όπως αναφέραμε ήδη, οι methods λειτουργούν με τον ίδιο ακριβώς τρόπο όπως και τα functions όταν περνάμε παραμέτρους σε αυτές. Όταν δηλώνουμε παραμέτρους στα methods, δεν χρειάζεται να κάνουμε αναφορά και στην self παράμετρο. Ο λόγος είναι γιατί αυτές οι μεταβλητές δεν είναι παράμετροι της κλάσης αλλά τοπικές, προσωρινές, μεταβλητές που ορίζονται μόνο μέσα στην method.

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

App.py

<span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">():</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> id</span><span class="pun">=</span><span class="lit">0</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> id


    </span><span class="kwd">def</span><span class="pln"> paySalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'A check will be sent to {self.name}'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> companyInformation</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'All employees are working for the company ABC'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> vacationCalc</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> daysTotal</span><span class="pun">,</span><span class="pln"> daysRequested</span><span class="pun">):</span><span class="pln">
        remainingDays </span><span class="pun">=</span><span class="pln"> daysTotal </span><span class="pun">-</span><span class="pln"> daysRequested
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"You have requested"</span><span class="pun">,</span><span class="pln"> daysRequested</span><span class="pun">,</span><span class="pln"> </span><span class="str">"days of vacation"</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"You have"</span><span class="pun">,</span><span class="pln"> remainingDays</span><span class="pun">,</span><span class="pln"> </span><span class="str">"of vacation left"</span><span class="pun">)</span><span class="pln">


mike </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">(</span><span class="str">"Michail"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Employee</span><span class="pun">.</span><span class="pln">companyInformation</span><span class="pun">()</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">paySalary</span><span class="pun">()</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">vacationCalc</span><span class="pun">(</span><span class="lit">22</span><span class="pun">,</span><span class="lit">5</span><span class="pun">)</span><span class="pln">

      </span>   

Output

<span class="pln">
</span><span class="typ">All</span><span class="pln"> employees are working </span><span class="kwd">for</span><span class="pln"> the company ABC
A check will be sent to </span><span class="typ">Michail</span><span class="pln">
</span><span class="typ">You</span><span class="pln"> have requested </span><span class="lit">5</span><span class="pln"> days </span><span class="kwd">of</span><span class="pln"> vacation
</span><span class="typ">You</span><span class="pln"> have </span><span class="lit">17</span><span class="pln"> </span><span class="kwd">of</span><span class="pln"> vacation left
 </span>	 

Μέχρι τώρα έχουμε δει ότι για να τροποποιήσουμε την τιμή μιας μεταβλητής που ανήκει σε ένα αντικείμενο, δεν έχουμε παρά να καλέσουμε το αντικείμενο.μεταβλητή και αμέσως μετά να δηλώσουμε την καινούργια τιμή που θέλουμε να αναθέσουμε στην μεταβλητή. Αν και αυτός ο τρόπος είναι ο πιο γρήγορος είναι και ο πιο ευάλωτος σε λάθη αφού δεν υπάρχει κανένας τρόπος να ελέγξουμε την τιμή. Για παράδειγμα, σκεφτείτε ότι έχουμε ορίσει μια μεταβλητή salary η οποία αναφέρεται στον μισθό του εργαζόμενου. Αν περάσουμε 1 ευρώ ή 1000000 ευρώ το πρόγραμμα δεν θα παραπονεθεί ούτε θα διακρίνει κανένα λάθος αφού και οι δύο είναι αριθμοί. Για να μειώσουμε τέτοιου είδους λάθη χρησιμοποιούμε getters και setters μεθόδους.

Οι getter και setter methods είναι κανονικές methods όπως τις γνωρίζεται που δια μέσω αυτών αναθέτουμε τιμές στις μεταβλητές. Δηλαδή αντί να καλέσουμε την μεταβλητή, καλούμε την μέθοδο για να αναθέσουμε τιμή στην μεταβλητή. Τι κερδίζουμε με αυτό τον τρόπο? Μα φυσικά την ικανότητα να γράψουμε ελέγχους πριν αναθέσουμε την τιμή στην μεταβλητή.

Στο παρακάτω παράδειγμα, έχουμε προσθέσει μια ακόμα μεταβλητή στην κλάση Employee που ονομάζεται salary. Αντί να καλέσουμε την salary, θα καλέσουμε την μέθοδο setSalary για να αναθέσουμε τιμή στην μεταβλητή salary και την getSalary για να λάβουμε πίσω την τιμή που έχει η μεταβλητή salary εκείνη την στιγμή.

App.py

<span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">():</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> id</span><span class="pun">=</span><span class="lit">0</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> id
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">salary </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">


    </span><span class="kwd">def</span><span class="pln"> paySalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'A check will be sent to {self.name}'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> companyInformation</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'All employees are working for the company ABC'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> vacationCalc</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> daysTotal</span><span class="pun">,</span><span class="pln"> daysRequested</span><span class="pun">):</span><span class="pln">
        remainingDays </span><span class="pun">=</span><span class="pln"> daysTotal </span><span class="pun">-</span><span class="pln"> daysRequested
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"You have requested"</span><span class="pun">,</span><span class="pln"> daysRequested</span><span class="pun">,</span><span class="pln"> </span><span class="str">"days of vacation"</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"You have"</span><span class="pun">,</span><span class="pln"> remainingDays</span><span class="pun">,</span><span class="pln"> </span><span class="str">"of vacation left"</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> setSalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> salary</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> salary</span><span class="pun">&gt;</span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> salary</span><span class="pun">&lt;</span><span class="lit">2000</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">salary </span><span class="pun">=</span><span class="pln"> salary
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"This salary amount is not acceptable"</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> getSalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'Your current salary is {self.salary}'</span><span class="pun">)</span><span class="pln">

mike </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">(</span><span class="str">"Michail"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">setSalary</span><span class="pun">(</span><span class="lit">1900</span><span class="pun">)</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">getSalary</span><span class="pun">()</span><span class="pln">

      </span>   

Output

<span class="pln">
</span><span class="typ">Your</span><span class="pln"> current salary </span><span class="kwd">is</span><span class="pln"> </span><span class="lit">1900</span><span class="pln">
 </span>	 

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

Προσθέτουμε λοιπόν μια ακόμα μεταβλητή με το όνομα age η οποία περιγράφει την ηλικία του εργαζόμενου. Με την μέθοδο employeeBirthday αυξάνουμε την ηλικία κατά ένα. Με την μέθοδο getAge εμφανίζουμε την ηλικία στο Terminal.

App.py

<span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">():</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> id</span><span class="pun">=</span><span class="lit">0</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> id
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">salary </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">


    </span><span class="kwd">def</span><span class="pln"> paySalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'A check will be sent to {self.name}'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> companyInformation</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'All employees are working for the company ABC'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> vacationCalc</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> daysTotal</span><span class="pun">,</span><span class="pln"> daysRequested</span><span class="pun">):</span><span class="pln">
        remainingDays </span><span class="pun">=</span><span class="pln"> daysTotal </span><span class="pun">-</span><span class="pln"> daysRequested
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"You have requested"</span><span class="pun">,</span><span class="pln"> daysRequested</span><span class="pun">,</span><span class="pln"> </span><span class="str">"days of vacation"</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"You have"</span><span class="pun">,</span><span class="pln"> remainingDays</span><span class="pun">,</span><span class="pln"> </span><span class="str">"of vacation left"</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> setSalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> salary</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> salary</span><span class="pun">&gt;</span><span class="lit">0</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> salary</span><span class="pun">&lt;</span><span class="lit">2000</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">salary </span><span class="pun">=</span><span class="pln"> salary
        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"This salary amount is not acceptable"</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> getSalary</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'Your current salary is {self.salary}'</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> employeeBirthday</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">+=</span><span class="lit">1</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> getAge</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">f</span><span class="str">'your age is {self.age}'</span><span class="pun">)</span><span class="pln">

mike </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">(</span><span class="str">"Michail"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">employeeBirthday</span><span class="pun">()</span><span class="pln">
mike</span><span class="pun">.</span><span class="pln">getAge</span><span class="pun">()</span><span class="pln">

      </span>   

Output

<span class="pln">
your age </span><span class="kwd">is</span><span class="pln"> </span><span class="lit">31</span><span class="pln">
 </span>	 

ΕΙΣΗΓΗΤΗΣ

Merry Jhonson

Μιχάλης Κασάπογλου

Ο Μιχάλης Κασάπογλου, είναι ένας από τους πιο έμπειρους τεχνικούς εκπαιδευτές στον χώρο του προγραμματισμού με πάνω από 20 χρόνια εμπειρία. Έχει εργαστεί σαν IT Operations Manager, Senior Programmer, και Training Team Leader ενώ κατέχει και αρκετές πιστοποιήσεις που καλύπτουν ένα μεγάλο φάσμα τεχνολογιών στο προγραμματισμό, σε βάσεις δεδομένων και cloud. Στον ελεύθερο του χρόνο διατηρεί ένα τεχνολογικό blog στο οποίο θα βρείτε αρκετά δωρεάν μαθήματα προγραμματισμού για αρχάριους.

loader