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
610
Bitcode in Swift
notorca
0
47
Mobile Optimized 2014
notorca
1
260
Fun with blocks in ObjC
notorca
1
90
CocoaHeads in Grodno, Lighting
notorca
0
81
Foundation data structures
notorca
0
140
iOS memory management
notorca
0
90
NSProxy, multithreading, messaging
notorca
1
93
Python impergections
notorca
0
80
Other Decks in Programming
See All in Programming
実践AIチャットボットUI実装入門
syumai
7
2.5k
株式会社 Sun terras カンパニーデック
sunterras
0
250
技術的負債の正体を知って向き合う / Facing Technical Debt
irof
0
120
CSC305 Lecture 04
javiergs
PRO
0
260
Swift Concurrency - 状態監視の罠
objectiveaudio
2
480
私達はmodernize packageに夢を見るか feat. go/analysis, go/ast / Go Conference 2025
kaorumuta
2
500
いま中途半端なSwift 6対応をするより、Default ActorやApproachable Concurrencyを有効にしてからでいいんじゃない?
yimajo
2
360
複雑化したリポジトリをなんとかした話 pipenvからuvによるモノレポ構成への移行
satoshi256kbyte
1
850
ソフトウェア設計の実践的な考え方
masuda220
PRO
3
500
CI_CD「健康診断」のススメ。現場でのボトルネック特定から、健康診断を通じた組織的な改善手法
teamlab
PRO
0
190
クラシルを支える技術と組織
rakutek
0
190
monorepo の Go テストをはやくした〜い!~最小の依存解決への道のり~ / faster-testing-of-monorepos
convto
2
430
Featured
See All Featured
4 Signs Your Business is Dying
shpigford
185
22k
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
189
55k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
114
20k
Building an army of robots
kneath
306
46k
BBQ
matthewcrist
89
9.8k
Bash Introduction
62gerente
615
210k
Music & Morning Musume
bryan
46
6.8k
It's Worth the Effort
3n
187
28k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
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