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
94
Dictionary in Python
Cyril Lashkevich
March 13, 2014
Tweet
Share
More Decks by Cyril Lashkevich
See All by Cyril Lashkevich
Go Scheduler
notorca
2
530
Bitcode in Swift
notorca
0
39
Mobile Optimized 2014
notorca
1
250
Fun with blocks in ObjC
notorca
1
76
CocoaHeads in Grodno, Lighting
notorca
0
71
Foundation data structures
notorca
0
130
iOS memory management
notorca
0
75
NSProxy, multithreading, messaging
notorca
1
80
Python impergections
notorca
0
60
Other Decks in Programming
See All in Programming
offers_20241022_imakiire.pdf
imakurusu
2
360
Kaigi on Rails 2024 - Rails APIモードのためのシンプルで効果的なCSRF対策 / kaigionrails-2024-csrf
corocn
5
3.4k
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
9
1k
C#/.NETのこれまでのふりかえり
tomokusaba
1
160
Jakarta Concurrencyによる並行処理プログラミングの始め方 (JJUG CCC 2024 Fall)
tnagao7
1
230
What’s New in Compose Multiplatform - A Live Tour (droidcon London 2024)
zsmb
1
340
Android 15 でアクションバー表示時にステータスバーが白くなってしまう問題
tonionagauzzi
0
140
カラム追加で増えるActiveRecordのメモリサイズ イメージできますか?
asayamakk
4
1.6k
JaSST 24 九州:ワークショップ(は除く)実践!マインドマップを活用したソフトウェアテスト+活用事例
satohiroyuki
0
260
Identifying User Idenity
moro
6
7.9k
アジャイルを支えるテストアーキテクチャ設計/Test Architecting for Agile
goyoki
7
2.8k
のびしろを広げる巻き込まれ力:偶然を活かすキャリアの作り方/oso2024
takahashiikki
1
410
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.2k
A Tale of Four Properties
chriscoyier
156
23k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
3
370
How GitHub (no longer) Works
holman
311
140k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
33k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.8k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
43
6.6k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2.1k
Navigating Team Friction
lara
183
14k
Six Lessons from altMBA
skipperchong
26
3.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
290
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