Sets Data Structure in Python

What is a Set?

You've learned List, Tuple, and Dictionary. Set is the last data structure.

A set is a collection that has two special properties:

  • No duplicate values — every item is unique
  • No order — items have no index, no position


    my_set = {1, 2, 3, 4, 5}
    print(my_set)    # {1, 2, 3, 4, 5}

Looks similar to dictionary but no key-value pairs — just values.


The Killer Feature — No Duplicates


    numbers = {1, 2, 3, 2, 4, 1, 5, 3}
    print(numbers)    # {1, 2, 3, 4, 5} — duplicates automatically removed

This is the main reason sets exist. When you need unique values — use a set.


Creating a Set


    # Direct creation
    fruits = {"apple", "banana", "mango", "apple", "banana"}
    print(fruits)    # {'apple', 'banana', 'mango'} — duplicates gone

    # Convert list to set — very common use case
    marks_list = [85, 90, 85, 78, 90, 92, 78]
    marks_set = set(marks_list)
    print(marks_set)    # {85, 90, 78, 92} — unique marks only

    # Empty set — must use set(), not {}
    empty = set()       # correct
    empty = {}          # WRONG — this creates empty dictionary


No Index — Cannot Access by Position


    fruits = {"apple", "banana", "mango"}

    print(fruits[0])    # ERROR! sets don't support indexing

Sets have no order so there's no first or second item. You either loop through all items or check if something exists.


Checking Membership


    fruits = {"apple", "banana", "mango"}

    print("apple" in fruits)      # True
    print("grapes" in fruits)     # False

    if "mango" in fruits:
        print("Mango is available!")

Checking membership in a set is faster than in a list — especially with large data. This is one more reason to use sets when you only need to check existence.


Adding and Removing Items


    fruits = {"apple", "banana", "mango"}

    fruits.add("orange")          # add one item
    print(fruits)

    fruits.add("apple")           # adding duplicate — nothing happens
    print(fruits)                 # still same, no error

    fruits.remove("banana")       # remove — gives error if not found
    print(fruits)

    fruits.discard("grapes")      # remove — NO error if not found
    print(fruits)

Output:

{'apple', 'banana', 'mango', 'orange'}
{'apple', 'banana', 'mango', 'orange'}
{'apple', 'mango', 'orange'}
{'apple', 'mango', 'orange'}

Always prefer .discard() over .remove() unless you specifically want an error when item is missing.


Looping Through a Set


    fruits = {"apple", "banana", "mango"}

    for fruit in fruits:
        print(fruit)

Works same as list but order is not guaranteed — items may print in any order every time you run.


Set Operations — The Real Power

Sets support mathematical set operations. These are extremely useful:

Union — All items from both sets


    set1 = {1, 2, 3, 4}
    set2 = {3, 4, 5, 6}

    union = set1 | set2
    print(union)    # {1, 2, 3, 4, 5, 6} — all items, no duplicates


Intersection — Only items present in BOTH sets


    set1 = {1, 2, 3, 4}
    set2 = {3, 4, 5, 6}

    common = set1 & set2
    print(common)    # {3, 4} — only items in both


Difference — Items in first set but NOT in second


    set1 = {1, 2, 3, 4}
    set2 = {3, 4, 5, 6}

    diff = set1 - set2
    print(diff)    # {1, 2} — in set1 but not in set2

    diff2 = set2 - set1
    print(diff2)   # {5, 6} — in set2 but not in set1


Real World Use of Set Operations


    students_python = {"Rahul", "Priya", "Gagan", "Amit"}
    students_java = {"Priya", "Amit", "Ravi", "Neha"}

    # Who is enrolled in both courses?
    both = students_python & students_java
    print(f"Both courses: {both}")        # {'Priya', 'Amit'}

    # Who is enrolled in at least one course?
    any_course = students_python | students_java
    print(f"Any course: {any_course}")    # {'Rahul', 'Priya', 'Gagan', 'Amit', 'Ravi', 'Neha'}

    # Who is in Python but NOT Java?
    only_python = students_python - students_java
    print(f"Only Python: {only_python}")  # {'Rahul', 'Gagan'}


Most Common Use Case — Remove Duplicates from List

In real projects this is the most frequent reason to use a set:


    # User entered tags with duplicates
    tags = ["python", "coding", "python", "beginner", "coding", "python"]
    print(f"Original: {tags}")

    # Remove duplicates
    unique_tags = list(set(tags))
    print(f"Unique: {unique_tags}")

Output:

Original: ['python', 'coding', 'python', 'beginner', 'coding', 'python']
Unique: ['beginner', 'python', 'coding']

Convert to set to remove duplicates, convert back to list if you need indexing.


All Four Data Structures — Final Comparison


    # List — ordered, changeable, allows duplicates
    my_list = [1, 2, 3, 2, 1]

    # Tuple — ordered, unchangeable, allows duplicates  
    my_tuple = (1, 2, 3, 2, 1)

    # Set — unordered, changeable, NO duplicates
    my_set = {1, 2, 3, 2, 1}       # becomes {1, 2, 3}

    # Dictionary — key-value pairs, changeable, keys unique
    my_dict = {"name": "Gagan", "age": 22}


List

Tuple

Set

Dictionary

Ordered

Yes

Yes

No

Yes (Python 3.7+)

Duplicates

Yes

Yes

No

Keys: No, Values: Yes

Changeable

Yes

No

Yes

Yes

Access by

Index

Index

Key

Syntax

[]

()

{}

{key: val}



Quick Decision Guide

Need to store data that won't change?         → Tuple
Need unique values only?                      → Set
Need to look up data by a name/label?         → Dictionary
Everything else (ordered, changeable list)?   → List

Exercise 🏋️

Solve these three small problems using sets:

Problem 1 — Remove Duplicates


    visitor_log = [101, 203, 101, 305, 203, 101, 407, 305]

Find how many unique visitors came. Print the unique visitor IDs.

Problem 2 — Common Friends


    friends_a = {"Rahul", "Priya", "Gagan", "Amit", "Neha"}
    friends_b = {"Priya", "Ravi", "Gagan", "Kiran", "Amit"}

Find:

  • Friends common to both A and B
  • Friends only A has (not B)
  • All unique friends combined

Problem 3 — Membership Check

Ask user to enter a username. Check if it exists in this set of registered users and print appropriate message:


    registered_users = {"gagan", "rahul", "priya", "amit", "neha"}


Tuples & Dictionaries in Python

Part 1 — Tuples

What is a Tuple?

A tuple is exactly like a list — it stores multiple values. But with one big difference:

Lists are mutable — you can change them after creation Tuples are immutable — once created, you cannot change them


    # List — can be changed
    fruits_list = ["apple", "banana", "mango"]

    # Tuple — cannot be changed
    fruits_tuple = ("apple", "banana", "mango")

Only difference in syntax — list uses [], tuple uses ().


Creating a Tuple


    coordinates = (28.6, 77.2)           # latitude, longitude
    rgb = (255, 0, 128)                  # color values
    days = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
    person = ("Gagan", 22, "Delhi")      # mixed types

    # Single item tuple — needs a trailing comma
    single = (42,)        # this is a tuple
    not_tuple = (42)      # this is just a number in brackets — NOT a tuple


Accessing Items — Same as List


    person = ("Gagan", 22, "Delhi")

    print(person[0])     # Gagan
    print(person[1])     # 22
    print(person[-1])    # Delhi — negative indexing works too

Slicing works too:


    days = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")

    print(days[0:5])     # ('Mon', 'Tue', 'Wed', 'Thu', 'Fri')
    print(days[-2:])     # ('Sat', 'Sun')


Tuples are Immutable — Cannot Change


    colors = ("red", "green", "blue")

    colors[0] = "yellow"    # ERROR! TypeError: tuple does not support item assignment

Once a tuple is created, its values are locked. No adding, removing, or changing.


Why Use Tuple If You Can't Change It?

Great question. Here's why tuples exist:

1. Safety — When data should never change, use a tuple. Like days of the week, months of the year, coordinates of a fixed location. Using a tuple signals to anyone reading your code "this data is not supposed to change."

2. Speed — Tuples are slightly faster than lists because Python knows they won't change.

3. Dictionary keys — Tuples can be used as dictionary keys, lists cannot. (We'll see this soon.)

Real world examples of tuple data:


    months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

    directions = ("North", "South", "East", "West")

    status_codes = (200, 301, 404, 500)

These values will never change — tuple is perfect.


Tuple Methods

Tuples have only 2 methods (because you can't modify them):


    numbers = (1, 2, 3, 2, 4, 2, 5)

    print(numbers.count(2))      # 3 — how many times 2 appears
    print(numbers.index(4))      # 4 — index of value 4
    print(len(numbers))          # 7 — total items


Tuple Unpacking — Very Useful

You can unpack tuple values directly into variables:


    person = ("Gagan", 22, "Delhi")

    name, age, city = person       # unpacking

    print(name)    # Gagan
    print(age)     # 22
    print(city)    # Delhi

This works with lists too. You've seen a version of this before with enumerate().

Looping Through Tuple


    days = ("Mon", "Tue", "Wed", "Thu", "Fri")

    for day in days:
        print(day)

Exactly same as looping through a list.


Part 2 — Dictionaries

What is a Dictionary?

A list stores items by index number — 0, 1, 2, 3...

A dictionary stores items by custom keys — like a real dictionary where you look up words.


    # List — access by number
    person_list = ["Gagan", 22, "Delhi"]
    print(person_list[0])    # Gagan — but what does index 0 mean?

    # Dictionary — access by name
    person_dict = {"name": "Gagan", "age": 22, "city": "Delhi"}
    print(person_dict["name"])    # Gagan — clear and readable!

Dictionary is made of key-value pairs:

  • "name" is the key
  • "Gagan" is the value

Creating a Dictionary


    student = {
        "name": "Gagan",
        "age": 22,
        "city": "Delhi",
        "is_student": True,
        "marks": 88.5
    }

    print(student)

Output:

{'name': 'Gagan', 'age': 22, 'city': 'Delhi', 'is_student': True, 'marks': 88.5}

Accessing Values


    student = {
        "name": "Gagan",
        "age": 22,
        "city": "Delhi"
    }

    print(student["name"])     # Gagan
    print(student["age"])      # 22
    print(student["city"])     # Delhi

If key doesn't exist — you get a KeyError:


    print(student["phone"])    # KeyError: 'phone'

Safe way using .get() — returns None instead of error:


    print(student.get("phone"))           # None — no error
    print(student.get("phone", "N/A"))    # N/A — custom default value

Always prefer .get() when you're not sure if the key exists.


Adding and Updating Values


    student = {"name": "Gagan", "age": 22}

    # Adding new key
    student["city"] = "Delhi"
    student["marks"] = 88.5

    # Updating existing key
    student["age"] = 23

    print(student)

Output:

{'name': 'Gagan', 'age': 23, 'city': 'Delhi', 'marks': 88.5}

Removing Items


    student = {"name": "Gagan", "age": 22, "city": "Delhi", "marks": 88.5}

    del student["marks"]              # delete by key
    print(student)

    removed = student.pop("city")     # remove and return value
    print(removed)                    # Delhi
    print(student)

Output:

{'name': 'Gagan', 'age': 22, 'city': 'Delhi'}
Delhi
{'name': 'Gagan', 'age': 22}

Dictionary Methods


    student = {"name": "Gagan", "age": 22, "city": "Delhi"}

    print(student.keys())      # dict_keys(['name', 'age', 'city'])
    print(student.values())    # dict_values(['Gagan', 22, 'Delhi'])
    print(student.items())     # dict_items([('name', 'Gagan'), ('age', 22), ('city', 'Delhi')])

    print(len(student))        # 3 — number of key-value pairs
    print("name" in student)   # True — check if key exists


Looping Through a Dictionary


    student = {"name": "Gagan", "age": 22, "city": "Delhi"}

    # Loop through keys only
    for key in student:
        print(key)

    # Loop through keys and values together — most common
    for key, value in student.items():
        print(f"{key}: {value}")

Output:

name: Gagan
age: 22
city: Delhi

Dictionary Inside a List — Very Common Pattern

This is how real-world data looks — a list of dictionaries:


    students = [
        {"name": "Rahul", "age": 20, "marks": 85},
        {"name": "Priya", "age": 21, "marks": 92},
        {"name": "Gagan", "age": 22, "marks": 78}
    ]

    # Access individual student
    print(students[0]["name"])     # Rahul
    print(students[1]["marks"])    # 92

    # Loop through all students
    for student in students:
        print(f"Name: {student['name']}, Marks: {student['marks']}")

Output:

Name: Rahul, Marks: 85
Name: Priya, Marks: 92
Name: Gagan, Marks: 78

This pattern is everywhere in real apps — when you fetch data from a database or API, it usually comes back in this format.


Nested Dictionary — Dictionary Inside Dictionary


    company = {
        "name": "TechCorp",
        "location": "Delhi",
        "ceo": {
            "name": "Amit Shah",
            "age": 45,
            "email": "amit@techcorp.com"
        }
    }

    print(company["name"])                    # TechCorp
    print(company["ceo"]["name"])             # Amit Shah
    print(company["ceo"]["email"])            # amit@techcorp.com


Real World Example — Contact Book


    contacts = {}

    def add_contact():
        name = input("Enter name: ")
        phone = input("Enter phone: ")
        email = input("Enter email: ")
        contacts[name] = {"phone": phone, "email": email}
        print(f"{name} added to contacts!")

    def view_contacts():
        if len(contacts) == 0:
            print("No contacts saved")
        else:
            print("\n=== All Contacts ===")
            for name, info in contacts.items():
                print(f"Name: {name}")
                print(f"  Phone: {info['phone']}")
                print(f"  Email: {info['email']}")
                print()

    def search_contact():
        name = input("Enter name to search: ")
        if name in contacts:
            info = contacts[name]
            print(f"\nName: {name}")
            print(f"Phone: {info['phone']}")
            print(f"Email: {info['email']}")
        else:
            print("Contact not found")

    def delete_contact():
        name = input("Enter name to delete: ")
        if name in contacts:
            del contacts[name]
            print(f"{name} deleted!")
        else:
            print("Contact not found")

    while True:
        print("\n=== Contact Book ===")
        print("1. Add contact")
        print("2. View all contacts")
        print("3. Search contact")
        print("4. Delete contact")
        print("5. Exit")

        choice = input("Enter choice: ")

        if choice == "1":
            add_contact()
        elif choice == "2":
            view_contacts()
        elif choice == "3":
            search_contact()
        elif choice == "4":
            delete_contact()
        elif choice == "5":
            print("Goodbye!")
            break
        else:
            print("Invalid choice")

This is a proper mini application — using dictionaries, lists, functions, loops, and conditions all together.


List vs Tuple vs Dictionary — When to Use What

List

Tuple

Dictionary

Syntax

[]

()

{}

Can change?

Yes

No

Yes

Access by

Index number

Index number

Key name

Use when

Order matters, data changes

Data is fixed

Key-value pairs, lookup by name

Example

Shopping cart, student marks

Coordinates, RGB colors, months

User profile, contact info

 








Exercise 🏋️

Build a Simple Inventory System:

  1. Start with this inventory already in a dictionary:
inventory = {
    "apple": {"price": 20, "quantity": 50},
    "banana": {"price": 10, "quantity": 100},
    "mango": {"price": 40, "quantity": 30}
}
  1. Build a menu with these options:
    • View all items (show name, price, quantity)
    • Add new item (ask name, price, quantity)
    • Update quantity of existing item
    • Remove item
    • Exit

Expected view output:

=== Inventory ===
apple  - Price: Rs.20, Quantity: 50
banana - Price: Rs.10, Quantity: 100
mango  - Price: Rs.40, Quantity: 30

This exercise combines lists, dictionaries, functions, loops, and conditions — basically everything from Stage 1 to Stage 4!


Error Handling in Python

Try / Except Why Error Handling? Run this program:     num = int ( input ( " Enter a number: " ))     print ( f "Double i...