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
46
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
87
NSProxy, multithreading, messaging
notorca
1
92
Python impergections
notorca
0
79
Other Decks in Programming
See All in Programming
オープンセミナー2025@広島「君はどこで動かすか?」アンケート結果
satoshi256kbyte
0
220
私の後悔をAWS DMSで解決した話
hiramax
4
170
ライブ配信サービスの インフラのジレンマ -マルチクラウドに至ったワケ-
mirrativ
2
270
OSS開発者という働き方
andpad
3
1.1k
DockerからECSへ 〜 AWSの海に出る前に知っておきたいこと 〜
ota1022
5
1.8k
AWS発のAIエディタKiroを使ってみた
iriikeita
1
110
Kiroの仕様駆動開発から見えてきたAIコーディングとの正しい付き合い方
clshinji
1
180
TDD 実践ミニトーク
contour_gara
1
250
エンジニアのための”最低限いい感じ”デザイン入門
shunshobon
0
130
Microsoft Orleans, Daprのアクターモデルを使い効率的に開発、デプロイを行うためのSekibanの試行錯誤 / Sekiban: Exploring Efficient Development and Deployment with Microsoft Orleans and Dapr Actor Models
tomohisa
0
220
AI時代のドメイン駆動設計-DDD実践におけるAI活用のあり方 / ddd-in-ai-era
minodriven
24
9.2k
Langfuseと歩む生成AI活用推進
licux
3
320
Featured
See All Featured
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
490
Reflections from 52 weeks, 52 projects
jeffersonlam
351
21k
The Language of Interfaces
destraynor
160
25k
The Straight Up "How To Draw Better" Workshop
denniskardys
236
140k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.5k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Designing for Performance
lara
610
69k
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