Подтвердить что ты не робот

Запрос "hashable" о значении Python

Я заинтересован в том, чтобы взять произвольный dict и скопировать его в новый dict, мутируя его на этом пути.

Одна мутация, которую я хотел бы сделать, - это своп-ключи и значение. К сожалению, некоторые ценности сами по себе являются диктофонами. Тем не менее, это генерирует ошибку "unhashable type: 'dict". На самом деле, я не против просто подчеркивать значение и давать ему ключ. Но я хотел бы сделать что-то вроде этого:

for key in olddict:
  if hashable(olddict[key]):
    newdict[olddict[key]] = key
  else
    newdict[str(olddict[key])] = key

Есть ли чистый способ сделать это, который не связан с захватом исключения и разбор строки сообщения для "нераспакованного типа"?

4b9b3361

Ответ 1

Начиная с Python 2.6 вы можете использовать абстрактный collections.Hashable базовых классов. collections.Hashable:

>>> import collections
>>> isinstance({}, collections.Hashable)
False
>>> isinstance(0, collections.Hashable)
True

Этот подход также кратко упоминается в документации для __hash__.

Это означает, что экземпляры класса не только TypeError соответствующий TypeError когда программа попытается получить их хеш-значение, но они также будут правильно идентифицированы как не подлежащие обработке при проверке isinstance(obj, collections.Hashable) (в отличие от классов, которые определяют их собственный __hash__() явно поднять TypeError).

Ответ 2

def hashable(v):
    """Determine whether `v` can be hashed."""
    try:
        hash(v)
    except TypeError:
        return False
    return True

Ответ 3

Все хешируемые встроенные объекты python имеют метод .__hash__(). Вы можете проверить это.

olddict = {"a":1, "b":{"test":"dict"}, "c":"string", "d":["list"] }

for key in olddict:
   if(olddict[key].__hash__):
      print str(olddict[key]) + " is hashable"
   else: 
      print str(olddict[key]) + " is NOT hashable"

Выход

1 is hashable
string is hashable
{'test': 'dict'} is NOT hashable
['list'] is NOT hashable

Ответ 4

Почему бы не использовать утиную печать?

for key in olddict:
   try:
       newdict[olddict[key]] = key
   except TypeError:
       newdict[str(olddict[key])] = key