Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Dictionary in Python
Search
Cyril Lashkevich
March 13, 2014
Programming
0
110
Dictionary in Python
Cyril Lashkevich
March 13, 2014
Tweet
Share
More Decks by Cyril Lashkevich
See All by Cyril Lashkevich
Go Scheduler
notorca
2
590
Bitcode in Swift
notorca
0
43
Mobile Optimized 2014
notorca
1
260
Fun with blocks in ObjC
notorca
1
88
CocoaHeads in Grodno, Lighting
notorca
0
80
Foundation data structures
notorca
0
140
iOS memory management
notorca
0
84
NSProxy, multithreading, messaging
notorca
1
88
Python impergections
notorca
0
75
Other Decks in Programming
See All in Programming
ドメインモデリングにおける抽象の役割、tagless-finalによるDSL構築、そして型安全な最適化
knih
11
2k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
41
28k
Webからモバイルへ Vue.js × Capacitor 活用事例
naokihaba
0
740
C++20 射影変換
faithandbrave
0
500
Cursor AI Agentと伴走する アプリケーションの高速リプレイス
daisuketakeda
1
120
Using AI Tools Around Software Development
inouehi
0
1.2k
社内での開発コミュニティ活動とモジュラーモノリス標準化事例のご紹介/xPalette and Introduction of Modular monolith standardization
m4maruyama
1
130
Benchmark
sysong
0
230
Effect の双対、Coeffect
yukikurage
5
1.4k
関数型まつり2025登壇資料「関数プログラミングと再帰」
taisontsukada
2
840
Passkeys for Java Developers
ynojima
3
880
Create a website using Spatial Web
akkeylab
0
290
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
94
14k
Git: the NoSQL Database
bkeepers
PRO
430
65k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
Being A Developer After 40
akosma
90
590k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
A Modern Web Designer's Workflow
chriscoyier
693
190k
The World Runs on Bad Software
bkeepers
PRO
69
11k
Agile that works and the tools we love
rasmusluckow
329
21k
Practical Orchestrator
shlominoach
188
11k
RailsConf 2023
tenderlove
30
1.1k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Transcript
Dictionary в Python По мотивам Objects/dictnotes.txt Cyril @notorca Lashkevich piątek,
30 sierpnia 13
Как создать словарь {} dict() PyObject* PyDict_New() piątek, 30 sierpnia
13
Сколько словарей в Hello World? $ python -c "print('Hello world')"
| wc -l piątek, 30 sierpnia 13
Сколько словарей в Hello World? $ python -c "print('Hello world')"
| wc -l 1642 piątek, 30 sierpnia 13
Именованные параметры функицй 1 запись, 1 чтение 1-3 элемента Часто
встречается в обычных программах на Python piątek, 30 sierpnia 13
Поиск метода в классе 1 запись, много чтений 8-16 элементов
При наследовании много неудачных чтений с последующим поиском в базовом классе piątek, 30 sierpnia 13
Атрибуты и глобальные пременные Много записей и чтений 4-10 элементов
piątek, 30 sierpnia 13
Builtins Частые чтение, почти не бывает записи ~150 строковых ключей
(3.3) По некоторым ключам чтения гораздо чаще чем по другим piątek, 30 sierpnia 13
Удаление повторов, подсчет элементов Одинократное чтение по каждому из ключей
Произвольное количество элементов Многократный доступ по одному ключу подряд piątek, 30 sierpnia 13
Удаление дубликатов dict.fromkeys(seqn).keys() Все операции записи при конструировании piątek, 30
sierpnia 13
Подсчет элементов в последовательности for e in seqn: d[e] =
d.get(e,0) + 1 2 последовательных доступа по одинаковому ключу piątek, 30 sierpnia 13
Создание индекса из словаря списков setdefault совмещает 2 поиска в
1м for pnum, page in enumerate(pages): for w in page: d.setdefault(w, []).append(pnum) piątek, 30 sierpnia 13
Проверка принадлежности Словари произвольных размеров Создаются 1 раз и затем
мало изменяются Много вызовов has_key() и __contains__() piątek, 30 sierpnia 13
Динамические отображения Чередующиеся добавления, удаления, чтение и перезапись элементов piątek,
30 sierpnia 13
Реализация (2.7) Последовательная область памяти с доступом по индксу typedef
struct { Py_hash_t me_hash; PyObject *me_key; PyObject *me_value; } PyDictKeyEntry; piątek, 30 sierpnia 13
Пустой dict с размером по умолчанию (8 элементов) >>> d
= {} piątek, 30 sierpnia 13
Хеширование ключа Ключ преобразуется в индекс с помощъю функции hash()
hash() возвращает 32/64bit значение Для индекса берется n младших бит piątek, 30 sierpnia 13
Свойства хеша Для равных значений хеши всегда равны Даже если
представление значений разное: 9, 9.0, complex(9,0) Похожие значения дают сильно отличающиеся хеши piątek, 30 sierpnia 13
>>> d['ftp'] = 21 >>> bits(hash('ftp'))[-8:] 10100001 piątek, 30 sierpnia
13
>>> d['ftp'] = 21 >>> bits(hash('ftp'))[-8:] 10100001 piątek, 30 sierpnia
13
>>> d['ssh'] = 22 >>> bits(hash('ssh'))[-3:] 101 piątek, 30 sierpnia
13
>>> d['ssh'] = 22 >>> bits(hash('ssh'))[-3:] 101 piątek, 30 sierpnia
13
>>> d['smtp'] = 25 >>> bits(hash('smtp'))[-3:] 100 piątek, 30 sierpnia
13
>>> d['smtp'] = 25 >>> bits(hash('smtp'))[-3:] 100 piątek, 30 sierpnia
13
>>> d['time'] = 37 >>> bits(hash('time'))[-3:] 111 piątek, 30 sierpnia
13
>>> d['time'] = 37 >>> bits(hash('time'))[-3:] 111 piątek, 30 sierpnia
13
>>> d['www'] = 80 >>> bits(hash('www'))[-3:] 010 piątek, 30 sierpnia
13
>>> d['www'] = 80 >>> bits(hash('www'))[-3:] 010 piątek, 30 sierpnia
13
d = {'ftp': 21, 'ssh': 22, 'smtp': 25, 'time': 37,
'www': 80} piątek, 30 sierpnia 13
Поиск в словаре Вычислить хеш от ключа Обрезать старшие биты
Взять значение из слота по индексу piątek, 30 sierpnia 13
>>> d['smtp'] 25 >>> bits(hash('smtp'))[-3:] 100 piątek, 30 sierpnia 13
Перебор всех элементов Словари возвращают свои ключи или значения в
порядке отличном от порядка добавления piątek, 30 sierpnia 13
>>> print d {'ftp': 21, 'www': 80, 'smtp': 25, 'ssh':
22, 'time': 37} piątek, 30 sierpnia 13
>>> d.keys() ['ftp', 'www', 'smtp', 'ssh', 'time'] piątek, 30 sierpnia
13
>>> d.values() [21, 80, 25, 22, 37] piątek, 30 sierpnia
13
Коллизии Разные ключи пытаются доступиться по одинаковому индексу Находим первое
свободное место piątek, 30 sierpnia 13
>>> d = {} piątek, 30 sierpnia 13
>>> d['smtp'] = 21 piątek, 30 sierpnia 13
>>> d['smtp'] = 21 piątek, 30 sierpnia 13
>>> d['dict'] = 2628 piątek, 30 sierpnia 13
>>> d['dict'] = 2628 piątek, 30 sierpnia 13
>>> d['svn'] = 3690 piątek, 30 sierpnia 13
>>> d['svn'] = 3690 piątek, 30 sierpnia 13
>>> d['ircd'] = 6667 piątek, 30 sierpnia 13
>>> d['ircd'] = 6667 piątek, 30 sierpnia 13
>>> d['zope'] = 9673 piątek, 30 sierpnia 13
>>> d['zope'] = 9673 # 2 из 5ти элементов на
своих ожидаемых местах piątek, 30 sierpnia 13
Коллизии и очередность Поскольку из за коллизий элементы могут находится
не по своим "естественным" индексам порядок элементов зависит от порядка добавления piątek, 30 sierpnia 13
Поиск первой свободной ячейки Последовательный поиск плох для int ключей
pertrurb = hash while (<слот занят>) { slot = (5*slot) + 1 + perturb; perturb >>= 5; } piątek, 30 sierpnia 13
>>> d['svn'] 3690 piątek, 30 sierpnia 13
>>> d['ircd'] 6667 piątek, 30 sierpnia 13
>>> d['nsca'] KeyError: 'nsca' piątek, 30 sierpnia 13
>>> d['netstat'] KeyError: 'netstat' piątek, 30 sierpnia 13
Не все поиски одинаковы Некоторые находят результат сразу Некоторым нужны
несколько итераций piątek, 30 sierpnia 13
threes = {3: 1, 3+8: 2, 3+16: 3, 3+24: 4,
3+32: 5} piątek, 30 sierpnia 13
Удаление элементов Нелзя просто так взять, и пометить ячейку как
пустую Необходимо вставить специальный "dummy" элемент piątek, 30 sierpnia 13
del d['smtp'] piątek, 30 sierpnia 13
del d['smtp'] d['ircd'] ??? piątek, 30 sierpnia 13
del d['smtp'] #Заменяем на "dummy" слот #Может быть использован снова
piątek, 30 sierpnia 13
del d['smtp'] #Заменяем на "dummy" слот #Может быть использован снова
piątek, 30 sierpnia 13
>>> del d['svn'], d['dict'], d['zope'] >>> d['ircd'] piątek, 30 sierpnia
13
Увеличение размера таблицы Таблица заполнена максимум на 2/3 2.7: <
50k size × 4 > 50k size × 2 3.3: size × 2 piątek, 30 sierpnia 13
>>> d = {} piątek, 30 sierpnia 13
d = dict.fromkeys(words[:5]) # 40% коллизий # Заполнен на ⅔,
resize piątek, 30 sierpnia 13
d['abash'] = None # размер ×4 до 32 # 0%
коллизий piątek, 30 sierpnia 13
d = dict.fromkeys(words[:21]) # 29% коллизий # Заполнен на ⅔
piątek, 30 sierpnia 13
d['abode'] = None # размер ×4 до 128 # 9%
коллизий piątek, 30 sierpnia 13
d = dict.fromkeys(words[:85]) # 33% коллизий # Заполнен на ⅔
piątek, 30 sierpnia 13
Время доступа к элементам Растет по мере заполнения словаря Затем
резко умешьшается после изменения размера Среднее время доступа ОК piątek, 30 sierpnia 13
Поиски vs размер piątek, 30 sierpnia 13
Время vs размер piątek, 30 sierpnia 13
Удаление элементов Не уменьшает размер таблицы Таблица может уменьшиться только
при добавлении элементов piątek, 30 sierpnia 13
Порядок элементов Во время изменения размера порядок элементов может полностью
поменяться Добавление элементов во время итерации запрещено RuntimeError: dictionary changed size during iteration piątek, 30 sierpnia 13
Свой __hash__() Хорошо перемешать биты Равные хеши для равных элементов
__eq__() должен быть Быстро вычисляется piątek, 30 sierpnia 13
Пример __hash__() class Point(object): def __init__(self, x, y): self.x, self.y
= x, y def __eq__(self, p): return self.x==p.x and self.y==p.y def __hash__(self): return hash(self.x) ^ hash(self.y) piątek, 30 sierpnia 13
oCERT #2011-003 Хэш для str, bytes и datetime смешивается с
"солью" уникальной для каждого процесса Python pre 3.3: -R option 3.3: by default piątek, 30 sierpnia 13
Python 3: Split-table словари. Общая таблица с ключами для разных
таблиц со значениями piątek, 30 sierpnia 13
Спасибо http://blip.tv/pycon-us- videos-2009-2010-2011/pycon-2010- the-mighty-dictionary-55-3352147 Python source code piątek, 30 sierpnia
13