Definition of iterable and sequence objects
What is an iterable object?
An object capable of returning its members one at a time.
Examples of iterables
– all sequence types (such as list, str, and tuple)
– some non-sequence types like dict, file objects
– objects of any classes you define with an __iter__()
method or with a __getitem__()
method that implements sequence semantics.
What is a sequence object?
An iterable
which supports efficient element access using integer indices via the __getitem__()
special method and defines a __len__()
method that returns the length of the sequence.
Examples of sequences:
– Some built-in sequence types are list, str, tuple, and bytes.
beware: dict implements the 2 functions but is considered a mapping rather than a sequence.
Sequences
Common types
There are 4 basic sequence types: lists, tuples, str and range objects.
Additional sequence types tailored for processing of binary data and text strings are described in dedicated sections.
Command sequence operations
–__getitem__()
: efficient element access using integer indices
– __len__()
: method that returns the length of the sequence.
The collections.abc.Sequence abstract base class defines a much richer interface that goes beyond just __getitem__()
and __len__()
,
adding count(), index(), __contains__(), and __reversed__()
.
Common functions to sequences :
x in s
: True if an item of s is equal to x, else False
x not in s
: False if an item of s is equal to x, else True
s + t
: concatenation of s and t
s * n or n * s
: equivalent to adding s to itself n times
s[i]
: ith item of s, origin 0
s[i:j]
: slice of s from i to j
s[i:j:k]
: slice of s from i to j with step k
len(s)
: length of s
min(s)
: smallest item of s
max(s)
: largest item of s
s.index(x[, i[, j]])
: index of the first occurrence of x in s (at or after index i and before index j)
s.count(x)
: total number of occurrences of x in s
concrete example of basic functions of sequences
string example:
def test_string_sequence_functions(self): foo: str = 'I am a good person' # in self.assertTrue('am' in foo) # not in self.assertTrue('Am' not in foo) # + self.assertEqual('I am a good person and you?', foo + ' and you?') # * self.assertEqual('I am a good personI am a good personI am a good person', foo * 3) # access by index self.assertEqual('I', foo[0]) self.assertEqual('g', foo[7]) self.assertEqual('o', foo[8]) self.assertEqual('o', foo[9]) # access form the last elements self.assertEqual('n', foo[-1]) self.assertEqual('o', foo[-2]) # slice self.assertEqual('am', foo[2:4]) self.assertEqual('I am a good ', foo[:12]) self.assertEqual('person', foo[12:]) # length self.assertEqual(18, len(foo)) # min and max self.assertEqual(' ', min(foo)) self.assertEqual('s', max(foo)) # index of the first occurrence of x in s self.assertEqual(2, foo.index('a')) # index of the first occurrence of x in s by starting by the index 3 self.assertEqual(5, foo.index('a', 3)) # total number of occurrences of x in s self.assertEqual(1, foo.count('I')) self.assertEqual(3, foo.count('o')) self.assertEqual(0, foo.count('z')) |
list example:
def test_list_sequence_functions(self): foo: List[int] = [1, 5, 10, 5, 5, 0] # in self.assertTrue(1 in foo) self.assertTrue(5 in foo) # not in self.assertTrue(2 not in foo) # + self.assertEqual([1, 5, 10, 5, 5, 0, 9, 88], foo + [9, 88]) # * self.assertEqual([1, 5, 10, 5, 5, 0, 1, 5, 10, 5, 5, 0], foo * 2) # access by index self.assertEqual(1, foo[0]) self.assertEqual(5, foo[1]) self.assertEqual(10, foo[2]) # access form the last elements self.assertEqual(0, foo[-1]) self.assertEqual(5, foo[-2]) # slice self.assertEqual([10, 5], foo[2:4]) self.assertEqual([1, 5, 10, 5], foo[:4]) self.assertEqual([10, 5, 5, 0], foo[2:]) # length self.assertEqual(6, len(foo)) # min and max self.assertEqual(0, min(foo)) self.assertEqual(10, max(foo)) # index of the first occurrence of x in s self.assertEqual(1, foo.index(5)) # index of the first occurrence of x in s by starting by the index 3 self.assertEqual(3, foo.index(5, 2)) # total number of occurrences of x in s self.assertEqual(1, foo.count(1)) self.assertEqual(3, foo.count(5)) self.assertEqual(0, foo.count(9)) |
tuple basic example:
def test_tuple_sequence_functions(self): foo: tuple[int, str, str] = (1, 'David', 'Doe') # in self.assertTrue(1 in foo) self.assertTrue('David' in foo) self.assertTrue('Doe' in foo) # not in self.assertTrue(2 not in foo) # + self.assertEqual((1, 'David', 'Doe', 'lion', 'tiger'), foo + ('lion', 'tiger')) # * self.assertEqual((1, 'David', 'Doe', 1, 'David', 'Doe'), foo * 2) # access by index self.assertEqual(1, foo[0]) self.assertEqual('David', foo[1]) self.assertEqual('Doe', foo[2]) # access form the last elements self.assertEqual('Doe', foo[-1]) self.assertEqual('David', foo[-2]) # slice self.assertEqual((1, 'David'), foo[0:2]) self.assertEqual((1, 'David', 'Doe'), foo[:3]) self.assertEqual(('David', 'Doe'), foo[1:]) # length self.assertEqual(3, len(foo)) # min and max # the aggregate function minimum and maximum cannot work with different types # self.assertEqual(0, min(foo)) # self.assertEqual(10, max(foo)) # index of the first occurrence of x in s self.assertEqual(1, foo.index('David')) # index of the first occurrence of x in s by starting by the index 3 self.assertEqual(1, foo.index('David', 1)) # total number of occurrences of x in s self.assertEqual(1, foo.count(1)) self.assertEqual(1, foo.count('Doe')) self.assertEqual(0, foo.count(9)) |
tuple imutability example
from typing import Tuple class Foo: def __init__(self, text) -> None: self.text = text def __repr__(self) -> str: return f'Foo: text={self.text}' foo_hello = Foo('hello') foo_boy = Foo('boy') t: Tuple[Foo, Foo] = (foo_hello, foo_boy) print(f'id={id(t)}, t={t}') # id=3055929302144, t=(Foo: text=hello, Foo: text=boy) foo_boy.text = 'girl' print(f'id={id(t)}, t={t}') # id=3055929302144, t=(Foo: text=hello, Foo: text=girl) t += t print(f'id={id(t)}, t={t}') # id=3055928752896, t=(Foo: text=hello, Foo: text=girl, Foo: text=hello, Foo: text=girl) |
Output:
id=2052380007168, t=(Foo: text=hello, Foo: text=boy) id=2052380007168, t=(Foo: text=hello, Foo: text=girl) id=2052379458144, t=(Foo: text=hello, Foo: text=girl, Foo: text=hello, Foo: text=girl) |
list() and set() built-in functions
Overview
These two functions have a close behavior:
– They create a list object or a set object.
– Two ways to use them: either we provide no parameter to create an empty collection or we specify an iterable as parameter and it creates a collection with elements contained in the iterable parameter.
Examples
from typing import List from typing import Set l: List[str] = list('gin') print(f'l={l}') # l=['g', 'i', 'n'] s: Set[str] = set('gin') print(f's={s}') # s={'n', 'i', 'g'} s: Set[str] = set(['gin', 'john', 'gin']) print(f's={s}') # s={'john', 'gin'} l: List[str] = list({'gin', 'john'}) print(f'l={l}') # l=['john', 'gin'] s: Set[str] = {'gin', 'john'} print(f's={s}') # s={'john', 'gin'} s: Set[str] = {'gin', 'john', 'gin'} print(f's={s}') # s={'john', 'gin'} s: Set[str] = set() s.add('gin') print(f's={s}') # s={'gin'} l: List[str] = list() l.append('gin') print(f'l={l}') # l=['gin'] |
Dictionary
What is it ?
Very close of a Map (in Java/C# for example), a dictionary is a set of key:value elements, whereb keys are unique.
Initialize a dictionary
# empty dic empty_dic = {} # dic with st key and number value dic = {'jack': 1234, 'john': 4567} # dic with number key and str value dic = {1234: 'jack', 4567: 'john'} # dic with number key and list value dic = {1234: ['jack', 'jackie'], 4567: ['john', 'johnny']} |
Basic operations on dictionary
– get value for a key
– query key contained in
– query key not contained in
– add or update an element
– delete an element
– get list of keys, sorted by insertion order
– get list of keys, sorted asc
pleasures_by_food = { 'potatoes': 'very good', 'chicken': 'good', } # get value for 'potatoes' key print('potatoes pleasure = ', pleasures_by_food['potatoes']) # query key contained in print('does it contain chicken ?', 'chicken' in pleasures_by_food) # query key not contained in print('does it not contain chicken ?', 'chicken' not in pleasures_by_food) # add the cheese element pleasures_by_food['cheese'] = 'interesting' # update the potatoes element print('update the potatoes element') pleasures_by_food['potatoes'] = 'not bad' print(f'pleasures_by_food={pleasures_by_food}') # del the cheese element print('Remove cheese key') # del pleasures_by_food['cheese'] # alternative to delete pop = pleasures_by_food.pop('cheese') print(f'pop={pop}') # alternative to delete with default value if key does not exist pop = pleasures_by_food.pop('cheese', 'unknown') print(f'pop={pop}') # get a list of keys sorted by insertion order print(list(pleasures_by_food)) # get a list of keys sorted by ascending order print('Sort dictionary') print(sorted(pleasures_by_food) |
Merging collections
Merging dictionaries
Updating an existing dictionary
update(other)
Update the dictionary with the key/value pairs from other, overwriting existing keys.
Return None.
update()
accepts either another dictionary object or an iterable of key/value pairs (as tuples or other iterables of length two).
New in version 3.9 (|
As union operator):
d |= other
Update the dictionary d
with keys and values from other,
which may be either a mapping or an iterable of key/value
pairs. The values of other take priority when d
and other
share keys.
Creating a new dictionary
New in version 3.9 (|
As union operator):
d | other
:
Create a new dictionary with the merged keys and values of d
and other
, which must both be dictionaries. The
values of other
take priority when d
and other
share keys.
Examples
knights = { 'gallahad': 'the pure', 'robin': 'the brave', 'nobody': 'knights' } queens = { 'diana': 'the love', 'helena': 'the mother', 'nobody': 'queen' } # Creating a new dictionary print('\nCreating a new dictionary') knights_queens_new_object = knights | queens print(f'id(knights)={id(knights)}') print(f'id(queens)={id(queens)}') print(f'id(knights_queens_new_object)={id(knights_queens_new_object)}') print(f'knights_queens_new_object={knights_queens_new_object}') # updating a dictionary special_queens = { 'super': 'woman', 'special': 'mommy', } print('\nUpdating a dictionary') knights.update(special_queens) print(f'id(knights)={id(knights)}') print(f'id(special_queens)={id(special_queens)}') print(f'knights={knights}' |
Output:
Creating a new dictionary id(knights)=140652742766976 id(queens)=140652742767168 id(knights_queens_new_object)=140652742767232 knights_queens_new_object={'gallahad': 'the pure', 'robin': 'the brave', 'nobody': 'queen', 'diana': 'the love', 'helena': 'the mother'} Updating a dictionary id(knights)=140652742766976 id(special_queens)=140652741891328 knights={'gallahad': 'the pure', 'robin': 'the brave', 'nobody': 'knights', 'super': 'woman', 'special': 'mommy'} |
Merging lists
Updating an existing list
list.extend(iterable)
Extend the list by appending all the items from the iterable.
Equivalent to a[len(a):] = iterable
.
As alternative, we can also use the +=
operator.
Creating a new list
We use the +
operator.
Examples:
first_array = [1, 3, 5] second_array = [6, 3, 8] # Creating a new list print('\nCreating a new list') first_array_second_array_new_object = first_array + second_array print(f'id(first_array)={id(first_array)}') print(f'id(second_array)={id(second_array)}') print(f'id(first_array_second_array_new_object)={id(first_array_second_array_new_object)}') print(f'first_array_second_array_new_object={first_array_second_array_new_object}') # updating a list special_second_array = [1, 3, 6] print('\nUpdating a list') first_array.extend(special_second_array) # alternative # first_array+=special_second_array print(f'id(first_array)={id(first_array)}') print(f'id(special_second_array)={id(special_second_array)}') print(f'first_array={first_array}' |
Output:
Creating a new list id(first_array)=139647775655744 id(second_array)=139647775683648 id(first_array_second_array_new_object)=139647775702400 first_array_second_array_new_object=[1, 3, 5, 6, 3, 8] Updating a list id(first_array)=139647775655744 id(special_second_array)=139647775702464 first_array=[1, 3, 5, 1, 3, 6] |