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

Ως νέοι προγραμματιστές, όλοι κάνουμε λάθη. Αλλά ορισμένα λάθη πιθανότατα οφείλονται στην έλλειψη εξοικείωσης με τη γλώσσα προγραμματισμού. Έτσι, έχω συγκεντρώσει μερικά από τα πιο συνηθισμένα λάθη που μπορεί να κάνετε κατά τον προγραμματισμό με Python.
6. Επεξεργαστείτε μια λίστα κατά την επανάληψη
Η τροποποίηση μιας λίστας Python κατά την επανάληψη μπορεί να φαίνεται σαν μια έξυπνη συντόμευση, αλλά είναι ένα συνηθισμένο κόλπο της Python! Αυτό το ύπουλο σφάλμα μπορεί να οδηγήσει σε απροσδόκητη συμπεριφορά, όπως παράλειψη στοιχείων ή μια εντελώς λανθασμένη λίστα.
Ας υποθέσουμε ότι έχουμε μια λίστα αριθμών και θέλουμε να διαγράψουμε όλους τους αριθμούς που είναι μικρότεροι από 5. Φαίνεται προφανές, σωστά;
numbers = [1, 2, 6, 3, 7, 4, 8, 5]
print("Original list:", numbers)
for number in numbers:
if number < 5:
numbers.remove(number)
print("Modified list (oops!):", numbers)
Αν εκτελέσετε αυτόν τον κώδικα, θα διαπιστώσετε ότι ο αριθμός 2 παραμένει στη λίστα.

Αλλά γιατί; Σε αυτόν τον κώδικα, προσπαθούμε να επαναλάβουμε τους αριθμούς και να αφαιρέσουμε στοιχεία μικρότερα από 5. Ωστόσο, όταν αφαιρούμε ένα στοιχείο, η λίστα συρρικνώνεται και οι δείκτες των επόμενων στοιχείων αλλάζουν.
Αυτό μπορεί να προκαλέσει την παράλειψη στοιχείων από τον βρόχο. Για παράδειγμα, όταν αφαιρείται το 1, το 2 μετακινείται στην παλιά του θέση, αλλά ο εσωτερικός μετρητής του βρόχου έχει ήδη μετακινηθεί, γεγονός που μπορεί να προκαλέσει την παράλειψη του 1.
Ο ασφαλέστερος και πιο συνηθισμένος τρόπος για να τροποποιήσετε μια λίστα με βάση τα στοιχεία της είναι να αντιγράψετε ένα αντίγραφό της ή να δημιουργήσετε μια νέα λίστα μόνο με τα στοιχεία που θέλετε να διατηρήσετε. Στη μέθοδο αντιγραφής, δημιουργούμε ένα ρηχό αντίγραφο της λίστας πριν από την αντιγραφή. Με αυτόν τον τρόπο, μπορείτε να αφαιρέσετε στοιχεία από την αρχική λίστα χωρίς να επηρεάσετε τη διαδικασία αντιγραφής.
numbers = [1, 2, 6, 3, 7, 4, 8, 5]
print("Original list:", numbers)
for number in numbers[:]: # Iterate over a slice (copy) of the list
if number < 5:
numbers.remove(number)
print("Modified list (fixed with copy):", numbers)
Χρησιμοποιώντας τη συνάρτηση numbers[:], δημιουργούμε ένα κομμάτι της λίστας αριθμών, ένα ρηχό αντίγραφο. Στη συνέχεια, ο βρόχος for επαναλαμβάνεται πάνω από αυτό το αντίγραφο, εντελώς ανεξάρτητα από τυχόν τροποποιήσεις που κάνουμε στην αρχική λίστα αριθμών.
Η πιο συχνά χρησιμοποιούμενη μέθοδος στην Python για την επίτευξη αυτού του στόχου είναι η δημιουργία μιας νέας λίστας που περιέχει μόνο τα στοιχεία που θέλετε να διατηρήσετε. Αυτή η προσέγγιση αποφεύγει εντελώς την τροποποίηση επί τόπου και είναι συχνά πιο αποτελεσματική.
numbers = [1, 2, 6, 3, 7, 4, 8, 5]
print("Original list:", numbers)
filtered_numbers = [number for number in numbers if number >= 5]
print("Filtered list (new list method):", filtered_numbers)
Σε αυτόν τον κώδικα, χρησιμοποιούμε μια κατανόηση λίστας για να δημιουργήσουμε μια νέα λίστα από την αρχική λίστα που περιέχει τα επιθυμητά στοιχεία. Αυτό διατηρεί επίσης την αρχική λίστα άθικτη.
5. Ονομασία συγκρούσεων
Η επιλογή ονομάτων μεταβλητών και αρχείων μπορεί να φαίνεται σαν μια ασήμαντη λεπτομέρεια, μέχρι που η Python σας πιάνει εξ απροόπτου (μεταφορικά). Η λανθασμένη ονομασία πραγμάτων μπορεί να οδηγήσει σε παράξενα σφάλματα, παραπλανητικές συναρτήσεις και ώρες σύγχυσης. Υπάρχουν δύο συνηθισμένοι τρόποι με τους οποίους συμβαίνει αυτό: η χρήση λέξεων-κλειδιών Python ή ενσωματωμένων ονομάτων ως δικά σας ή η κατά λάθος ονομασία των σεναρίων σας από υπάρχουσες ενότητες Python.
Η Python δεν θα σας εμποδίσει να ονομάσετε μια λίστα μεταβλητών, μια συμβολοσειρά ή ακόμα και ένα άθροισμα. Αλλά μόνο και μόνο επειδή μπορείτε να το κάνετε δεν σημαίνει ότι πρέπει να το κάνετε.
list = [1, 2, 3]
print(list)
Αυτός ο κώδικας θα λειτουργήσει ομαλά. Ωστόσο, αν προσθέσετε μια άλλη γραμμή που περιέχει τη συνάρτηση Python list(), θα εμφανιστεί ένα σφάλμα.
list = [1, 2, 3]
print(list)
list = list('123')

Αυτό συμβαίνει επειδή αντικαταστήσατε την ενσωματωμένη συνάρτηση list() με το δικό σας αντικείμενο list. Όταν προσπαθείτε να καλέσετε τη συνάρτηση list('123'), η Python νομίζει ότι προσπαθείτε να καλέσετε τη δική σας λίστα και όχι την ενσωματωμένη συνάρτηση. Επομένως, να χρησιμοποιείτε πάντα περιγραφικά ονόματα που δεν έρχονται σε σύγκρουση με τις βασικές δυνατότητες της Python.
numbers = [1, 2, 3]
converted = list('123')
Αυτό όχι μόνο θα σας βοηθήσει να αποφύγετε τη χρήση δεσμευμένων λέξεων-κλειδιών, αλλά είναι επίσης μια καλή πρακτική για την αναγνωσιμότητα του κώδικα και την αποσφαλμάτωση. Το ίδιο ισχύει και για την ονομασία αρχείων σεναρίου. Ας υποθέσουμε ότι δημιουργείτε ένα αρχείο με το όνομα random.py για να δοκιμάσετε τυχαίους αριθμούς:
# random.py
import random
print(random.randint(1, 10))
Αλλά όταν το εκτελέσετε αυτό, πιθανότατα θα δείτε ένα σφάλμα που αναφέρει: "Η ενότητα 'random' δεν έχει το χαρακτηριστικό 'randint'". Η Python εισάγει το δικό σας αρχείο (random.py) αντί για την πραγματική ενότητα τυχαίας επιλογής από την τυπική βιβλιοθήκη. Αυτό είναι ένα συνηθισμένο σφάλμα shader.
Αποφύγετε να ονομάζετε τα σενάρια σας με βάση υπάρχουσες ενότητες όπως random.py, math.py, os.py ή json.py. Εάν το κάνετε κατά λάθος, μην ξεχάσετε να διαγράψετε τους αντίστοιχους φακέλους .pyc ή __pycache__ μετά τη μετονομασία.
4. Μεταβλητά ορίσματα συνάρτησης
Η Python σάς επιτρέπει να αντιστοιχίζετε προεπιλεγμένες τιμές σε ορίσματα συνάρτησης, κάτι που είναι πολύ βολικό. Ωστόσο, όταν αυτές οι προεπιλεγμένες τιμές είναι μεταβλητές (όπως λίστες ή λεξικά), αντιμετωπίζετε ένα κρυφό σφάλμα.
Ένα εικονικό μεταβλητό αντικείμενο δημιουργείται μόνο μία φορά, όταν ορίζεται η συνάρτηση, όχι κάθε φορά που καλείται. Αυτό σημαίνει ότι εάν τροποποιηθεί, η αλλαγή αυτή παραμένει σε ισχύ μέχρι την επόμενη κλήση.
def add_item_to_list(item, item_list=[]):
item_list.append(item)
return item_list
print(add_item("apple"))
print(add_item("banana"))
Όταν εκτελείτε αυτόν τον κώδικα, μπορεί να περιμένετε ότι κάθε κλήση της συνάρτησης add_item_to_list() θα ξεκινά με μια νέα, κενή λίστα, εάν δεν παρείχατε μία. Ωστόσο, η έξοδος εμφανίζει κάτι απροσδόκητο:

Καλέσαμε τη συνάρτηση δύο φορές. Γιατί το "apple" εξακολουθεί να υπάρχει στη δεύτερη κλήση; Η λίστα_στοιχείων δημιουργείται μόνο μία φορά, επομένως κάθε κλήση στη συνάρτηση τροποποιεί συνεχώς την ίδια λίστα. Αυτό οδηγεί σε εκπληκτική και προβληματική συμπεριφορά. Για να το διορθώσετε αυτό, μπορείτε να χρησιμοποιήσετε το "None" ως προεπιλογή και να δημιουργήσετε τη λίστα μέσα στη συνάρτηση:
def add_item_to_list(item, item_list=None):
if item_list is None:
item_list = []
item_list.append(item)
return item_list
print(add_item("apple"))
print(add_item("banana"))
Όταν η προεπιλεγμένη τιμή έχει οριστεί σε "καμία", δημιουργείται μια νέα λίστα κάθε φορά που καλείται η συνάρτηση.
3. Λανθασμένος χειρισμός αρχείων
Η εργασία με αρχεία σε Python είναι πολύ εύκολη. Ωστόσο, ένα συνηθισμένο λάθος που μπορεί να παρεισφρήσει στον κώδικά σας είναι το να μην κλείνετε το αρχείο. Μπορεί να φαίνεται ακίνδυνο, αλλά το να αφήνετε τα αρχεία ανοιχτά μπορεί να οδηγήσει σε διαρροές μνήμης, καταστροφή ή κλείδωμά τους, ώστε να μην είναι δυνατή η πρόσβαση σε αυτά από άλλα προγράμματα.
file = open('data.txt', 'r')
content = file.read()
print(content)
# Forgot to close the file!
Αν αφήσετε τα αρχεία ανοιχτά, μπορεί να προκληθούν σοβαρά προβλήματα και μπορεί ακόμη και να αποτραπεί η διαγραφή ή η τροποποίησή τους από άλλες διεργασίες. Επομένως, να κλείνετε πάντα το αρχείο αφού ολοκληρώσετε τις λειτουργίες σας. Μπορείτε να το κάνετε αυτό χρησιμοποιώντας τη συνάρτηση close().
file = open('data.txt', 'r')
content = file.read()
print(content)
file.close()
Μια άλλη καλή πρακτική είναι να χρησιμοποιήσετε την εντολή with στην Python, η οποία φροντίζει αυτόματα για το κλείσιμο του αρχείου για εσάς.
with open('data.txt', 'r') as file:
content = file.read()
print(content)
Το μπλοκ with χειρίζεται όλο τον καθαρισμό στο παρασκήνιο. Μόλις βγείτε από το μπλοκ, η Python κλείνει το αρχείο για εσάς. Αυτό αποφεύγει το χειροκίνητο κλείσιμο του αρχείου.
2. Εισαγάγετε τα πάντα από την Unity
Ως αρχάριος, μπορεί να είναι δελεαστικό να προσθέσετε ένα αρχείο * εισαγωγής από μια ενότητα στην αρχή του κώδικά σας και να είστε έτοιμοι. Αλλά καθώς ο κώδικάς σας μεγαλώνει, αυτή η συντόμευση γίνεται αιτία αποτυχίας.
from math import *
from custom_math import *
print(sqrt(16))
Τι γίνεται αν και τα math και custom_math ορίζουν μια συνάρτηση που ονομάζεται sqrt(); Ποια από τις δύο καλείται; Η Python δεν σας το λέει. Απλώς παρακάμπτει κρυφά την προηγούμενη συνάρτηση.
Ενδέχεται να χρησιμοποιείτε μια εντελώς διαφορετική συνάρτηση χωρίς να το συνειδητοποιείτε. Επιπλέον, σε μεγάλες βάσεις δεδομένων, η διόρθωση σφαλμάτων γίνεται περίπλοκη. Ενδέχεται να χάσετε την παρακολούθηση των συναρτήσεων ή των κλάσεων. Για αυτόν τον λόγο, θα πρέπει να είστε σαφείς κατά την εισαγωγή τους.
import math
import custom_math
print(math.sqrt(16))
print(custom_math.sqrt(16))
Ή ακόμα και έτσι:
from math import sqrt as m_sqrt
from custom_math import sqrt as c_sqrt
print(m_sqrt(16))
print(c_sqrt(16))
Το ρητό είναι καλύτερο από το έμμεσο (μια βασική ιδέα της φιλοσοφίας της Python). Ξέρεις πάντα τι χρησιμοποιείς και από πού προήλθε.
1. Χειριστείτε σωστά τις εξαιρέσεις
Ακόμα και ο πιο ακριβής κώδικας μπορεί να αντιμετωπίσει απροσδόκητα προβλήματα. Αυτά ονομάζονται εξαιρέσεις στην Python. Η ομαλή διαχείρισή τους είναι αυτό που κάνει το πρόγραμμά σας ανθεκτικό. Ωστόσο, πολλοί αρχάριοι προσεγγίζουν τη διαχείριση εξαιρέσεων με μια «γενική» νοοτροπία, χρησιμοποιώντας ευρείες δηλώσεις εξαιρέσεων. Αυτό μπορεί προσωρινά να αποσιωπήσει τα σφάλματα, αλλά κάνει τον κώδικά σας εύθραυστο, περίπλοκο και δύσκολο στον εντοπισμό σφαλμάτων.
try:
result = 10 / 0
except:
print("Something went wrong!")

Αυτό εντοπίζει τα πάντα. Ακόμα και σφάλματα που δεν περιμένατε ή δεν θέλατε να διαχειριστείτε. Σφάλματα σύνταξης, διακοπές πληκτρολογίου, τυπογραφικά λάθη και προβληματικές εισαγωγές. Η Python θα τα εντοπίσει όλα με αυτήν τη γενική εξαίρεση. Αυτή δεν είναι η ιδανική λύση. Αντίθετα, να είστε συγκεκριμένοι σχετικά με το τι εντοπίζετε:
try:
result = 10 / 0
except ZeroDivisionError:
print("You can't divide by zero!")
Εντοπίζετε μόνο το σφάλμα που περιμένετε. Εάν παρουσιαστεί άλλο σφάλμα, η Python θα το εμφανίσει. Έτσι, δεν αγνοείτε σιωπηλά τα πραγματικά σφάλματα. Μπορείτε επίσης να χειριστείτε έξυπνα πολλαπλές εξαιρέσεις:
try:
value = int(input("Enter a number: "))
result = 10 / value
except ValueError:
print("That's not a valid number!")
except ZeroDivisionError:
print("You can't divide by zero!")
Αποφύγετε τη χρήση μόνο του "except:". Εάν είναι απαραίτητο να εντοπίσετε όλες τις εξαιρέσεις (σπάνια), χρησιμοποιήστε το "except:" και χειριστείτε το προσεκτικά. Χειριζόμενοι τις εξαιρέσεις προσεκτικά, ο κώδικάς σας γίνεται πιο προβλέψιμος, πιο εύκολος στην ανίχνευση σφαλμάτων και πιο ικανός να παρέχει πιο χρήσιμα σχόλια.
Αποφεύγοντας αυτά τα λάθη, θα μειώσετε τα σφάλματα, πράγμα που σημαίνει λιγότερη ανάγκη για εντοπισμό σφαλμάτων στον κώδικα Python. Εάν είστε νέοι στην Python και ψάχνετε για πόρους, υπάρχουν πολλά παιχνίδια που διδάσκουν την Python. Επιπλέον, μπορείτε να υλοποιήσετε έργα όπως ένα εργαλείο παρακολούθησης εξόδων ή να δημιουργήσετε βασικά σενάρια.

