Python for AI 104
Acknowledgement: This post is based mainly on Dr. Vinh Dinh Nguyen’s presentation and slides and partly on on TA, STA, and peers’ responses from the course AIO2025 offered by AI VIETNAM.
Relevance: The audience of this lecture were those who have read Python for AI 103, had some coding experience, and known a bit of AI knowledge. Absolute beginners are encouraged to read the material and repeatedly practice coding without AI assistance to strengthen their coding and code-reading skills. Note that only necessary Python knowledge is introduced here.
In today’s post, we’ll explore tuples, sets, and dictionaries. We’ll also discuss some applications in AI including text classification and image histogram.
Review: Data Structure and List
A data structure is a format for storing, organizing, and manipulating data efficiently. It’s similar to how your things are organized at home. For instance, if our books are all over the place, it may take forever to find one when needed. But if they are placed on the shelves in an orderly fashion, we can quickly locate what we want in a second.
Data structures fall into two main categories: built-in and user-defined. We talked about lists last time; now we’ll focus on other built-in data structures. We’ll learn more about user-defined ones and how to create them later in this Python for AI series.
A list can be one-dimensional, two-dimensional, and multi-dimensional. We talked about the first two with 2D lists being one list nesting another. We can think of these lists as a matrix or imagine them as classrooms’ desks arranged in rows and columns.
Practice Exercises
- one-dimensional
- two-dimensional
- Draw a 2d matrix.
- How are the positions of the first students in each row related to the number of students in its corresponding row?
- How are the positions of other students in each row related to the student at the beginning of that row and their column number?
Pro tip: The process of working with data is:
- have data and want to manipulate it
- analyze data to figure out the pattern(s) or what its structure is
- design corresponding algorithms
- bring these algorithms to life with code.
Mutable vs Immuatable
Objects are the fundamental building blocks of Python, representing everything we’ve learned so far and more in the language. Each object has 3 unique properties:
- Identity: the memory address of an object, like key in dictionary.
- Type: the data representation of an object like integer, string, boolean, or list.
- Value: the value assigned an object, like value in dictionary.
While the identity and type of an object are fixed once it’s created, its value(s) might be changeable. The mutability of an object’s type refers to this behavior—being able to change an object’s value without changing its identity. Think of it like this: fake food displayed at restaurants is an immutable object whereas food served to customers is a mutable object.
Note that mutability is not the same as reassignment—assigning a completely new value to an existing object.
| Mutable | Immutable | |
|---|---|---|
| Property | CAN reassign a different value to an element or add/delete an element after creation without affecting the object's identity | CANNOT reassign a different value to an element or add/delete an element after creation whatsoever
|
| Effect |
|
|
| Data structure | list, dictionary, set | string, tuple |
| Examples |
|
|
Why do we need Immutablibility?
It’s true that mutability offers flexibility, letting us modify objects in-place without taking up additional memory. Ironically, this strength is also its own weakness. Anyone can change a mutable object’s value(s) either by accident or with a bad intention like hacking.
A mutable object can pose a safety risk whereas an immutable one is more protected. Immutability helps preserve data security and data integrity, which is a critical role player in safeguarding digital information.
Tuple
tuple_name = (element_1, ..., element_n)
tuple_name = element_1, ..., element_n
(element_name_1, ..., element_name_n) = (element_1, ..., element_n)
element_name_1, ..., element_name_n = (element_1, ..., element_n)
element_name_1, ..., element_name_n = element_1, ..., element_n
You may notice that there is more than one way to define a tuple. Unlike brackets in lists, parentheses are optional for tuples. The last three options allow tuple unpacking, which will be introduced shortly. Like lists, tuples can have elements of different types.
Operators, Methods, and Built-in Functions
Except for being immutable, a tuple’s attributes are very similar to a list’s.
- A tuple is ordered.
- A tuple’s elements are accessed, retrieved, and traversed via indices.
However, due to its immutability, a tuple has way fewer operators and built-in methods than a list does. Use dir() to see them. All previously mentioned built-in functions for lists are supported in tuples.
l = list()
dir(l)
>>> ['append', 'insert', 'extend', 'pop', 'remove', 'clear', 'index', 'reverse', 'sort', 'count', 'copy']
t = tuple()
dir(t)
>>> ['count', 'index']
| Method and Function | List | Tuple |
|---|---|---|
| updating elements | ||
| slicing | ||
| $+$ and $*$ | ||
| append() | ||
| insert() | ||
| extend() | ||
| pop() | ||
| remove() | ||
| clear() | ||
| index() | ||
| reverse() | ||
| sort() | ||
| count() | ||
| copy() | ||
| len() | ||
| min() | ||
| max() | ||
| sorted() | ||
| sum() | ||
| reversed() | ||
| enumerate() | ||
| zip() |
- Notice
sorted()andreversed()are supported in tuples butsort()andreverse()are not.
Practice Exercises
sorted() and reversed() are supported in tuples but sort() and reverse() are not. Exercise 2: What is the output of the following?
def get_person():
name = 'AI'
age = 10
occupation = 'assistant'
return (name, age, occupation)
person = get_person()
person[0] = 'AGI'
print(person)
t1 = (1, 0)
print(t1)
t1 += (2,)
print(t1)
t1 = (1, 2, 3, 4, 5)
t2 = ('a', 'b', 'c')
t3 = zip(t1, t2)
for x, y in t3:
print(x, y)
t = (4, 6, 2, 1, 7, 3, -1)
sorted_t = sorted(t)
print(sorted_t)
print(t.sort())
Exercise 3: Write a function that compute a quadratic equation given three coefficients. The function should return a tuple. Convert from Tuple to List and Vice Versa
a_tuple = (3, 4, 5, 6, 7)
a_list = list(a_tuple)
a_list
>>> [3, 4, 5, 6, 7]
a_list = [3, 4, 5, 6, 7]
a_tuple = tuple(a_list)
a_tuple
>>> (3, 4, 5, 6, 7)
Tuple Unpacking
As we mentioned above, the last three ways of creating a tuple make tuple unpacking possible. Think of it like unloading goods from a vehicle—we can, in no particular order, pick them up and inspect what each item is. In the same way, tuple elements can be accessed without indices.
a, b, c = (5, 6, 7)
# test
a
>>> 5
It would be quite inconvenient and time-consuming if we had to come up with a bunch of names for these elements since not all are needed. No problem—Python lets you use _ as a placeholder for values we do not need.
a, _ , c = (5, 6, 7)
Tuple with One Element
❌ this renders an integer
| ✅ this renders a tuple
|
Swapping Function
There is no built-in function that switches positions of elements in a tuple, but we can certainly write our own function to do so. Let’s take a look.
| Without Tuple | With Tuple |
|---|---|
|
|
Practice Exercises
Exercise 2: Compare the size of a tuple and a list using the
sys package and its getSizeof()function. Provide possible reasons for the result you get. Set
set_name = {element_1, ..., element_n}
Beside this rule, a set can be created using set comprehension as follows.
a_set = {i * i for i in range(7)}
a_set
>>> {0, 1, 4, 36, 9, 16, 25}
Unlike lists and tuples, sets are:
- unindexed: no index is assigned to elements.
- unordered: elements may not be shown in the same arrangement as in creation.
- their elements are unique.
Sets are useful when element order isn’t important.
Even though sets can have elements of different types, their elements must be immutable—that is, of a unhashable type. This ensures no element duplication in a set.
Like sets in Mathematics, Python’s sets also perform common set operations like union and intersection. Not only that, sets support other methods such as adding elements. If you’re familiar with SQL or read SQL for AI 101, you might notice some similarities between SQL operations and those in Python.
| Method and Description |
|
|---|---|
copy() Create a copy |
|
add() Add an item |
|
update() Insert a set |
|
remove() Remove an element ⚠️ raise KeyError if non-existent |
|
discard() Remove an element if present NO error |
|
union() | Join two sets |
|
intersection() & Get all elements that belong to both sets |
|
difference() - Get all elements that belong to only one set
|
|
difference_update() Get all elements that belong to only one set
|
|
symmetric_difference() ^ Get all elements that belong to either set but not to both
|
|
symmetric_difference_update() Get all elements that belong to either set but not to both
|
|
Convert from Set to List or Tuple and Vice Versa
In a conversion from a list or tuple to a set, the uniqueness of elements are automatically applied.
a_tuple = (3, 4, 7, 3, 7)
a_set = set(a_tuple)
a_set
>>> {3, 4, 7}
a_list = [3, 4, 7, 3, 7]
a_set = set(a_list)
a_set
>>> {3, 4, 7}
Dictionary
dictionary_name = {key_1: value_1, ..., key_n: value_n}
Why do we need Dictionary?
As far as we know, lists, tuples, and sets have the following characteristics:
- list: mutable, indexed, ordered, duplicates allowed
- tuple: immutable, indexed, ordered, duplicates allowed
- set: mutable, unindexed, unordered, duplicates not allowed.
Each of the characteristics has its own pros and cons. Ideally, we’d something that combines possibly the best features of all. That’s where a dictionary comes in.
- key-value pairs: keys can have any meaningful name.
- mutable: you can add/delete a key-value pair and update value of some key.
- indexed: keys play an index role.
- ordered: a new element is added to the end or a given position.
- duplicates not allowed: keys are unique thus can only be of an immutable type.
Dictionary Creation
We can use below techniques individually or together to create a dictionary.
By Assigment
person = dict()
person
>>> {}
person['name'] = 'Amber'
person
>>> {'name': 'Amber'}
person['age'] = 28
person
>>> {'name': 'Amber', 'age': 28}
Dictionary Comprehension
a_dict = {str(i): i for i in range(7)}
a_dict
>>> {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6}
From zip() We can also make a dictionary by zipping two lists or sets as well.
tuple_1 = (1, 2, 3)
tuple_2 = (4, 5, 6)
a_dict = dict(zip(tuple_1, tuple_2))
type(a_dict)
>>> <class 'dict'>
a_dict
>>> {1: 4, 2: 5, 3: 6}
Built-in Methods
We can manipulate a dictionary’s items thanks to mutability.
Add/Update an element
Like we see above, a key-value pair can be added to a dictionary simply by assignment. The value of a key can be updated in the same fashion.
Additionally, the setdefault() method allows us to push a new item to the end. However, this method cannot update the value of an existing element.
| Description | By Definition | setdefault() Method |
|---|---|---|
| Add an item to the end |
|
|
| Update an item | Updated
| ⚠️ NOT updated
|
Note that an item must exist for its value to be updated; or else, KeyError is returned. Use the in keyword to check an item’s existence.
fruits = {'banana': 2, 'apple': 5}
'apple' in fruits
>>> True
'avocado' in fruits
>>> False
Make a Copy of a Dictionary
There are three types of copies in a dictionary in Python. We’ll first look at examples and compare them with each other.
person = {'name': 'Amber', 'age': 28}
# create a copy of a dictionary
copied_person = person.copy()
# check their identities
id(person) == id(copied_person)
>>> False
# check their first elements' identities
id(person['name']) == id(copied_person['name'])
>>> True
'''
copy() makes the original and the copy point to different memory addresses
but allows each corresponding pair of elements to have the same memory address.
'''
| copy() Method | deepcopy() Function | Assignment |
|---|---|---|
|
|
|
|
|
|
Get an Item
| Description | Via a Method | Others |
|---|---|---|
| Get keys | Use keys()
| Use for loop
|
| Get values | Use values()
| Read a value via key name and get() method return None if non-existent
|
| Read a value via its key name ⚠️ raise KeyError if non-existent
| ||
| Get keys and values | Use items()
|
Delete an Item
As we mentioned before, keys of a dictionary are unchangable in Python whereas the values can be modified.
To delete a value of an item, simply set it to None or an empty data structure via its key. Deleting a key deletes the item itself.
Use popitem() to remove the last item and it returns a tuple of that item’s key and value.
fruits = {'banana': 7, 'apple': 5, 'orange': 8}
# test
removed_fruit = fruits.popitem()
print(f'removed_fruit: {removed_fruit}')
print(f'fruits: {fruits}')
'''
removed_fruit: ('orange', 8)
fruits: {'banana': 7, 'apple': 5}
'''
Use clear() to delete all items.
fruits = {'banana': 7, 'apple': 5, 'orange': 8}
# test
fruits.clear()
print(f'fruits: {fruits}')
'''
fruits: {}
'''
Use pop() and del to delete a specific item only when it exists. The former returns the removed element whereas the latter returns nothing.
| pop() Method | del Method |
|---|---|
| ⚠️ raise KeyError if non-existent | |
|
|
Add/Merge Two Dictionaries
Attaching ** before each merged dictionary is essential for this operation to work. It unpacks those dictionaries before adding items to the result dictionary.
fruits = {'banana': 7, 'apple': 5, 'orange': 8}
veggie = {'okra': 10, 'squash': 1}
result = {**fruits, **veggie}
print(f'result: {result}')
'''
result = {'banana': 7, 'apple': 5, 'orange': 8, 'okra': 10, 'squash': 1}
'''
Unpacking a dictionary can help pass its items to a function as arguments, not the dictionary itself.
Practice Exercises
None value from a dictionary. Exercise 2: Write an arbitrary function that takes items of dictionaries as parameters and call the function with a dictionary as its argument.
Hints: What's important when dictionaries are merged?
Exercise 3: Does the function you wrote in exercise 2 work if a dictionary is passed as an argument? Explain why or why not.
Applications in AI
You may wonder: Where do we need these data structures in AI?
Well, to name a few examples,
- Tuple: IOU (intersection-over-union) and NMS (non-maximum suppression)
- Set: Text Embedding and Text Classification
- Dictionary: Image histogram
It’s alright if you know none of these. We’ll discuss a couple of them in a moment.
Text Classification Using Set
A Text Classification problem in Machine Learning involves categorizing texts into different groups. Some examples are checking if a comment on social media is positive or negative and checking whether an email is a spam.
For computers to understand and work with texts, we must convert them into numbers because computers can only operate on numerical data. This task contains two steps:
- text preprocessing (standardization)
- text embedding (vectorization).
On top of them, the whole process also contains inputing text samples and interacting with numerical data via layers in machine learning algorithm.
Consider a corpus—a large collection of text such as words, phrases, and sentences. For convenience, take a small corpus with two following samples:
- sample 1: ‘We are learning AI’
- sample 2: ‘AI is a trending topic’.
The practical process may entail resolving specific issues arising along the way, but we’ll cover main steps in text preprocessing and text embedding. This example shows a way to convert text to numbers.
- Clean and standardize all the text, that is, punctuations removed, lowercase, and so on.
- Build vocabulary from the corpus:
- Add words from the corpus to the vocabulary
- Can add words not in the corpus to the vocabulary
- Assign a number to each word as their’s unique identity.
- Separate each element in the corpus into a list of words.
- Encode each word of such a list into a number from the vocabulary.
You may wonder, How can I build vocabulary? Which tools should I use?
Let’s look closer.
- Our vocabulary can only have words. What can you use to convert two sentences into words? Removing punctuations.
- Both samples have ‘AI’ that cannot be repeated when added to the vocabulary. Which structure doesn’t allow repetition? Either a set or dictionary is acceptable. At this step, we only need separate words, so a set is our choice here.
- We want to assign each element a number. But a set is unordered, so it’s cumbersome to control what number is corresponding to a word. Now, we need an ordered structure. Which one is it? A list, tuple, or dictionary are all good.
- Note that if we use dictionary, we’ll have words as keys and numbers as values, so we can find an encoded number for each word.
Image Histogram Using Dictionary
Besides text problems, we have image problems as well.
In reality, there are many types of images such as binary images, gray-scale images, color images, and multispectral pictures. Each of them can be represented with image data or a matrix format.
This example is on a binary image which uses a 2D matrix. Our goal is to convert this image into a histogram. Gray-scale images can also be handled the same way since they are represented by a 2D matrix.
- Set each element of this matrix to its corresponding pixel intensity. Pixel intensity is the numerical value representing the brightness of a single pixel in an image.
- In this case, it’s either 0 or 255 since the image is binary.
- How can you input values to a 2D matrix? We talked about this!
- Convert this matrix into an abstract histogram, i.e, the distribution of pixel intensity:
- Which tool can you use to compute a sum? Yup, it’s a for loop. It’s actually nested because it’s 2D.
- Which tool can you use to keep both pixel intensity and its value and update those values as needed? Yup, it’s a dictionary.
- Draw the real histogram.
Practice Exercises
Hints:
- How do you get a value of an item given its key? You can modify it to return a default number if needed.
- You can use
matplotlib.pyplotpackage to demonstrate a histogram.
FAQ
Here are some good questions asked during class. The answers to these questions came from either some admin, TA, STA, or members of AIO2025.
| Questions | Answers |
|---|---|
| Where can I practice coding? | http://leetcode.com/ and https://www.hackerrank.com/ |
Which data structures above can I use enumerate() function with? | All of them. Set displays items randomly since it’s unordered. You need to use items() method with dictionary for both keys and values to be displayed. Iterating over a dictionary is equivalent to iterating over its keys only. |
| In text preprocessing and embedding, what if cleaning punctuations change the context meaning? | This is an area called punctuation detection in NLP. You delete only punctuations that have little to no impact in the context. |
| Would a word with different meanings assigned different numbers? | No. This situation is handled in the text embedding step. |
| How big of the vocabulary for a language is enough? | Possibly hundreds of thousands of words. |
| A resource for unpacking arguments in Python. Do lists have unpacking? | Yes. Look at https://www.geeksforgeeks.org/python/packing-and-unpacking-arguments-in-python/. |
| Can a set be sorted? | Yes, with sorted() function but not with sort() method. Their definitions are different. |
| What is a list with elements of different sizes? | https://stackoverflow.com/questions/11984386/expand-and-flatten-a-ragged-nested-list |
| Is swapping function change the identity of a tuple? | I tried and it seems unchanged for both function definitions. |
Enjoy Reading This Article?
Here are some more articles you might like to read next: