Data Structures and Program ControlIntroductionBusiness analytics depends not only on statistical methods but also on the ability to represent, inspect, transform, and validate data. Python provides built-in data structures and control statements that allow analysts to move from raw records to reliable business information. A sales report, for example, may contain customer names as strings, transaction amounts in lists, product categories in sets, and customer profiles in dictionaries. Conditional logic and iteration then make it possible to classify transactions, calculate totals, detect exceptions, and automate routine decisions. This chapter develops the essential Python structures and control mechanisms required for business analytics. The emphasis is on meaning, appropriate selection, readable implementation, and responsible use rather than memorizing syntax. Learning ObjectivesBy the end of this chapter, you should be able to: - distinguish among strings, lists, tuples, sets, and dictionaries;
- use indexing and slicing to access structured data;
- construct useful data collections with comprehensions;
- apply conditional logic to business rules;
- use iteration to process records and produce summaries;
- handle common errors with exceptions;
- select appropriate structures for practical analytics tasks; and
- identify data-quality, governance, and ethical risks in automated processing.
1. Data Structures as Models of Business InformationA data structure is an organized way of storing values so that a program can access and manipulate them. The choice of structure communicates assumptions about the data. A sequence suggests order; a set emphasizes uniqueness; a dictionary represents relationships between keys and values. Python is dynamically typed, so a variable can refer to different kinds of objects during execution. Nevertheless, analysts should maintain conceptual discipline. A transaction amount should not be silently mixed with a customer identifier, and a missing value should not automatically be treated as zero. 1.1 StringsA string is an ordered, immutable sequence of characters. Strings are used for names, product codes, addresses, dates represented as text, and categorical labels. customer = "Amina Khan"
product_code = "SKU-104"
print(customer.upper())
print(product_code.startswith("SKU-"))Because strings are ordered, they support indexing and slicing. Because they are immutable, an operation such as .upper() returns a new string rather than changing the original object. Common operations include: | Operation | Example | Purpose |
|---|
| Concatenation | "North" + " " + "Region" | joins strings | | Length | len(code) | counts characters | | Case conversion | text.lower() | standardizes case | | Trimming | text.strip() | removes surrounding whitespace | | Replacement | text.replace("Ltd", "Limited") | substitutes text | | Splitting | line.split(",") | creates a list from delimiters | | Joining | ", ".join(items) | combines strings |
A useful analytics practice is normalization before comparison: raw_region = " north "
region = raw_region.strip().title()
# region is now "North" Normalization reduces false differences, but it must be used carefully. Converting all text to lowercase may be suitable for matching product labels, but inappropriate when capitalization carries meaning, such as account identifiers. 1.2 ListsA list is an ordered, mutable collection. It can contain duplicate values and values of different types, although homogeneous lists are usually easier to analyze. monthly_sales = [12000, 13500, 12800, 14900]
monthly_sales.append(15200)
monthly_sales[1] = 14000 Lists are suitable when order matters and the collection may change. Common methods include .append(), .extend(), .insert(), .remove(), .pop(), and .sort(). The assignment b = a does not create an independent list; both names refer to the same object. To create a shallow copy, use b = a.copy() or b = a[:]. This distinction is important when preparing alternative versions of a dataset. 1.3 TuplesA tuple is an ordered, immutable collection. Tuples are useful for fixed records or values that should not be changed accidentally. sale = ("TX1007", "East", 2450.75)
transaction_id, region, amount = saleTuple unpacking improves readability. A tuple can also serve as a dictionary key when its elements are hashable, for example (year, quarter). Immutability supports data integrity, but it does not make every nested object immutable. A tuple containing a list can still have that list modified. Analysts should therefore distinguish between shallow immutability and complete immutability. 1.4 SetsA set is an unordered collection of unique, hashable values. Sets are especially useful for membership tests and removing duplicates. online_regions = {"North", "South", "West"}
new_regions = {"South", "East"}
print(online_regions | new_regions) # union
print(online_regions & new_regions) # intersection
print(online_regions - new_regions) # differenceSet operations have clear business interpretations. A union combines customers from two campaigns; an intersection identifies customers appearing in both campaigns; a difference identifies customers in one group but not another. Since sets do not preserve a business-defined order, they should not replace lists when sequence is meaningful. 1.5 DictionariesA dictionary stores key–value pairs. Keys are unique and must be hashable; values may be of almost any type. customer = {
"id": "C204",
"segment": "Business",
"credit_limit": 25000,
"active": True
}
print(customer["segment"])
customer["credit_limit"] = 30000Use dictionary[key] when a missing key indicates a programming or data error. Use .get() when absence is expected: phone = customer.get("phone", "Not provided")Dictionaries are natural representations of records and lookup tables. A dictionary may also contain lists or other dictionaries, producing nested structures. For example, sales_by_region["North"] might contain a list of monthly values. 2. Indexing, Slicing, and SelectionPython uses zero-based indexing: the first item has index 0. Negative indexes count from the end. quarters = ["Q1", "Q2", "Q3", "Q4"]
first = quarters[0]
last = quarters[-1]
second_to_fourth = quarters[1:4] A slice has the general form sequence[start:stop:step]. The start is included and the stop is excluded. Thus, quarters[1:3] returns Q2 and Q3. Strings, lists, and tuples support indexing and slicing; sets do not because they have no positional order. Dictionaries are accessed by keys, not by numerical position. Nested data requires multiple selections: orders = [
{"id": "O1", "amount": 850},
{"id": "O2", "amount": 1200}
]
second_amount = orders[1]["amount"]A common error is IndexError, which occurs when a sequence index is outside its valid range. Defensive code checks length or uses controlled iteration rather than assuming that every record has the same structure. 3. Comprehensions and TransformationA comprehension creates a collection from an iterable in a compact expression. A list comprehension has the conceptual form: [expression for item in iterable if condition] For example: amounts = [850, 1200, 450, 2100]
large_orders = [amount for amount in amounts if amount >= 1000] A dictionary comprehension creates key–value pairs: prices = {"A": 12, "B": 20, "C": 15}
price_with_tax = {code: price * 1.10 for code, price in prices.items()}A set comprehension creates unique results: regions = {order["region"] for order in orders if "region" in order}Comprehensions are valuable for straightforward transformation and filtering. They should not be used when the expression becomes difficult to read, requires extensive side effects, or contains several nested conditions. In those cases, a conventional loop is more maintainable. 4. Conditional Logic and Business RulesConditional statements allow a program to choose actions based on facts. The basic structure is if, followed by optional elif branches and an optional else branch. def classify_order(amount):
if amount >= 2000:
return "High value"
elif amount >= 1000:
return "Medium value"
else:
return "Standard"Conditions use comparison operators such as ==, !=, <, >, <=, and >=. Boolean operators combine conditions: and requires both conditions, or requires at least one, and not reverses a Boolean result. if amount >= 1000 and customer_status == "Active":
decision = "Eligible for priority service"Business rules should be explicit about boundary values. In the function above, an amount of exactly 2,000 is high value, while an amount of exactly 1,000 is medium value. Overlapping or contradictory rules can produce unintended classifications, so rules should be tested with boundary cases. Python also treats some values as false in Boolean contexts, including None, False, 0, empty strings, and empty collections. This is convenient but potentially dangerous: an amount of zero and a missing amount are not necessarily the same business condition. Prefer explicit tests such as amount is None when missingness matters. 5. Iteration and AggregationIteration repeats an operation over items. A for loop is normally preferred when processing a known collection. revenue = 0
for order in orders:
revenue += order["amount"]The range() function generates integer sequences, while enumerate() supplies both index and value: for position, region in enumerate(["North", "South", "West"], start=1):
print(position, region)The zip() function pairs elements from iterables. It stops when the shortest iterable is exhausted, so analysts should verify that inputs have compatible lengths when every pairing is required. products = ["A", "B", "C"]
units = [10, 5, 8]
for product, quantity in zip(products, units):
print(product, quantity)A while loop repeats while a condition remains true. It is useful when termination depends on an event, but the condition must eventually become false. Otherwise, an infinite loop results. break exits a loop; continue skips to the next iteration. These statements can be useful, but excessive use may obscure the processing logic.
Accumulation patternsA running total uses an accumulator: total = 0
for amount in amounts:
total += amountA count can be maintained similarly. For simple totals, Python’s built-in sum() is clearer. For conditional counts, sum() can use Boolean values because True behaves numerically as 1 and False as 0: number_of_large_orders = sum(amount >= 1000 for amount in amounts) This is a programming convention, not a substitute for understanding the business definition of a qualifying order. 6. Exception Handling and Data ReliabilityAn exception is an event that interrupts normal execution because an operation cannot be completed safely. Common exceptions include ValueError for an invalid value, TypeError for an inappropriate type, KeyError for a missing dictionary key, and IndexError for an invalid sequence position. Exception handling uses try and except: def parse_amount(value):
try:
amount = float(value)
except (TypeError, ValueError):
return None
return amountThe function returns None for invalid input, allowing a later process to identify missing or rejected records. A robust pipeline should not silently discard these records. It should log the problem, preserve the original value where appropriate, and report the number and nature of rejected observations. An optional else block runs when no exception occurs, while finally runs regardless of success or failure. finally is useful for cleanup, such as closing a resource. Avoid broad handlers such as except Exception: unless there is a carefully justified recovery and logging strategy. Broad handling can conceal programming defects. Raising an exception communicates that a function’s contract has been violated: def discount_rate(rate):
if not 0 <= rate <= 1:
raise ValueError("rate must be between 0 and 1")
return rateThe condition is an assumption of the function: the rate is expressed as a decimal proportion, so 0.15 means 15 percent. If the input convention is percentage points, the interface should state that explicitly. 7. Integrated Business Application: Order-Quality MonitoringThe following is an illustrative case. A retailer receives order records from several regional systems. Management wants to calculate valid revenue, classify orders, identify regions, and report data-quality problems without allowing one malformed record to stop the entire process. Background and problemEach record may contain an order identifier, region, customer segment, and amount. Some amounts arrive as strings, some are missing, and some records contain invalid negative values. The retailer needs a transparent process that distinguishes valid revenue from rejected data. Analysis and approachA list stores records in arrival order. Each record is represented by a dictionary. A set identifies unique regions. Strings are normalized, conditional logic classifies orders, and exception handling isolates conversion failures. records = [
{"id": "O100", "region": " north ", "segment": "Business", "amount": "1250"},
{"id": "O101", "region": "South", "segment": "Consumer", "amount": 850},
{"id": "O102", "region": "North", "segment": "Business", "amount": "unknown"},
{"id": "O103", "region": "West", "segment": "Business", "amount": -50}
]
valid_orders = []
rejected_orders = []
regions = set()
def process_order(record):
try:
amount = float(record["amount"])
if amount < 0:
raise ValueError("negative amount")
region = record["region"].strip().title()
if not region:
raise ValueError("blank region")
category = (
"High value" if amount >= 1000
else "Standard"
)
return {
"id": record["id"],
"region": region,
"segment": record.get("segment", "Unknown"),
"amount": amount,
"category": category
}
except (KeyError, TypeError, ValueError) as error:
return {"id": record.get("id", "Unknown"), "error": str(error)}
for record in records:
result = process_order(record)
if "error" in result:
rejected_orders.append(result)
else:
valid_orders.append(result)
regions.add(result["region"])
total_revenue = sum(order["amount"] for order in valid_orders)OutcomeThe valid orders are O100 and O101. Their revenue is 1,250 + 850 = 2,100. The unique normalized regions are North and South. O102 is rejected because unknown cannot be converted to a number. O103 is rejected because its amount is negative. The process does not merely produce a total; it also preserves a rejection trail. This is essential for auditability. A manager can see why reported revenue excludes particular records and can assign corrective action to the relevant source system. Learning pointsFirst, data structures should reflect the data model. Second, validation rules must be explicit, especially for missing, negative, or malformed values. Third, error handling should support investigation rather than hide problems. Finally, an automated result is only as trustworthy as its definitions, input controls, and monitoring. 8. Professional Practice, Governance, and LimitationsReadability and testingReadable code uses descriptive names, small functions, consistent indentation, and comments that explain decisions rather than obvious syntax. Functions should have clear input and output expectations. Test cases should include normal values, empty collections, boundary values, missing keys, malformed strings, and unexpected types. Data quality and auditabilityA script can execute successfully while producing an incorrect report. For example, silently converting an invalid amount to zero may inflate data completeness and understate the apparent error rate. Production processes should record validation outcomes, source information, processing time, and rule versions. Privacy and access controlDictionaries and lists often contain personal or commercially sensitive information. Analysts should minimize collected fields, restrict access, avoid exposing identifiers in logs, and follow applicable organizational and legal requirements. Data should not be copied into experimental notebooks or shared files without authorization. Fairness and automated decisionsConditional rules can affect customers, employees, or suppliers. A rule classifying customers as “high risk” may seem objective but can reproduce biased source data. The analyst should document variables, review thresholds, assess disparate effects where relevant, and provide an escalation path for unusual cases. Python implements rules; it does not establish their legitimacy. Contemporary practiceModern analytics pipelines often use Python collections at the preparation stage and then move to libraries such as pandas for tabular data. The underlying concepts remain important: a pandas column resembles a sequence, a record resembles a mapping, and filtering still depends on Boolean logic. AI-assisted coding can suggest loops or comprehensions, but generated code must be reviewed for correctness, privacy, security, and hidden assumptions. Automated suggestions do not replace testing or professional accountability. Best-Practice Checklist- Choose a structure according to order, uniqueness, mutability, and lookup needs.
- Normalize text only when the business meaning permits it.
- Use explicit tests for missing values and boundary conditions.
- Prefer clear loops over overly complex comprehensions.
- Validate external data before calculations.
- Catch specific exceptions and record rejected inputs.
- Preserve an audit trail for important transformations.
- Test both expected and unexpected cases.
- Protect confidential information in code, logs, and notebooks.
- Document assumptions and business-rule ownership.
Chapter SummaryPython’s core data structures provide distinct models for business information. Strings represent textual values; lists represent ordered mutable collections; tuples represent fixed ordered collections; sets represent unique values; and dictionaries represent key–value relationships. Indexing and slicing retrieve parts of sequences, while comprehensions support concise transformation and filtering. Conditional statements encode business rules, and iteration processes collections to calculate totals, counts, and classifications. Exception handling prevents malformed input from unnecessarily terminating a process, but errors should be recorded rather than concealed. The integrated order-monitoring case illustrates how these features work together in a reliable analytical workflow. Effective business analytics requires more than syntactically correct Python. Analysts must define rules precisely, test boundary cases, protect sensitive data, document assumptions, and assess the consequences of automated classifications. These practices form the foundation for later work with tabular data, visualization, statistical analysis, and predictive modeling. Key TermsString: An immutable ordered sequence of characters. List: An ordered, mutable collection. Tuple: An ordered, immutable collection. Set: An unordered collection of unique hashable values. Dictionary: A collection of key–value pairs. Index: A position used to access an item in a sequence. Slice: A selected range of a sequence. Mutable: Capable of being changed after creation. Immutable: Not directly changeable after creation. Comprehension: A compact syntax for constructing a collection. Conditional statement: Logic that selects actions based on conditions. Iteration: Repeated processing of items in an iterable. Accumulator: A variable updated progressively during processing. Exception: An event indicating that normal execution cannot continue safely. Validation: Checking whether data satisfies specified requirements. Normalization: Transforming data into a consistent representation. Hashable: Suitable for use as a set element or dictionary key. Audit trail: A record of inputs, transformations, errors, and outputs. Boundary case: An input at or near the limit of a rule. Review QuestionsShort Answer Questions- Why is a dictionary often appropriate for representing a business record?
- What is the difference between a list and a tuple?
- Explain what the slice
items[1:4] returns. - Why should missing values not automatically be treated as zero?
- What is the purpose of catching a
ValueError during numeric conversion?
Long Answer Questions- Compare strings, lists, tuples, sets, and dictionaries in terms of order, uniqueness, mutability, and typical business use.
- Explain how conditional logic and iteration can be combined to implement a customer-segmentation rule.
- Discuss the benefits and limitations of list, set, and dictionary comprehensions.
- Design an exception-handling strategy for a monthly sales-import process.
- Explain why auditability and data governance are necessary even when Python code runs without errors.
Analytical / Application Questions- A retailer receives product codes with inconsistent spacing and capitalization. Design a Python-based cleaning and validation approach, including likely exceptions and quality checks.
- A customer appears in two campaign lists, but one list contains duplicates. Which data structures and operations would you use to identify unique shared customers? Explain your reasoning.
- A management rule awards priority service to active customers whose order amount is at least 1,000, but the source contains missing, negative, and text-formatted amounts. Develop a processing logic that produces valid decisions and a separate rejection report.
Multiple Choice Questions with AnswersQuestion 1Which Python data structure is most appropriate for storing unique sales regions when order is not important? A. List B. Tuple C. Set D. String Correct Answer: C. Set Question 2What does items[1:4] return for a sequence? A. Items at indexes 1, 2, and 3 B. Items at indexes 1, 2, 3, and 4 C. Only the item at index 4 D. Items at indexes 0, 1, 2, and 3 Correct Answer: A. Items at indexes 1, 2, and 3 Question 3Which method safely retrieves a dictionary value when a key may be absent? A. append() B. get() C. split() D. sort() Correct Answer: B. get() Question 4What is the result of sum(amount >= 1000 for amount in [800, 1000, 1500])? A. 1 B. 2 C. 3 D. 2300 Correct Answer: B. 2 Question 5Which exception commonly occurs when float("unknown") is executed? A. IndexError B. KeyError C. ValueError D. NameError Correct Answer: C. ValueError Question 6Why is a tuple useful for a fixed business record? A. It automatically removes duplicates B. It prevents direct modification of the tuple structure C. It always sorts its values D. It permits only numeric values Correct Answer: B. It prevents direct modification of the tuple structure Question 7What does the set intersection operation identify? A. Values appearing in either set B. Values appearing in both sets C. Values appearing only in the first set D. All duplicate values within one list Correct Answer: B. Values appearing in both sets Question 8Which statement about a list comprehension is correct? A. It can construct a list using an expression and iteration B. It can be used only with dictionaries C. It always modifies the original list D. It requires every item to be a string Correct Answer: A. It can construct a list using an expression and iteration Question 9In the illustrative order-monitoring case, what valid revenue results from orders of 1,250 and 850? A. 400 B. 850 C. 1,250 D. 2,100 Correct Answer: D. 2,100 Question 10Which practice best supports reliable exception handling in an analytics pipeline? A. Catch every error and ignore it B. Convert every invalid value to zero C. Catch specific exceptions and record rejected inputs D. Stop processing after the first malformed record Correct Answer: C. Catch specific exceptions and record rejected inputs
|