Chapter 3_Collections
I. Python Collections
Python collections are built-in container data types used to store multiple values in a single variable.
Main collection types:
- list → mutable, ordered
- tuple → immutable, ordered
- set → mutable, unordered, unique elements
- dict → mutable, ordered (Python 3.7+)
II. Lists (Mutable, Ordered, Iterable)
1. Creation:
list1 = [ ]
list2 = list()
2. Access:
2.1 Length:
len(list1)
2.2 By Index:
list1[i]
2.3 By slicing:
list1[i:j]
2.4 Membership:
val in list1
not inalso exists
2.5 Looping:
for i in list1 # method 1
for i in range(len(list1)) # method 2
while ( i < len(list1) ): # method 3
3. Modification:
3.1 Change Items:
3.1.1 Change item value:
list1[i] = new_val
3.1.2 Change range of items values:
list1[i:j] = list2
# ⚠️ If len(list2) is different from (j - i), the list size will change accordingly.
# Example:
list1 = ['a', 'b', 'c','d']
list1[0:2] = [0]
print(list1) # [0, 'c', 'd']
3.2 Add Items:
3.2.1 Insert an item to the end
list1.append(val)
3.2.2 Insert an item at a specific index
list1.insert(index, val)
3.2.3 Append elements from another iterable ( list, tuple, dict, … )
list1.extend(iterable1)
# If iterable1 is a dict, only keys are added.
3.3 Remove Items:
3.3.1 Remove an item from the end:
list1.pop()
3.3.2 Remove val first occurrence:
list1.remove(val)
3.3.3 Remove an item from a specific index:
list1.pop(index)
del list1[index]
3.3.4 Remove the entire list:
del list1
3.3.5 Clear list items:
list1.clear()
4. List Comprehension:
List comprehension offers a shorter syntax when you want to create a new list based on the values of an existing list.
newlist = [expression for item in iterable if condition] # the `if` part is optional # which is useful for filtering the iterable items. # you can also add a condition as an expression to control the outcome
#Examples:
newlist = [x for x in range(10)]
newlist = [x for x in range(10) if x < 5]
newlist = [x if x != "banana" else "orange" for x in fruits] # Expression here is a shorthand if-else
5. Sort Lists:
5.1 .sort([reverse = True], [key = keyFunc])
# key func is a function that returns a number/thing that will be used to sort the list
# Example:
list1.sort(key = str.lower) # case insensitive sort.
5.2 Reverse order:
list1.reverse()
6. Copy Lists:
6.1 .copy():
list2 = list1.copy()
6.2 list():
list2 = list(list1)
6.3 Using slicing:
list2 = list1[:]
7. Join Lists:
7.1 + Operator:
list3 = list1 + list2
7.2 .extend():
list1.extend(list2)
7.3 for loop + append():
for x in list2:
list1.append(x)
8. Other methods:
list1.index( val ) # First occurrence index
list1.count( val )
III. Tuples (Immutable, Ordered, Iterable)
Note: Tuples items are unchangeable but there is a way around it : tuple ->(convert) list -> modify list -> tuple
Tuples are immutable but can contain mutable objects.
1. Creation:
tuple1 = ('a', 'b', 'c') # multiple items
tuple2 = ('a', ) # Single item
tuple3 = ('a') # ❌ False not a tuple, type = str
2. Access:
2.1 Length:
len(tuple1)
2.2 By Index:
tuple1[i]
2.3 By slicing:
tuple1[i:j]
2.4 Membership:
val in tuple1
not inalso exists
2.5 Looping:
for i in tuple1 # method 1
for i in range(len(tuple1)) # method 2
while ( i < len(tuple1) ): # method 3
3. Modification:
3.1 Change item value
x = ('a', 'b')
l1 = list(x)
l1[0] = 0
x = tuple(l1)
3.2 Add items:
x = ('a','b')
l1 = list(x)
l1.append('c')
x = tuple(l1)
3.3 Add tuple to an existing tuple
x = ('a', 'b')
y = ('c', 'd')
z = x + y # creates another object
3.4 Remove items:
x = ('a', 'b')
l1 = list(x)
l1.remove('a')
x = tuple(l1)
3.5 Delete tuple:
del thisTuple
4. Unpacking
Using Asterisk
*
a, *b, c = [1, 2, 3, 4]
print(a, b, c) # 1 [2, 3] 4
5. Join, multiply tuples
tuple3 = tuple1 + tuple2 # join tuples
tuple4 = tuple1 * 3 # repeat items
6. Other methods:
tuple1.count(val)
tuple1.index(val)
IV. Sets (Mutable, Unordered, Iterable)
Note Sets items should be immutable tuples containing mutable objects are NOT allowed inside sets.
# 1 is considered as True, same thing for 0 for sets {1, True} # only one element {0, False} # only one element
1. Creation:
set1 = {'a', 'b', 'c'}
set2 = set(('a', 'b', 'c'))
2. Access:
Note set items can’t be accessed by index/value nor slicing. but it can be accessed using a for loop
2.1 For loop:
# this is the only way to access and to loop through a set.
for x in set1:
print(x)
2.2 Membership:
val in set1
not inalso exists
3. Modification:
3.1 add item:
set1.add(val)
3.2 add items from another iterable:
set1.update( iterable1 )
3.3 Remove item:
set1.remove(val) # if the val doesn't exist it raises an error
set1.discard(val) # safe option for .remove()
set1.pop() # remove a random val because sets are unordered.
3.4 Clear set:
set1.clear()
4. Join Sets:
4.1 UNION:
set3 = set1.union(set2)
set3 = set1 | set2
set1.update( set2 ) # modifty set1
4.2 INTERSECT:
set3 = set1.intersection(set2)
set3 = set1 & set2
set1.intersection_update(set2)
4.3 DIFFERENCE:
set3 = set1.difference(set2)
set3 = set1 - set2
set1.difference_update(set2)
# Symeteric difference: keep elements, that are not present in both sets
set3 = set1.symmetric_difference(set2)
set1.symmetric_difference_update(set2)
5. FrozenSet (Immutable version of sets)
5.1 Creation:
x = frozenset({'a', 'b'})
5.2 Methods:
# return NEW frozensets
x.copy() # returns the same object because frozenSets are immutable.
x.union(other)
x.intersection(other)
x.difference(other)
x.symmetric_difference(other)
# return booleans
x.issubset(other)
x.issuperset(other)
x.isdisjoint(other)
V. Dicts (Mutable, Ordered, Iterable)
1. Creation:
Note
- dict keys : immutables
- Dictionaries preserve insertion order since Python 3.7+
dict1 = {k0:v0, k1:v1, ...}
dict2 = dict( k0 = v0, k1 = v1)
2. Access:
2.1 Length:
len(dict1)
2.2 By key:
dict1[key1]
2.3 By .get():
dict1.get(key1)
dict1.get(key1, default) # Custom default value
2.4 get keys:
keys = dict1.keys() # returns a dict_keys view (iterable, not a list)
2.5 get values:
values = dict1.values() # returns a dict_values view
2.6 get elements as list of tuples: [(k0,v0), (k1,v1), ... ] (as a view, not a list)
dict1.items()
Note: Views are updated automaticaly
2.7 Membership:
key1 in dict1 # checks keys only, not values
not inalso exists
2.8 Looping:
for k,v in dict1.items() # method 1
for k in dict1.keys() # method 2
# or
for k in dict1 # method 2'
for v in dict1.values() #method 3
3. Modification:
3.1 Change/add items:
dict1[ key1 ] = val
dict1.update({key1 : val}) # Can update multiple keys at once
# For both methods:
# Add the item if key1 does not exist.
# Update the value if key1 already exists
3.2 Remove items:
dict1.pop( key1 ) # Remove item by key
dict1.popitem() # removes the last inserted item
del dict1[ key1 ]
del dict1 # Delete entire dict
dict1.clear()
4. Copy a Dictionary:
dict2 = dict1.copy()
dict2 = dict(dict1)
Note
there is also what so called nested dictionaries
example: { “user1”:{ “name”:“achraf”, “lastName”:“SL” }, … }
dict1[“user1”][“name”]
5. Dictionary comprehension:
{key_expr: value_expr for item in iterable [if condition]}
6. Dictionary Methods:
dict1 = dict.fromkeys(keys, only_one_value) # Returns a dictionary with the specified keys and value
# if `only_one_value` is not specified it becomes None
value = dict1.setdefault(key, val) # Returns the value of the specified key. If the key does not exist: insert the key, with the specified value and return it.
Note
dict.fromkeys()ifonly_one_valueis mutabled = dict.fromkeys(['a', 'b'], []) d['a'].append(1) print(d) # {'a': [1], 'b': [1]}