Υπερφόρτωση χειριστή Python

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

Υπερφόρτωση χειριστή Python

Οι χειριστές της Python εργάζονται για ενσωματωμένες τάξεις. Αλλά ο ίδιος χειριστής συμπεριφέρεται διαφορετικά με διαφορετικούς τύπους. Για παράδειγμα, ο +χειριστής θα πραγματοποιήσει αριθμητική προσθήκη σε δύο αριθμούς, θα συγχωνεύσει δύο λίστες ή θα συνδυάσει δύο χορδές.

Αυτό το χαρακτηριστικό στο Python που επιτρέπει στον ίδιο χειριστή να έχει διαφορετικό νόημα ανάλογα με το περιβάλλον ονομάζεται υπερφόρτωση χειριστή.

Τι συμβαίνει λοιπόν όταν τα χρησιμοποιούμε με αντικείμενα μιας κατηγορίας που ορίζεται από το χρήστη; Ας εξετάσουμε την ακόλουθη τάξη, η οποία προσπαθεί να προσομοιώσει ένα σημείο στο 2-D σύστημα συντεταγμένων.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)

Παραγωγή

 Traceback (τελευταία κλήση τελευταία): Αρχείο ", γραμμή 9, σε έντυπη μορφή (p1 + p2) TypeError: τύποι (ες) που δεν υποστηρίζονται για +: 'Point' και 'Point'

Εδώ, μπορούμε να δούμε ότι TypeErrorέχει ανασηκωθεί, αφού η Python δεν ήξερε πώς να προσθέσει δύο Pointαντικείμενα μαζί.

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

Ειδικές λειτουργίες Python

Οι συναρτήσεις τάξης που ξεκινούν με διπλή υπογράμμιση __ονομάζονται ειδικές λειτουργίες στο Python.

Αυτές οι συναρτήσεις δεν είναι οι τυπικές λειτουργίες που ορίζουμε για μια τάξη. Η __init__()συνάρτηση που ορίσαμε παραπάνω είναι μία από αυτές. Καλείται κάθε φορά που δημιουργούμε ένα νέο αντικείμενο αυτής της τάξης.

Υπάρχουν πολλές άλλες ειδικές λειτουργίες στην Python. Επισκεφτείτε το Python Special Functions για να μάθετε περισσότερα σχετικά με αυτά.

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

 >>> p1 = Point(2,3) >>> print(p1) 

Ας υποθέσουμε ότι θέλουμε η print()συνάρτηση να εκτυπώνει τις συντεταγμένες του Pointαντικειμένου αντί αυτού που έχουμε. Μπορούμε να ορίσουμε μια __str__()μέθοδο στην τάξη μας που ελέγχει τον τρόπο εκτύπωσης του αντικειμένου. Ας δούμε πώς μπορούμε να το επιτύχουμε:

 class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x,self.y)

Τώρα ας δοκιμάσουμε print()ξανά τη λειτουργία.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0), (1))".format(self.x, self.y) p1 = Point(2, 3) print(p1)

Παραγωγή

 (2, 3)

Αυτό είναι καλύτερο. Αποδεικνύεται ότι αυτή η ίδια μέθοδος επικαλείται όταν χρησιμοποιούμε την ενσωματωμένη συνάρτηση str()ή format().

 >>> str(p1) '(2,3)' >>> format(p1) '(2,3)'

Έτσι, όταν χρησιμοποιείτε str(p1)ή format(p1), η Python καλεί εσωτερικά τη p1.__str__()μέθοδο. Εξ ου και το όνομα, οι ειδικές λειτουργίες.

Τώρα ας επιστρέψουμε στην υπερφόρτωση του χειριστή.

Υπερφόρτωση του χειριστή +

Για να υπερφορτώσουμε τον +χειριστή, θα πρέπει να εφαρμόσουμε τη __add__()λειτουργία στην τάξη. Με μεγάλη δύναμη έρχεται μεγάλη ευθύνη. Μπορούμε να κάνουμε ό, τι θέλουμε, μέσα σε αυτή τη λειτουργία. Αλλά είναι πιο λογικό να επιστρέφετε ένα Pointαντικείμενο του αθροίσματος συντεταγμένων.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y)

Τώρα ας δοκιμάσουμε ξανά τη λειτουργία προσθήκης:

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y) p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)

Παραγωγή

 (3,5)

Αυτό που πραγματικά συμβαίνει είναι ότι, όταν χρησιμοποιείτε p1 + p2, η Python καλεί p1.__add__(p2)με τη σειρά της Point.__add__(p1,p2). Μετά από αυτό, η λειτουργία προσθήκης πραγματοποιείται με τον τρόπο που καθορίσαμε.

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

Χειριστής Εκφραση Εσωτερικώς
Πρόσθεση p1 + p2 p1.__add__(p2)
Αφαίρεση p1 - p2 p1.__sub__(p2)
Πολλαπλασιασμός p1 * p2 p1.__mul__(p2)
Εξουσία p1 ** p2 p1.__pow__(p2)
Διαίρεση p1 / p2 p1.__truediv__(p2)
Διαίρεση δαπέδου p1 // p2 p1.__floordiv__(p2)
Υπόλοιπο (modulo) p1 % p2 p1.__mod__(p2)
Bitwise Left Shift p1 << p2 p1.__lshift__(p2)
Bitwise Right Shift p1>> p2 p1.__rshift__(p2)
Bitwise ΚΑΙ p1 & p2 p1.__and__(p2)
Bitwise Ή p1 | p2 p1.__or__(p2)
Bitwise XOR p1 p2 p1.__xor__(p2)
ΔΥΟ ΔΥΟ ~p1 p1.__invert__()

Χειριστές σύγκρισης υπερφόρτωσης

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

Ας υποθέσουμε ότι θέλαμε να εφαρμόσουμε το σύμβολο λιγότερο από το <σύμβολο στην Pointτάξη μας .

Let us compare the magnitude of these points from the origin and return the result for this purpose. It can be implemented as follows.

 # overloading the less than operator class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __lt__(self, other): self_mag = (self.x ** 2) + (self.y ** 2) other_mag = (other.x ** 2) + (other.y ** 2) return self_mag < other_mag p1 = Point(1,1) p2 = Point(-2,-3) p3 = Point(1,-1) # use less than print(p1 

Output

 True False False

Similarly, the special functions that we need to implement, to overload other comparison operators are tabulated below.

Operator Expression Internally
Less than p1 < p2 p1.__lt__(p2)
Less than or equal to p1 <= p2 p1.__le__(p2)
Equal to p1 == p2 p1.__eq__(p2)
Not equal to p1 != p2 p1.__ne__(p2)
Greater than p1> p2 p1.__gt__(p2)
Greater than or equal to p1>= p2 p1.__ge__(p2)

ενδιαφέροντα άρθρα...