portaldacalheta.pt
  • Κύριος
  • Ζωή Σχεδιαστών
  • Διαδικασίες Χρηματοδότησης
  • Συμβουλές Και Εργαλεία
  • Μηχανική Διοίκηση
Τεχνολογία

Buggy Python Code: Τα 10 πιο συνηθισμένα λάθη που κάνουν οι προγραμματιστές της Python



Σχετικά με την Python

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

Σχετικά με αυτό το άρθρο

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



Έχοντας αυτό κατά νου, αυτό το άρθρο παρουσιάζει μια λίστα με τα «κορυφαία 10» κάπως λεπτών, δυσκολότερων πιάτων λαθών που μπορούν να δαγκώσουν ακόμη περισσότερα προηγμένοι προγραμματιστές της Python στο πίσω μέρος.



επίσημα στοιχεία και αρχές σχεδιασμού

(Σημείωση: Αυτό το άρθρο προορίζεται για πιο προηγμένο κοινό από ό, τι Κοινά λάθη των προγραμματιστών Python , το οποίο προσανατολίζεται περισσότερο σε εκείνους που είναι νεότεροι στη γλώσσα.)



Κοινό λάθος # 1: Κατάχρηση εκφράσεων ως προεπιλογή για ορίσματα συνάρτησης

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

>>> def foo(bar=[]): # bar is optional and defaults to [] if not specified ... bar.append('baz') # but this line could be problematic, as we'll see... ... return bar

Ένα κοινό λάθος είναι να πιστεύουμε ότι το προαιρετικό όρισμα θα οριστεί στην καθορισμένη προεπιλεγμένη έκφραση κάθε φορά η συνάρτηση καλείται χωρίς να παρέχει τιμή για το προαιρετικό όρισμα. Στον παραπάνω κώδικα, για παράδειγμα, μπορεί κανείς να αναμένει ότι η κλήση foo() επανειλημμένα (δηλαδή, χωρίς να προσδιορίζεται ένα bar επιχείρημα) θα επέστρεφε πάντα 'baz', δεδομένου ότι η υπόθεση θα ήταν ότι κάθε φορά foo() καλείται (χωρίς καθορισμένο όρισμα bar) bar έχει οριστεί σε [] (δηλαδή, μια νέα κενή λίστα).



Αλλά ας δούμε τι πραγματικά συμβαίνει όταν το κάνετε αυτό:

>>> foo() ['baz'] >>> foo() ['baz', 'baz'] >>> foo() ['baz', 'baz', 'baz']

Ε; Γιατί συνέχισε να προσαρτά την προεπιλεγμένη τιμή 'baz' σε ένα υπάρχον λίστα κάθε φορά foo() κλήθηκε, αντί να δημιουργήσει ένα νέος λίστα κάθε φορά;



Η πιο προηγμένη απάντηση προγραμματισμού Python είναι αυτή η προεπιλεγμένη τιμή για ένα όρισμα συνάρτησης αξιολογείται μόνο μία φορά, τη στιγμή που ορίζεται η συνάρτηση. Έτσι, το bar Το όρισμα αρχικοποιείται στην προεπιλογή του (δηλαδή, μια κενή λίστα) μόνο όταν foo() ορίζεται πρώτα, αλλά στη συνέχεια καλεί στο foo() (δηλαδή, χωρίς καθορισμένο όρισμα bar) θα συνεχίσει να χρησιμοποιεί την ίδια λίστα με την οποία bar αρχικοποιήθηκε αρχικά.

FYI, μια κοινή λύση για αυτό είναι ως εξής:



>>> def foo(bar=None): ... if bar is None: # or if not bar: ... bar = [] ... bar.append('baz') ... return bar ... >>> foo() ['baz'] >>> foo() ['baz'] >>> foo() ['baz']

Κοινό λάθος # 2: Η λανθασμένη χρήση μεταβλητών κατηγορίας

Εξετάστε το ακόλουθο παράδειγμα:

>>> class A(object): ... x = 1 ... >>> class B(A): ... pass ... >>> class C(A): ... pass ... >>> print A.x, B.x, C.x 1 1 1

Βγάζει νόημα.



>>> B.x = 2 >>> print A.x, B.x, C.x 1 2 1

Ναι, ξανά όπως αναμενόταν.

>>> A.x = 3 >>> print A.x, B.x, C.x 3 2 3

Τι στο $% #! & ?? Αλλάξαμε μόνο A.x. Γιατί C.x αλλάζετε επίσης;



Στο Python, οι μεταβλητές τάξης αντιμετωπίζονται εσωτερικά ως λεξικά και ακολουθούν αυτό που αναφέρεται συχνά ως Παραγγελία ανάλυσης μεθόδου (MRO) . Έτσι στον παραπάνω κώδικα, αφού το χαρακτηριστικό x δεν βρίσκεται στην κλάση C, θα αναζητηθεί στις βασικές του κατηγορίες (μόνο A στο παραπάνω παράδειγμα, αν και η Python υποστηρίζει πολλαπλές κληρονομιές). Με άλλα λόγια, C δεν έχει το δικό του x ιδιοκτησία, ανεξάρτητα από A. Έτσι, οι αναφορές στο C.x στην πραγματικότητα αναφέρονται σε A.x. Αυτό προκαλεί πρόβλημα Python εκτός εάν αντιμετωπιστεί σωστά. Μάθε περισσότερα για χαρακτηριστικά κλάσης στο Python .

Συνηθισμένο λάθος # 3: Καθορισμός λανθασμένων παραμέτρων για ένα μπλοκ εξαίρεσης

Ας υποθέσουμε ότι έχετε τον ακόλουθο κωδικό:

>>> try: ... l = ['a', 'b'] ... int(l[2]) ... except ValueError, IndexError: # To catch both exceptions, right? ... pass ... Traceback (most recent call last): File '', line 3, in IndexError: list index out of range

Το πρόβλημα εδώ είναι ότι το except η δήλωση κάνει δεν λάβετε μια λίστα εξαιρέσεων που καθορίζονται με αυτόν τον τρόπο. Αντίθετα, στο Python 2.x, η σύνταξη except Exception, e χρησιμοποιείται για τη σύνδεση της εξαίρεσης με το προαιρετικός καθορισμένη δεύτερη παράμετρος (σε αυτήν την περίπτωση e), προκειμένου να καταστεί διαθέσιμη για περαιτέρω έλεγχο. Ως αποτέλεσμα, στον παραπάνω κώδικα, το IndexError εξαίρεση είναι δεν πιάστηκε από το except δήλωση; Αντίθετα, η εξαίρεση καταλήγει να δεσμεύεται σε μια παράμετρο που ονομάζεται IndexError.

Ο σωστός τρόπος για να πιάσετε πολλές εξαιρέσεις σε ένα except Η δήλωση είναι να καθορίσει την πρώτη παράμετρο ως α πλειάδα περιέχει όλες τις εξαιρέσεις που πρέπει να αλιευθούν. Επίσης, για μέγιστη φορητότητα, χρησιμοποιήστε το as λέξη-κλειδί, καθώς αυτή η σύνταξη υποστηρίζεται τόσο από το Python 2 όσο και από το Python 3:

>>> try: ... l = ['a', 'b'] ... int(l[2]) ... except (ValueError, IndexError) as e: ... pass ... >>>

Κοινό λάθος # 4: Παρανόηση των κανόνων του Python

Η ανάλυση πεδίου Python βασίζεται σε αυτό που είναι γνωστό ως LEGB κανόνας, που είναι συντομογραφία μεγάλο οβάλ, ΕΙΝΑΙ κλείνοντας, σολ lobal, σι uilt-in. Φαίνεται αρκετά απλό, σωστά; Λοιπόν, στην πραγματικότητα, υπάρχουν μερικές λεπτές αποχρώσεις στον τρόπο που λειτουργεί στο Python, γεγονός που μας φέρνει στο κοινό πιο προηγμένο πρόβλημα προγραμματισμού Python παρακάτω. Σκέψου τα ακόλουθα:

>>> x = 10 >>> def foo(): ... x += 1 ... print x ... >>> foo() Traceback (most recent call last): File '', line 1, in File '', line 2, in foo UnboundLocalError: local variable 'x' referenced before assignment

Ποιο είναι το πρόβλημα?

Το παραπάνω σφάλμα παρουσιάζεται επειδή, όταν κάνετε ένα ΑΝΑΘΕΣΗ ΕΡΓΑΣΙΑΣ σε μια μεταβλητή σε ένα πεδίο, Αυτή η μεταβλητή θεωρείται αυτόματα από την Python ότι είναι τοπική σε αυτό το πεδίο και σκιάζει οποιαδήποτε παρόμοια ονομασία μεταβλητή σε οποιοδήποτε εξωτερικό πεδίο.

Έτσι, πολλοί εκπλήσσονται όταν έλαβαν ένα UnboundLocalError σε προηγουμένως λειτουργικό κώδικα όταν τροποποιείται προσθέτοντας μια δήλωση ανάθεσης κάπου στο σώμα μιας συνάρτησης. (Μπορείτε να διαβάσετε περισσότερα σχετικά με αυτό εδώ .)

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

>>> lst = [1, 2, 3] >>> def foo1(): ... lst.append(5) # This works ok... ... >>> foo1() >>> lst [1, 2, 3, 5] >>> lst = [1, 2, 3] >>> def foo2(): ... lst += [5] # ... but this bombs! ... >>> foo2() Traceback (most recent call last): File '', line 1, in File '', line 2, in foo UnboundLocalError: local variable 'lst' referenced before assignment

Ε; Γιατί foo2 βόμβα ενώ foo1 έτρεξε καλά;

Η απάντηση είναι η ίδια με το πρόβλημα του προηγούμενου παραδείγματος, αλλά είναι βεβαίως πιο λεπτή. foo1 δεν κάνει ένα ΑΝΑΘΕΣΗ ΕΡΓΑΣΙΑΣ έως lst, ενώ foo2 είναι. Θυμάμαι ότι lst += [5] είναι πραγματικά συντομογραφία για lst = lst + [5], βλέπουμε ότι προσπαθούμε να το κάνουμε αναθέτω μια τιμή σε lst (συνεπώς τεκμαίρεται από την Python ότι είναι στην τοπική εμβέλεια). Ωστόσο, η τιμή που θέλουμε να αντιστοιχίσουμε στο lst βασίζεται στο lst το ίδιο (και πάλι, θεωρείται ότι βρίσκεται στο τοπικό πεδίο εφαρμογής), το οποίο δεν έχει ακόμη καθοριστεί. Κεραία.

Κοινό λάθος # 5: Τροποποίηση λίστας κατά την επανάληψη της

Το πρόβλημα με τον ακόλουθο κώδικα πρέπει να είναι αρκετά προφανές:

>>> odd = lambda x : bool(x % 2) >>> numbers = [n for n in range(10)] >>> for i in range(len(numbers)): ... if odd(numbers[i]): ... del numbers[i] # BAD: Deleting item from a list while iterating over it ... Traceback (most recent call last): File '', line 2, in IndexError: list index out of range

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

Ευτυχώς, η Python ενσωματώνει μια σειρά από κομψά παραδείγματα προγραμματισμού τα οποία, όταν χρησιμοποιούνται σωστά, μπορούν να οδηγήσουν σε σημαντικά απλοποιημένο και βελτιωμένο κώδικα. Ένα δευτερεύον πλεονέκτημα αυτού είναι ότι ο απλούστερος κώδικας είναι λιγότερο πιθανό να δαγκωθεί από το σφάλμα κατά λάθος-διαγραφή-ενός-λίστας-στοιχείου-ενώ-επανάληψης-over-it. Ένα τέτοιο παράδειγμα είναι αυτό του καταλόγους κατανόησης . Επιπλέον, η κατανόηση λίστας είναι ιδιαίτερα χρήσιμη για την αποφυγή αυτού του συγκεκριμένου προβλήματος, όπως φαίνεται από αυτήν την εναλλακτική εφαρμογή του παραπάνω κώδικα που λειτουργεί τέλεια:

>>> odd = lambda x : bool(x % 2) >>> numbers = [n for n in range(10)] >>> numbers[:] = [n for n in numbers if not odd(n)] # ahh, the beauty of it all >>> numbers [0, 2, 4, 6, 8]

Κοινό λάθος # 6: Σύγχυση του τρόπου με τον οποίο η Python δεσμεύει μεταβλητές στα κλεισίματα

Λαμβάνοντας υπόψη το ακόλουθο παράδειγμα:

>>> def create_multipliers(): ... return [lambda x : i * x for i in range(5)] >>> for multiplier in create_multipliers(): ... print multiplier(2) ...

Μπορεί να περιμένετε την ακόλουθη έξοδο:

0 2 4 6 8

Αλλά παίρνετε πραγματικά:

αρχή gestalt της κοινής μοίρας
8 8 8 8 8

Εκπληξη!

Αυτό συμβαίνει λόγω του Python's αργά δεσμευτική συμπεριφορά που λέει ότι οι τιμές των μεταβλητών που χρησιμοποιούνται στο κλείσιμο εξετάζονται τη στιγμή που καλείται η εσωτερική λειτουργία. Έτσι, στον παραπάνω κώδικα, όποτε καλείται οποιαδήποτε από τις επιστρεφόμενες συναρτήσεις, η τιμή του i κοιτάζει ψηλά στο περιβάλλον πεδίο κατά τη στιγμή που καλείται (και μέχρι τότε, ο βρόχος έχει ολοκληρωθεί, οπότε i έχει ήδη εκχωρηθεί η τελική του τιμή 4).

Η λύση σε αυτό το κοινό πρόβλημα Python είναι λίγο χακαρή:

>>> def create_multipliers(): ... return [lambda x, i=i : i * x for i in range(5)] ... >>> for multiplier in create_multipliers(): ... print multiplier(2) ... 0 2 4 6 8

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

Κοινό λάθος # 7: Δημιουργία εξαρτήσεων κυκλικής μονάδας

Ας υποθέσουμε ότι έχετε δύο αρχεία, a.py και b.py, καθένα από τα οποία εισάγει το άλλο, ως εξής:

Σε a.py:

import b def f(): return b.x print f()

Και σε b.py:

import a x = 1 def g(): print a.f()

Αρχικά, ας δοκιμάσουμε την εισαγωγή a.py:

>>> import a 1

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

έξυπνο οικιακό διαδίκτυο των πραγμάτων

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

Επιστρέφοντας λοιπόν στο παράδειγμά μας, όταν εισαγάγαμε a.py, δεν είχε κανένα πρόβλημα κατά την εισαγωγή b.py, αφού b.py δεν απαιτεί τίποτα από a.py να καθορίζονται τη στιγμή που εισάγεται . Η μόνη αναφορά στο b.py έως a είναι η κλήση προς a.f(). Αλλά αυτή η κλήση είναι σε g() και τίποτα στο a.py ή b.py επικαλείται g(). Έτσι η ζωή είναι καλή.

Αλλά τι θα συμβεί αν επιχειρήσουμε να εισαγάγουμε b.py (χωρίς προηγούμενη εισαγωγή a.py, δηλαδή):

>>> import b Traceback (most recent call last): File '', line 1, in File 'b.py', line 1, in import a File 'a.py', line 6, in print f() File 'a.py', line 4, in f return b.x AttributeError: 'module' object has no attribute 'x'

Ωχ. Αυτό δεν είναι καλό! Το πρόβλημα εδώ είναι ότι, κατά τη διαδικασία εισαγωγής b.py, επιχειρεί να εισαγάγει a.py, το οποίο με τη σειρά του καλεί f(), το οποίο επιχειρεί να αποκτήσει πρόσβαση b.x. Αλλά b.x δεν έχει ακόμη οριστεί. Εξ ου και το AttributeError εξαίρεση.

Τουλάχιστον μία λύση σε αυτό είναι αρκετά ασήμαντο. Απλώς τροποποιήστε b.py για εισαγωγή a.py στα πλαίσια g():

x = 1 def g(): import a # This will be evaluated only when g() is called print a.f()

Όχι όταν το εισάγουμε, όλα είναι καλά:

>>> import b >>> b.g() 1 # Printed a first time since module 'a' calls 'print f()' at the end 1 # Printed a second time, this one is our call to 'g'

Κοινό λάθος # 8: Το όνομα συγκρούεται με τις ενότητες Python Standard Library

Μία από τις ομορφιές του Python είναι ο πλούτος των βιβλιοθηκών που συνοδεύει το 'out of the box'. Ως αποτέλεσμα, εάν δεν το αποφεύγετε συνειδητά, δεν είναι τόσο δύσκολο να συναντήσετε μια σύγκρουση ονόματος μεταξύ του ονόματος μιας από τις ενότητες σας και μιας μονάδας με το ίδιο όνομα στην τυπική βιβλιοθήκη που αποστέλλεται με την Python (για παράδειγμα , μπορεί να έχετε μια ενότητα που ονομάζεται email.py στον κωδικό σας, η οποία θα έρχεται σε διένεξη με την τυπική λειτουργική μονάδα βιβλιοθήκης με το ίδιο όνομα).

Αυτό μπορεί να οδηγήσει σε σοβαρά προβλήματα, όπως η εισαγωγή μιας άλλης βιβλιοθήκης, η οποία με τη σειρά της προσπαθεί να εισαγάγει την έκδοση Python Standard Library μιας ενότητας, αλλά, επειδή έχετε μια ενότητα με το ίδιο όνομα, το άλλο πακέτο εισάγει εσφαλμένα την έκδοσή σας αντί για αυτήν που υπάρχει μέσα η Βιβλιοθήκη Python Standard. Εδώ συμβαίνουν κακά σφάλματα Python.

Πρέπει, επομένως, να προσέξουμε για να αποφύγουμε τη χρήση των ίδιων ονομάτων με αυτά των ενοτήτων της Python Standard Library. Είναι πολύ πιο εύκολο για εσάς να αλλάξετε το όνομα μιας λειτουργικής μονάδας εντός του πακέτου σας από το να αρχειοθετήσετε ένα Πρόταση βελτίωσης Python (PEP) για να ζητήσετε αλλαγή ονόματος πριν και για να το εγκρίνετε.

Κοινό λάθος # 9: Αποτυχία αντιμετώπισης διαφορών μεταξύ Python 2 και Python 3

Εξετάστε το ακόλουθο αρχείο foo.py:

import sys def bar(i): if i == 1: raise KeyError(1) if i == 2: raise ValueError(2) def bad(): e = None try: bar(int(sys.argv[1])) except KeyError as e: print('key error') except ValueError as e: print('value error') print(e) bad()

Στο Python 2, αυτό λειτουργεί καλά:

$ python foo.py 1 key error 1 $ python foo.py 2 value error 2

Αλλά τώρα ας το δούμε στο Python 3:

$ python3 foo.py 1 key error Traceback (most recent call last): File 'foo.py', line 19, in bad() File 'foo.py', line 17, in bad print(e) UnboundLocalError: local variable 'e' referenced before assignment

Τι μόλις συνέβη εδώ; Το «πρόβλημα» είναι ότι, στο Python 3, το αντικείμενο εξαίρεσης δεν είναι προσβάσιμο πέρα ​​από το πεδίο εφαρμογής του except ΟΙΚΟΔΟΜΙΚΟ ΤΕΤΡΑΓΩΝΟ. (Ο λόγος για αυτό είναι ότι, διαφορετικά, θα διατηρούσε έναν κύκλο αναφοράς με το πλαίσιο στοίβας στη μνήμη έως ότου ο συλλέκτης απορριμμάτων τρέξει και καθαρίσει τις αναφορές από τη μνήμη. Περισσότερες τεχνικές λεπτομέρειες σχετικά με αυτό είναι διαθέσιμες εδώ ).

Ένας τρόπος για να αποφύγετε αυτό το ζήτημα είναι να διατηρήσετε μια αναφορά στο αντικείμενο εξαίρεσης εξω απο το πεδίο εφαρμογής του except μπλοκ ώστε να παραμένει προσβάσιμο. Ακολουθεί μια έκδοση του προηγούμενου παραδείγματος που χρησιμοποιεί αυτήν την τεχνική, αποδίδοντας έτσι κώδικα που είναι φιλικός τόσο για το Python 2 όσο και για το Python 3:

η διαφορά μεταξύ s corp και c corp
import sys def bar(i): if i == 1: raise KeyError(1) if i == 2: raise ValueError(2) def good(): exception = None try: bar(int(sys.argv[1])) except KeyError as e: exception = e print('key error') except ValueError as e: exception = e print('value error') print(exception) good()

Τρέχοντας αυτό στο Py3k:

$ python3 foo.py 1 key error 1 $ python3 foo.py 2 value error 2

Yippee!

(Παρεμπιπτόντως, μας Οδηγός προσλήψεων Python συζητά πολλές άλλες σημαντικές διαφορές που πρέπει να γνωρίζετε κατά τη μετεγκατάσταση κώδικα από το Python 2 στο Python 3.)

Κοινό λάθος # 10: Κατάχρηση του __del__ μέθοδος

Ας υποθέσουμε ότι το είχατε σε ένα αρχείο που ονομάζεται mod.py:

import foo class Bar(object): ... def __del__(self): foo.cleanup(self.myhandle)

Και τότε προσπαθήσατε να το κάνετε από another_mod.py:

import mod mybar = mod.Bar()

Θα έχετε ένα άσχημο AttributeError εξαίρεση.

Γιατί; Διότι, όπως αναφέρεται εδώ , όταν τερματίζεται η λειτουργία του διερμηνέα, οι καθολικές μεταβλητές της μονάδας έχουν ρυθμιστεί σε None. Ως αποτέλεσμα, στο παραπάνω παράδειγμα, στο σημείο αυτό __del__ γίνεται επίκληση, το όνομα foo έχει ήδη οριστεί σε None.

Μια λύση σε αυτό το κάπως πιο προηγμένο πρόβλημα προγραμματισμού Python θα ήταν να χρησιμοποιηθεί atexit.register() αντι αυτου. Με αυτόν τον τρόπο, όταν το πρόγραμμά σας ολοκληρωθεί (κατά την κανονική έξοδο, δηλαδή), οι εγγεγραμμένοι χειριστές σας ξεκινούν πριν ο διερμηνέας κλείνει.

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

import foo import atexit def cleanup(handle): foo.cleanup(handle) class Bar(object): def __init__(self): ... atexit.register(cleanup, self.myhandle)

Αυτή η εφαρμογή παρέχει έναν καθαρό και αξιόπιστο τρόπο κλήσης οποιασδήποτε απαραίτητης λειτουργικότητας καθαρισμού κατά τον κανονικό τερματισμό του προγράμματος. Προφανώς, εξαρτάται από το foo.cleanup να αποφασίσετε τι να κάνετε με το αντικείμενο που είναι δεσμευμένο στο όνομα self.myhandle, αλλά έχετε την ιδέα.

Τύλιξε

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

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

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

Ελπίζουμε να βρείτε χρήσιμους τους δείκτες σε αυτό το άρθρο και να καλωσορίσουμε τα σχόλιά σας.

Λέξεις και ενέργειες - Ένας οδηγός για τη μικροτυπία

Σχεδιασμός Ux

Λέξεις και ενέργειες - Ένας οδηγός για τη μικροτυπία
Η κρίση που αναπτύσσεται στις κοινότητες συνταξιοδότησης συνεχούς φροντίδας (CCRCs)

Η κρίση που αναπτύσσεται στις κοινότητες συνταξιοδότησης συνεχούς φροντίδας (CCRCs)

Διαδικασίες Χρηματοδότησης

Δημοφιλείς Αναρτήσεις
Πέντε δοκιμασμένες μάχες τεχνικές που δεν χρησιμοποιεί ο προγραμματιστής του WordPress API
Πέντε δοκιμασμένες μάχες τεχνικές που δεν χρησιμοποιεί ο προγραμματιστής του WordPress API
MetaDapper: Η χαρτογράφηση δεδομένων και η μετατροπή γίνονται εύκολα με τα σωστά εργαλεία
MetaDapper: Η χαρτογράφηση δεδομένων και η μετατροπή γίνονται εύκολα με τα σωστά εργαλεία
Διευθυντής ανάπτυξης
Διευθυντής ανάπτυξης
Taming WebRTC με PeerJS: Δημιουργία ενός απλού παιχνιδιού Web P2P
Taming WebRTC με PeerJS: Δημιουργία ενός απλού παιχνιδιού Web P2P
Εξερεύνηση του πολυτροπικού σχεδιασμού - Ένα πρόγραμμα εκμάθησης του Adobe XD
Εξερεύνηση του πολυτροπικού σχεδιασμού - Ένα πρόγραμμα εκμάθησης του Adobe XD
 
Οι μεγάλες ερωτήσεις οδηγούν σε εξαιρετικό σχεδιασμό: Ένας οδηγός για τη διαδικασία σκέψης σχεδιασμού
Οι μεγάλες ερωτήσεις οδηγούν σε εξαιρετικό σχεδιασμό: Ένας οδηγός για τη διαδικασία σκέψης σχεδιασμού
Εξερεύνηση του πολυτροπικού σχεδιασμού - Ένα πρόγραμμα εκμάθησης του Adobe XD
Εξερεύνηση του πολυτροπικού σχεδιασμού - Ένα πρόγραμμα εκμάθησης του Adobe XD
Κοινή χρήση εθισμού επαναγοράς: Μελέτες περιπτώσεων επιτυχίας
Κοινή χρήση εθισμού επαναγοράς: Μελέτες περιπτώσεων επιτυχίας
Terraform AWS Cloud: Διαχείριση Sane Infrastructure
Terraform AWS Cloud: Διαχείριση Sane Infrastructure
Όλα όσα πρέπει να ξέρετε για το CVS-Aetna Merger
Όλα όσα πρέπει να ξέρετε για το CVS-Aetna Merger
Δημοφιλείς Αναρτήσεις
  • τρωτά σημεία πρωτοκόλλου ή/και εισβολές
  • εργαλείο που χρησιμοποιείται για την οπτικοποίηση όλων των δυνατών συνδυασμών
  • ωριαία τιμή έναντι υπολογισμού μισθού
  • πώς να χρησιμοποιήσετε το bootstrap 3
  • δωρεάν χακαρισμένες πιστωτικές κάρτες με χρήματα
  • υπολογιστής μισθού temp to perm
Κατηγορίες
  • Ζωή Σχεδιαστών
  • Διαδικασίες Χρηματοδότησης
  • Συμβουλές Και Εργαλεία
  • Μηχανική Διοίκηση
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt