Control_Flow_and

1

Lists

▶

Lists are one of Python's most fundamental and flexible data structures. They allow you to store, access, and manipulate ordered collections of items, making them indispensable for nearly every kind of programming task.

  • Creating and Accessing Lists
  • Lists are defined with square brackets: my_list = [1, 2, 3]. This syntax groups multiple values into a single named collection that can be referenced throughout your code.
  • Elements are accessed by index starting at 0: my_list[0] returns the first element. Indexing gives you direct, efficient access to any position in the list.
  • Negative indices access elements from the end of the list. For example, my_list[-1] returns the last element, which is useful when the list length is unknown.
  • Lists can contain elements of different data types, including other lists. This flexibility allows you to build complex, nested structures when your problem requires it.
  • Modifying Lists
  • Direct index assignment (my_list[0] = 10) replaces an existing element in place. Because lists are mutable, this change affects the original list immediately.
  • append() adds a single element to the end of the list. It is the most common way to grow a list one item at a time inside a loop or conditional block.
  • remove() deletes the first occurrence of a specified value. If the value does not exist in the list, Python raises a ValueError.
  • pop() removes and returns the element at a given index, defaulting to the last element. The returned value can be stored in a variable for further use.
  • List Slicing
  • The syntax list[start:stop] returns elements from index start up to but not including stop. This gives you a concise way to extract a contiguous portion of a list.
  • An optional step value controls how many indices to skip between selected elements. For example, my_list[::2] returns every other element starting from the beginning.
  • Slicing creates a shallow copy of the selected portion, leaving the original list unchanged. Modifying the slice does not affect the source list's contents at those positions.
  • List Comprehensions
  • List comprehensions replace many for-loop-based list-building patterns with a single line of code. The general form is [expression for item in iterable], which produces a new list of transformed values.
  • An optional if clause filters which items from the iterable are included. For example, [x for x in values if x > 0] keeps only positive numbers.
  • List comprehensions improve readability and are considered idiomatic Python. They signal clearly that the goal is to produce a new list from an existing sequence.
  • Common List Operations and Methods
  • len() returns the number of elements in a list. This is frequently used to control loops or validate that a list has the expected size before processing.
  • sort() rearranges list elements in place; sorted() returns a new sorted list without modifying the original. Choose between them depending on whether preserving the original order matters.
  • count() returns how many times a specific value appears in the list. It is useful for quick frequency checks without building a separate tally structure.
  • index() returns the position of the first occurrence of a specified value. If the value is not present, it raises a ValueError, so consider checking membership with in first.
NotesLists are ordered, mutable sequences that can hold items of any type, making them one of the most versatile and widely used data structures in Python.
2

Tuples

▶

Tuples are Python's ordered, immutable sequence type. While they look similar to lists, their inability to be changed after creation makes them the right choice whenever data should remain fixed and consistent throughout a program.

  • Creating and Accessing Tuples
  • Tuples are created with parentheses: my_tuple = (1, 2, 3), or without: my_tuple = 1, 2, 3. The parentheses are optional because it is the comma that actually creates the tuple.
  • Elements are accessed by zero-based index, identical to list indexing. You can also use negative indices and slicing with tuples just as you would with lists.
  • A single-element tuple must include a trailing comma to distinguish it from a parenthesized expression. Writing my_tuple = (5,) creates a tuple, while my_tuple = (5) is simply the integer 5.
  • Immutability of Tuples
  • Attempting to assign a new value to a tuple element raises a TypeError. Once a tuple is created, its contents are locked, and no element can be replaced, added, or removed.
  • Immutability guarantees the data remains consistent throughout program execution. This makes tuples safer to pass between functions when you need assurance that the original data will not be altered.
  • Because tuples are immutable, they are hashable and can be used as dictionary keys. Lists cannot serve as dictionary keys because they are mutable and therefore not hashable.
  • Tuple Packing and Unpacking
  • Packing: coordinates = (10, 20) stores two values in one tuple. Packing lets you group related values together under a single variable name.
  • Unpacking: x, y = coordinates assigns each element to a separate variable. This is a concise and readable alternative to accessing elements by index.
  • The number of variables on the left must match the number of elements in the tuple unless a starred expression is used. A starred variable like first, *rest = my_tuple captures all remaining elements into a list.
  • Functions that return multiple values implicitly return a tuple. Writing return x, y in a function is equivalent to return (x, y), and the caller can unpack the result directly.
  • When to Use Tuples vs. Lists
  • Use a tuple when the number and meaning of elements are fixed, such as a coordinate pair (x, y) or an RGB color value (255, 128, 0). The fixed structure communicates that these values belong together in a specific order.
  • Use a list when items will be added, removed, or reordered during execution. Lists support all mutation operations that tuples intentionally forbid.
  • Tuples communicate intent to other developers that the data is not meant to change. Choosing a tuple over a list is a form of self-documenting code that signals the fixed nature of the stored values.
NotesTuples are ordered, immutable sequences that are ideal for storing fixed collections of data that should not be changed after creation.
3

Dictionaries

▶

Dictionaries store data as key-value pairs, making it possible to look up information by a meaningful name rather than a numeric position. They are one of Python's most powerful built-in structures and appear frequently in engineering and scientific code.

  • Creating and Accessing Dictionaries
  • Dictionaries are defined as: my_dict = {'key': value, ...}. Each entry pairs a unique key with an associated value that can be any Python object.
  • Values are accessed with my_dict['key']; using a missing key raises a KeyError. This direct bracket access is fast but requires that you know the key exists.
  • The get() method returns a default value instead of raising an error when a key is not found. For example, my_dict.get('missing_key', 0) returns 0 rather than crashing the program.
  • Dictionary keys must be unique; assigning to an existing key overwrites its value. If you need to track multiple values per key, store a list or another collection as the value.
  • Modifying Dictionaries
  • Assigning to a new key (my_dict['new_key'] = value) adds the entry to the dictionary. If the key already exists, the assignment replaces the current value instead.
  • Assigning to an existing key replaces its current value. Dictionaries do not raise an error or create a duplicate; the old value is silently overwritten.
  • del removes a key-value pair; pop() removes and returns the value for a specified key. Use pop() when you need to capture the removed value for further processing.
  • update() merges key-value pairs from another dictionary, overwriting duplicate keys. This is a convenient way to combine configuration data or apply a batch of changes at once.
  • Iterating Over Dictionaries
  • keys() returns a view of all keys in the dictionary. Iterating over keys() is equivalent to iterating over the dictionary directly, since the default iteration yields keys.
  • values() returns a view of all values in the dictionary. Use this when you need to process or aggregate every stored value without caring about the associated keys.
  • items() returns a view of all (key, value) pairs, suitable for unpacking in a for loop. The pattern for k, v in my_dict.items(): gives you simultaneous access to each key and its value.
  • Engineering Applications of Dictionaries
  • Dictionaries allow data to be accessed by a meaningful label rather than a numeric index. For example, storing sensor readings as {'temperature': 98.6, 'pressure': 14.7} makes the code self-explanatory.
  • They are ideal for storing configuration settings, lookup tables, and named datasets. A material properties dictionary, for instance, can map material names to their density, Young's modulus, or yield strength.
  • Using descriptive string keys makes engineering code easier to read and maintain. Another engineer reading the code can immediately understand what each value represents without consulting separate documentation.
NotesDictionaries store data as key-value pairs, enabling fast lookups by key rather than by position, and are ideal for representing structured, labeled data.
4

Sets and Choosing the Right Data Structure

▶

Sets provide a way to store collections of unique elements and perform efficient membership tests or set algebra. Understanding sets alongside lists, tuples, and dictionaries equips you to choose the right structure for any engineering problem.

  • Creating and Using Sets
  • Sets are created with curly braces: my_set = {1, 2, 3}, or with set(). You can also convert another iterable, such as a list, into a set by passing it to set().
  • Duplicate values are automatically removed; each element appears only once. This behavior makes sets a convenient tool for deduplicating a collection of values.
  • An empty set must be created with set(), not {}, which creates an empty dictionary. This is a common source of bugs for programmers new to Python.
  • Set Operations
  • Union (| or union()) returns all elements present in either set. For example, {1, 2} | {2, 3} produces {1, 2, 3}, combining both collections without duplicates.
  • Intersection (& or intersection()) returns only elements present in both sets. This is useful for finding shared items between two data sources, such as sensors active in two different tests.
  • Difference (- or difference()) returns elements in the first set not found in the second. For example, {1, 2, 3} - {2, 3} gives {1}, isolating what is unique to the first set.
  • Symmetric difference (^ or symmetric_difference()) returns elements in one set but not both. It is equivalent to the union minus the intersection and highlights items that do not overlap.
  • Membership Testing with Sets
  • The in operator tests whether an element exists in a set in constant average time. This O(1) average performance is due to the underlying hash table implementation.
  • Membership testing in a set is much faster than in a list for large collections. Testing membership in a list requires scanning each element one by one, which grows slower as the list grows larger.
  • Sets are the preferred structure when the primary operation is checking for the presence of unique items. If you find yourself building a list and then repeatedly using in to search it, a set is almost certainly the better choice.
  • Comparing Core Data Structures
  • Lists are best for ordered, changeable sequences accessed by position. Use a list when the order of items matters and elements will be added, removed, or updated over time.
  • Tuples are best for fixed records where immutability and hashability are required. Their fixed nature makes them safe to use as dictionary keys or as return values from functions.
  • Dictionaries are best for labeled data requiring fast lookup by a meaningful key. Whenever you need to associate a name or identifier with a value, a dictionary is the natural fit.
  • Sets are best for storing unique items and performing membership tests or set algebra. If duplicates are irrelevant and order does not matter, a set provides both clarity and performance.
  • Selecting the Right Structure for Engineering Problems
  • Ask whether the data needs to be ordered and accessed by position — if yes, consider a list or tuple. Choose a list if the sequence will change; choose a tuple if it is fixed and should not be modified.
  • Ask whether the data needs to be accessed by a descriptive label — if yes, use a dictionary. Named access improves readability and eliminates the need to remember which index corresponds to which value.
  • Ask whether uniqueness of elements is required or membership testing will be frequent — if yes, use a set. Sets eliminate duplicates automatically and provide the fastest possible membership checks.
  • Ask whether the data should be protected from modification — if yes, prefer a tuple over a list. Choosing a tuple signals to collaborators and future maintainers that the values are intentionally constant.
NotesSets store unique, unordered elements and support efficient membership testing and set operations. This topic also provides guidance on selecting the appropriate data structure for engineering problems.