Υπάρχει ένας απλός τρόπος για να προσδιορίσετε αν μια μεταβλητή είναι λίστα, λεξικό ή κάτι άλλο; Παίρνω πίσω ένα αντικείμενο που μπορεί να είναι οποιουδήποτε τύπου και πρέπει να μπορώ να καταλάβω τη διαφορά.
Για να λάβετε τον τύπο ενός αντικειμένου, μπορείτε να χρησιμοποιήσετε την ενσωματωμένη συνάρτηση type()
. Περνώντας ένα αντικείμενο ως μοναδική παράμετρο θα επιστρέψετε το αντικείμενο τύπου αυτού του αντικειμένου:
>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})
<type 'dict'>
>>> type([])
<type 'list'>
Αυτό φυσικά λειτουργεί και για προσαρμοσμένους τύπους:
>>> class Test1 (object):
pass
>>> class Test2 (Test1):
pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True
Σημειώστε ότι η type()
θα επιστρέψει μόνο τον άμεσο τύπο του αντικειμένου, αλλά δεν θα είναι σε θέση να σας πει για την κληρονομικότητα τύπου.
>>> type(b) is Test1
False
Για να το καλύψετε αυτό, θα πρέπει να χρησιμοποιήσετε τη συνάρτηση isinstance
. Αυτό φυσικά λειτουργεί και για ενσωματωμένους τύπους:
>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True
Η isinstance()
είναι συνήθως ο προτιμώμενος τρόπος για να εξασφαλίσετε τον τύπο ενός αντικειμένου επειδή δέχεται και παράγωγους τύπους. Έτσι, εκτός αν χρειάζεστε πραγματικά το αντικείμενο τύπου (για οποιονδήποτε λόγο), η χρήση της isinstance()
προτιμάται από την type()
.
Η δεύτερη παράμετρος της isinstance()
δέχεται επίσης μια πλειάδα τύπων, έτσι ώστε να είναι δυνατός ο έλεγχος για πολλούς τύπους ταυτόχρονα. Η isinstance
θα επιστρέψει true, αν το αντικείμενο είναι οποιουδήποτε από αυτούς τους τύπους:
>>> isinstance([], (tuple, list, set))
True
Ίσως θα ήταν πιο Pythonic να χρησιμοποιήσετε ένα μπλοκ try
...except
. Με αυτόν τον τρόπο, αν έχετε μια κλάση που μοιάζει με λίστα, ή μοιάζει με dict, θα συμπεριφέρεται σωστά ανεξάρτητα από το ποιος είναι ο τύπος της πραγματικά.
Για να ξεκαθαρίσουμε, η προτιμώμενη μέθοδος για να "καταλάβετε τη διαφορά" μεταξύ των τύπων των μεταβλητών είναι με κάτι που ονομάζεται duck typing: εφόσον οι μέθοδοι (και οι τύποι επιστροφής) στις οποίες ανταποκρίνεται μια μεταβλητή είναι αυτές που περιμένει το υποπρόγραμμά σας, αντιμετωπίστε την σαν αυτό που περιμένετε να είναι. Για παράδειγμα, αν έχετε μια κλάση που υπερφορτώνει τους τελεστές αγκύλης με getattr
και setattr
, αλλά χρησιμοποιεί κάποιο αστείο εσωτερικό σχήμα, θα ήταν σκόπιμο να συμπεριφέρεται ως λεξικό, αν αυτό προσπαθεί να μιμηθεί.
Το άλλο πρόβλημα με τον έλεγχο type(A) is type(B)
είναι ότι αν το A
είναι υποκλάση του B
, αξιολογείται ως false
ενώ, προγραμματιστικά, θα ελπίζατε ότι θα ήταν true
. Αν ένα αντικείμενο είναι υποκλάση μιας λίστας, θα πρέπει να λειτουργεί σαν λίστα: ο έλεγχος του τύπου, όπως παρουσιάζεται στην άλλη απάντηση, θα το αποτρέψει αυτό. (Το isinstance
θα λειτουργήσει, ωστόσο).