-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdictionaries.py
More file actions
406 lines (311 loc) · 11.2 KB
/
Copy pathdictionaries.py
File metadata and controls
406 lines (311 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
"""
Module: dictionaries.py
Topic: Dictionaries in Python
Level: Beginner
This file teaches you about:
- Dictionary creation and basics
- Accessing and modifying dictionaries
- Dictionary methods
- Dictionary comprehensions
- Nested dictionaries
"""
# =============================================================================
# SECTION 1: DICTIONARY CREATION
# =============================================================================
print("=" * 60)
print("DICTIONARY CREATION")
print("=" * 60)
# Different ways to create dictionaries
dict1 = {'name': 'Alice', 'age': 25} # Direct creation
dict2 = dict(name='Bob', age=30) # Using dict() with keyword args
dict3 = dict([('name', 'Charlie'), ('age', 35)]) # From list of tuples
dict4 = {} # Empty dictionary
dict5 = dict() # Empty dictionary (constructor)
print(f"Direct: {dict1}")
print(f"dict(name='Bob', age=30): {dict2}")
print(f"From tuples: {dict3}")
print(f"Empty: {dict4}")
# Using dict.fromkeys()
keys = ['a', 'b', 'c']
new_dict = dict.fromkeys(keys, 0)
print(f"fromkeys(['a','b','c'], 0): {new_dict}")
# Dictionary with mixed key types
mixed = {'name': 'Alice', 1: 'one', (1, 2): 'tuple key'}
print(f"Mixed keys: {mixed}")
# =============================================================================
# SECTION 2: ACCESSING VALUES
# =============================================================================
print("\n" + "=" * 60)
print("ACCESSING VALUES")
print("=" * 60)
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}
print(f"Dictionary: {person}")
# Using key
print(f"\nUsing key:")
print(f" person['name']: {person['name']}")
# Using get() (safer, returns None or default if key missing)
print(f"\nUsing get():")
print(f" person.get('name'): {person.get('name')}")
print(f" person.get('job', 'Unknown'): {person.get('job', 'Unknown')}")
# KeyError when key doesn't exist
try:
print(person['job'])
except KeyError as e:
print(f" person['job'] raises KeyError: {e}")
# get() vs [] operator
print(f"\nComparison:")
print(f" person.get('job'): {person.get('job')}") # Returns None
print(f" person.get('job', 'N/A'): {person.get('job', 'N/A')}") # Returns default
# =============================================================================
# SECTION 3: MODIFYING DICTIONARIES
# =============================================================================
print("\n" + "=" * 60)
print("MODIFYING DICTIONARIES")
print("=" * 60)
person = {'name': 'Alice', 'age': 25}
print(f"Original: {person}")
# Add or update
person['city'] = 'New York' # Add new key
person['age'] = 26 # Update existing key
print(f"After add/update: {person}")
# update() - Add multiple key-value pairs
person.update({'job': 'Engineer', 'company': 'Tech Co'})
print(f"After update(): {person}")
# update() with keyword arguments
person.update(salary=75000, remote=True)
print(f"After update(kwargs): {person}")
# Delete operations
del person['remote']
print(f"After del: {person}")
removed = person.pop('company')
print(f"After pop('company'): {person}, removed: {removed}")
removed = person.pop('nonexistent', 'Not Found')
print(f"pop with default: {removed}")
# popitem() - Remove and return last item
last_item = person.popitem()
print(f"After popitem(): {person}, removed: {last_item}")
# clear() - Remove all items
temp = {'a': 1, 'b': 2}
temp.clear()
print(f"After clear(): {temp}")
# =============================================================================
# SECTION 4: DICTIONARY METHODS - KEYS, VALUES, ITEMS
# =============================================================================
print("\n" + "=" * 60)
print("KEYS, VALUES, ITEMS")
print("=" * 60)
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}
print(f"Dictionary: {person}")
# keys() - Get all keys
print(f"\nkeys(): {list(person.keys())}")
# values() - Get all values
print(f"values(): {list(person.values())}")
# items() - Get all key-value pairs
print(f"items(): {list(person.items())}")
# Iterating
print(f"\nIterating:")
print(" By key:")
for key in person:
print(f" {key}: {person[key]}")
print(" By items:")
for key, value in person.items():
print(f" {key}: {value}")
# Membership test (checks keys)
print(f"\nMembership:")
print(f" 'name' in person: {'name' in person}")
print(f" 'Alice' in person: {'Alice' in person}") # False - checks keys
print(f" 'Alice' in person.values(): {'Alice' in person.values()}")
# =============================================================================
# SECTION 5: DICTIONARY COMPREHENSIONS
# =============================================================================
print("\n" + "=" * 60)
print("DICTIONARY COMPREHENSIONS")
print("=" * 60)
# Basic syntax: {key: value for item in iterable}
squares = {x: x**2 for x in range(6)}
print(f"Squares: {squares}")
# With condition
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
print(f"Even squares: {even_squares}")
# Transform existing dictionary
prices = {'apple': 0.5, 'banana': 0.3, 'orange': 0.8}
taxed = {k: round(v * 1.1, 2) for k, v in prices.items()}
print(f"\nOriginal prices: {prices}")
print(f"With 10% tax: {taxed}")
# Swap keys and values
original = {'a': 1, 'b': 2, 'c': 3}
swapped = {v: k for k, v in original.items()}
print(f"\nOriginal: {original}")
print(f"Swapped: {swapped}")
# From two lists
keys = ['name', 'age', 'city']
values = ['Alice', 25, 'NYC']
combined = {k: v for k, v in zip(keys, values)}
print(f"\nFrom two lists: {combined}")
# =============================================================================
# SECTION 6: NESTED DICTIONARIES
# =============================================================================
print("\n" + "=" * 60)
print("NESTED DICTIONARIES")
print("=" * 60)
# Dictionary of dictionaries
employees = {
'emp1': {
'name': 'Alice',
'age': 25,
'skills': ['Python', 'JavaScript']
},
'emp2': {
'name': 'Bob',
'age': 30,
'skills': ['Java', 'C++']
}
}
print(f"Nested dictionary:")
for emp_id, details in employees.items():
print(f" {emp_id}: {details}")
# Accessing nested values
print(f"\nAccessing nested values:")
print(f" employees['emp1']['name']: {employees['emp1']['name']}")
print(f" employees['emp1']['skills']: {employees['emp1']['skills']}")
# Modifying nested values
employees['emp1']['age'] = 26
employees['emp1']['skills'].append('SQL')
print(f" After modification: {employees['emp1']}")
# =============================================================================
# SECTION 7: SPECIAL DICTIONARY TYPES
# =============================================================================
print("\n" + "=" * 60)
print("SPECIAL DICTIONARY TYPES")
print("=" * 60)
# defaultdict - Returns default value for missing keys
from collections import defaultdict
# Default to 0 for counting
word_count = defaultdict(int)
text = "apple banana apple cherry banana apple"
for word in text.split():
word_count[word] += 1
print(f"DefaultDict for counting: {dict(word_count)}")
# Default to list for grouping
from collections import defaultdict
grouped = defaultdict(list)
students = [('A', 'Alice'), ('B', 'Bob'), ('A', 'Amy')]
for grade, name in students:
grouped[grade].append(name)
print(f"DefaultDict for grouping: {dict(grouped)}")
# Counter - Count occurrences
from collections import Counter
text = "mississippi"
counter = Counter(text)
print(f"\nCounter('{text}'): {counter}")
print(f" Most common(2): {counter.most_common(2)}")
# OrderedDict - Preserves insertion order
from collections import OrderedDict
ordered = OrderedDict()
ordered['first'] = 1
ordered['second'] = 2
ordered['third'] = 3
print(f"\nOrderedDict: {list(ordered.keys())}")
# Note: In Python 3.7+, regular dict maintains insertion order
# =============================================================================
# SECTION 8: MERGING DICTIONARIES
# =============================================================================
print("\n" + "=" * 60)
print("MERGING DICTIONARIES")
print("=" * 60)
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
# Python 3.9+: Using | operator
merged = dict1 | dict2
print(f"dict1 | dict2: {merged}") # dict2 values take precedence
# Python 3.9+: Using |= operator
dict1_copy = dict1.copy()
dict1_copy |= dict2
print(f"dict1 |= dict2: {dict1_copy}")
# Python 3.5+: Using ** unpacking
merged = {**dict1, **dict2}
print(f"{{**dict1, **dict2}}: {merged}")
# Using update()
merged = dict1.copy()
merged.update(dict2)
print(f"update(): {merged}")
# =============================================================================
# SECTION 9: PRACTICAL EXAMPLES
# =============================================================================
print("\n" + "=" * 60)
print("PRACTICAL EXAMPLES")
print("=" * 60)
def count_characters(text):
"""Count each character in a string."""
char_count = {}
for char in text.lower():
if char.isalpha():
char_count[char] = char_count.get(char, 0) + 1
return char_count
print("\nCharacter Counter:")
sample = "Hello, World!"
counts = count_characters(sample)
print(f" '{sample}' -> {counts}")
def group_by_length(words):
"""Group words by their length."""
groups = {}
for word in words:
length = len(word)
if length not in groups:
groups[length] = []
groups[length].append(word)
return groups
words = ['apple', 'pie', 'banana', 'cat', 'dog', 'elephant']
print(f"\nGroup by length:")
print(f" Words: {words}")
print(f" Grouped: {group_by_length(words)}")
def invert_dict(d):
"""Invert a dictionary (swap keys and values)."""
inverted = {}
for key, value in d.items():
if value not in inverted:
inverted[value] = []
inverted[value].append(key)
return inverted
original = {'a': 1, 'b': 2, 'c': 1, 'd': 2}
print(f"\nInvert dictionary:")
print(f" Original: {original}")
print(f" Inverted: {invert_dict(original)}")
def safe_nested_get(d, *keys, default=None):
"""Safely get nested dictionary values."""
for key in keys:
try:
d = d[key]
except (KeyError, TypeError):
return default
return d
nested = {'user': {'profile': {'name': 'Alice', 'age': 25}}}
print(f"\nSafe nested access:")
print(f" nested: {nested}")
print(f" get(user, profile, name): {safe_nested_get(nested, 'user', 'profile', 'name')}")
print(f" get(user, missing, key): {safe_nested_get(nested, 'user', 'missing', 'key', default='N/A')}")
# Cache/memoization example
def create_cache():
"""Create a simple function cache using a dictionary."""
cache = {}
def cached_fibonacci(n):
if n in cache:
return cache[n]
if n <= 1:
result = n
else:
result = cached_fibonacci(n - 1) + cached_fibonacci(n - 2)
cache[n] = result
return result
return cached_fibonacci
print(f"\nMemoization with dictionary:")
fib = create_cache()
print(f" fibonacci(10): {fib(10)}")
# =============================================================================
# MAIN EXECUTION
# =============================================================================
if __name__ == "__main__":
print("\n" + "=" * 60)
print("✅ You've learned about Python dictionaries!")
print("📚 Next: Learn about sets in sets.py")
print("=" * 60)