Як би ви перевірили, чи є змінною словник у Python?
Це хороше запитання, але, на жаль, більшість upvoted відповідь веде з поганою рекомендацією type(obj) is dict
.
(Зверніть увагу, що ви також не повинні використовувати dict
як ім'я змінної - це ім'я вбудованого об'єкта.)
Якщо ви пишете код, який буде імпортований та використаний іншими особами, не припускайте, що вони будуть використовувати безпосередньо вбудований dict безпосередньо - зробивши таку презумпцію, що робить ваш код більш негнучким, і в цьому випадку створюйте легко приховані помилки, які не помилять програму .
Я настійно пропоную з метою правильності, ремонтопридатності та гнучкості майбутнім користувачам, ніколи не маючи менш гнучких унідіоматичних виразів у своєму коді, коли є більш гнучкі, ідіоматичні вирази.
is
є тестом на ідентичність об'єкта . Він не підтримує успадкування, він не підтримує жодної абстракції і не підтримує інтерфейс.
Тож я надам декілька варіантів, які можна зробити.
Підтримуюча спадщина:
Це перша рекомендація я хотів би зробити, тому що вона дозволяє користувачам поставити свій власний підклас Dict, або OrderedDict
, defaultdict
або Counter
з колекції модуля:
if isinstance(any_object, dict):
Але є ще більш гнучкі варіанти.
Підтримуючі абстракції:
from collections.abc import Mapping
if isinstance(any_object, Mapping):
Це дозволяє користувачеві вашого коду використовувати власну власну реалізацію абстрактного картографування, яка також включає будь-який підклас dict
та все ж отримувати правильну поведінку.
Використовуйте інтерфейс
Ви часто чуєте поради OOP, "програма на інтерфейс".
Ця стратегія використовує перевагу поліморфізму Python або типізації качок.
Тому просто спробуйте отримати доступ до інтерфейсу, зафіксувавши конкретні очікувані помилки ( AttributeError
у випадку, якщо таких немає, .items
і TypeError
у випадку, якщо items
їх не можна викликати), з розумним відпадом - і тепер будь-який клас, який реалізує цей інтерфейс, передасть вам свої елементи (примітка .iteritems()
відсутня в Python 3):
try:
items = any_object.items()
except (AttributeError, TypeError):
non_items_behavior(any_object)
else: # no exception raised
for item in items: ...
Можливо, ви можете подумати, що використання типу качки набирає занадто далеко, щоб отримати занадто багато помилкових позитивів, і це може бути, залежно від ваших цілей цього коду.
Висновок
Не використовуйте is
для перевірки типів для стандартного потоку управління. Використовуйте isinstance
, розглядайте такі абстракції, як Mapping
і MutableMapping
, і взагалі уникайте перевірки типу, використовуючи інтерфейс безпосередньо.