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

Классы слова Python помимо строк и целых чисел?

У кого-нибудь есть опрятные примеры словарей с интересными ключами (помимо канонической строки или целого) и как вы их использовали в своей программе?

Я понимаю, что все, что нам нужно для ключа, это что-то hashable, то есть оно должно быть неизменным и сопоставимым (имеет метод __eq__() или __cmp__()).

Связанный с этим вопрос: как быстро и легко определить новый hashable?

4b9b3361

Ответ 1

Отпустите для чего-то более эзотерического. Предположим, вы хотели выполнить список функций и сохранить результат каждого из них. Для каждой функции, которая создала исключение, вы хотите записать исключение, и вы также хотите, чтобы подсчитывать, сколько раз увеличивается каждый тип исключения. Функции и исключения могут использоваться как клавиши dict, поэтому это легко:

funclist = [foo, bar, baz, quux]

results    = {}
badfuncs   = {}
errorcount = {}

for f in funclist:
    try:
        results[f] = f()
    except Exception as e:
        badfuncs[f]   = e
        errorcount[type(e)] = errorcount[type(e)] + 1 if type(e) in errorcount else 1

Теперь вы можете сделать if foo in badfuncs, чтобы проверить, вызвала ли эта функция исключение (или if foo in results, чтобы проверить, правильно ли она работает), if ValueError in errorcount, чтобы увидеть, была ли какая-либо функция поднята ValueError и т.д.

Ответ 2

Вы можете использовать кортеж в качестве ключа, например, если вы хотите создать индекс с несколькими столбцами. Вот простой пример:

>>> index = {("John", "Smith", "1972/01/01"): 123, ("Bob", "Smith", "1972/01/02"): 124}
>>> index
{('Bob', 'Smith', '1972/01/02'): 124, ('John', 'Smith', '1972/01/01'): 123}
>>> index.keys()
[('Bob', 'Smith', '1972/01/02'), ('John', 'Smith', '1972/01/01')]
>>> index['John', 'Smith', '1972/01/01']
123

Для примера, как использовать dict в качестве ключа (hashable dict), см. этот ответ: Python hashable dicts

Ответ 3

Вы оставили, пожалуй, самый важный метод для объекта hashable: __hash__().

Самая короткая реализация вашего собственного хешируемого типа такова:

class A(object):
    pass

Теперь вы можете использовать экземпляры A в качестве словарных клавиш:

d = {}
a = A()
b = A()
d[a] = 7
d[b] = 8

Это связано с тем, что пользовательские классы по умолчанию хешируются, а их хэш-значение - их идентификатор, поэтому они будут сравнивать только равные, если они являются одним и тем же объектом.

Обратите внимание, что экземпляры A никоим образом не являются неизменяемыми, и тем не менее они могут использоваться как словарные ключи. Утверждение, что словарные ключи должны быть неизменяемыми, сохраняется только для встроенных типов.

Ответ 4

Заметьте, что я никогда не использовал это, но я всегда думал, используя кортежи, поскольку ключи могут позволить вам сделать некоторые интересные вещи. Например, я нашел бы удобный способ сопоставить координаты сетки. Вы можете думать об этом как о сетке в видеоигре (возможно, какая-то тактическая игра, например Fire Emblem):

>>> Terrain = { (1,3):"Forest", (1,5):"Water", (3,4):"Land" }
>>> print Terrain
{(1, 5): 'Water', (1, 3): 'Forest', (3, 4): 'Land'}
>>> print Terrain[(1,3)]
Forest
>>> print Terrain[(1,5)]
Water
>>> x = 3
>>> y = 4
>>> print Terrain[(x,y)]
Land

Что-то вроде этого.

Изменить: Как отметил Марк Рушаков в комментариях, я в основном предполагаю, что это разреженный массив.

Ответ 5

Я понятия не имею, зачем вам это делать (и желательно, не делать это)... но рядом со строками и целыми числами вы также можете использовать оба одновременно. То есть, как новичок, я нашел и сильным, и удивительным, что:

foo = { 1:'this', 2:'that', 'more':'other', 'less':'etc' }

- полностью действующий словарь, который обеспечивает доступ к foo[2] так же легко, как и для foo['more'].