Programming in Python

Chapter 1
Computational Thinking and the Python Ecosystem

Bachelors Program in AI & ML
Programming in Python   •   Bachelor

Computational Thinking and the Python Ecosystem

Introduction

Programming is often introduced as the act of writing instructions in a programming language. That description is correct but incomplete. Effective programming begins before code is written: a programmer must understand a problem, identify relevant information, design a procedure, represent that procedure precisely, and evaluate whether the resulting program behaves correctly. These activities form the foundation of computational thinking.

Computational thinking is a disciplined way of solving problems using concepts associated with computer science. It does not mean thinking like a machine or reducing every human problem to code. Rather, it involves expressing problems in ways that make solutions systematic, testable, repeatable, and suitable for execution by a computer or by people using computational tools.

Python is particularly suitable for learning these ideas. Its syntax is relatively readable, its standard library is extensive, and its ecosystem supports scientific computing, artificial intelligence, web development, automation, education, and data analysis. Nevertheless, Python is not the same as computational thinking. A language provides a means of expression; computational thinking provides principles for deciding what to express.

This chapter introduces algorithms, abstraction, decomposition, program execution, and the principal tools of the Python ecosystem. It also distinguishes Python implementations, explains common application domains, and considers professional practices that make Python programs reliable and maintainable.

Learning Objectives

By the end of this chapter, you should be able to:

  • Explain computational thinking and its principal components.
  • Distinguish an algorithm from a program and from a programming language.
  • Use decomposition and abstraction to structure a problem.
  • Describe how Python source code is interpreted and executed.
  • Distinguish interactive interpreters, scripts, notebooks, and integrated development environments.
  • Use basic command-line operations and documentation resources.
  • Identify major Python implementations and explain why implementation choice matters.
  • Relate Python to common application domains, including AI and machine learning.
  • Recognize limitations, professional risks, and ethical considerations in Python-based development.

1. Computational Thinking as a Problem-Solving Discipline

1.1 Problems, specifications, and solutions

A computational problem consists of a desired outcome together with information about inputs, constraints, and acceptable outputs. For example, “calculate a student’s average” is not yet a complete specification. A useful specification should clarify:

  • Which marks are provided?
  • Are all marks equally weighted?
  • What happens if no marks are supplied?
  • Should the result be rounded?
  • What range of values is valid?

A specification states what a system should do without necessarily stating how it should do it. A solution method describes how the desired outcome will be produced. Confusing these two levels frequently causes poor designs. A programmer who begins coding before clarifying the specification may produce a technically correct implementation of the wrong problem.

1.2 Algorithms

An algorithm is a finite, unambiguous, and effective procedure for solving a class of problems. The word “finite” means that the procedure should terminate for valid inputs, although some useful computational processes intentionally run continuously. “Unambiguous” means that each step has a sufficiently clear interpretation. “Effective” means that the steps can, in principle, be carried out using available operations.

An algorithm is independent of a particular programming language. It may be expressed in natural language, structured English, pseudocode, a flowchart, or mathematical notation. A Python program is one implementation of an algorithm, possibly combined with input/output operations, error handling, and user-interface logic.

Consider the task of finding the largest value in a non-empty list. A language-independent algorithm is:

1. Treat the first value as the current largest.

2. Examine each remaining value.

3. If a value is larger than the current largest, replace the current largest.

4. After all values have been examined, return the current largest.

The algorithm makes an important assumption: the input list is non-empty. If empty lists are permitted, the specification must define the appropriate behavior, such as returning a special value or raising an error.

In Python, a direct implementation is:

```python

def largest(values):

if not values:

raise ValueError("values must not be empty")

current = values[0]

for value in values[1:]:

if value > current:

current = value

return current

```

Python also provides `max(values)`, but understanding the underlying algorithm is important. Standard-library functions are abstractions built on algorithms; using them effectively requires knowing their assumptions and behavior.

1.3 Decomposition

Decomposition means breaking a complex problem into smaller, more manageable subproblems. A decomposed system can often be developed, tested, and understood one component at a time.

Suppose a university wants a program that produces a course report. The overall task can be decomposed into:

1. Read student records.

2. Validate marks.

3. Calculate totals or averages.

4. Assign grades.

5. Produce a report.

6. Save or display the result.

Each component can be represented by a function or module. Decomposition reduces cognitive load and supports reuse. It also improves fault isolation: if grade assignment is incorrect, that component can be tested without rerunning the entire reporting system.

Good decomposition is not merely splitting a long program into arbitrary pieces. Components should have coherent responsibilities and limited dependencies. A function that reads files, calculates grades, formats web pages, and sends email has too many responsibilities. Such a design is difficult to test and change.

1.4 Abstraction

Abstraction is the deliberate removal of unnecessary detail so that attention can be directed toward essential properties. In programming, abstraction appears in functions, classes, modules, data types, libraries, and application programming interfaces (APIs).

For example, a programmer can write:

```python

average = sum(marks) / len(marks)

```

without needing to reproduce the internal algorithm used by `sum`. The function provides a useful abstraction. At another level, a machine-learning library may provide a `fit` method that hides matrix operations, optimization procedures, and convergence checks.

Abstraction has two directions:

  • Procedural abstraction hides how an operation is performed behind a function or method.
  • Data abstraction hides how data is represented behind an interface, such as a list-like object or a database connection.

Abstraction must be used carefully. Excessive abstraction can make a system difficult to understand, debug, or configure. The appropriate level depends on the audience, problem, and required control.

1.5 Pattern recognition and generalization

Computational problem solving also involves recognizing similarities among problems. If a process repeatedly validates input, transforms data, and produces a result, it may be possible to create a reusable function or framework. Generalization means designing a solution that applies beyond one specific example.

For instance, rather than writing separate code to calculate the average of three marks and five marks, a general solution accepts a sequence of marks of arbitrary valid length. Generalization should not be confused with making code abstract for its own sake. A generalized solution is valuable when the broader requirement is real and the resulting complexity remains manageable.

2. Representing Algorithms Before Coding

2.1 Pseudocode and flowcharts

Pseudocode expresses an algorithm in a structured, language-independent form. It is useful during analysis because it emphasizes logic rather than syntax. For example:

```text

READ marks

IF marks is empty

REPORT an error

ELSE

total ← 0

FOR each mark in marks

IF mark is outside the permitted range

REPORT invalid input

total ← total + mark

average ← total / number of marks

DISPLAY average

```

A flowchart represents control flow graphically using conventions such as process boxes, decision diamonds, and arrows. Flowcharts can help beginners visualize branching and repetition, although pseudocode is often easier to maintain for larger algorithms.

2.2 Control structures

Most introductory algorithms use three fundamental control structures:

  • Sequence: instructions execute in order.
  • Selection: a condition determines which path is taken.
  • Iteration: a group of instructions is repeated.

Python expresses these structures with statements such as assignments and function calls for sequence, `if` and `match` for selection, and `for` and `while` for iteration. A program’s behavior depends not only on individual statements but also on their control flow.

2.3 Correctness and testing

An algorithm should be evaluated against its specification. Testing does not prove that a program is correct in every possible circumstance, but well-designed tests provide evidence and expose defects.

Useful categories include:

  • Typical cases: ordinary valid inputs.
  • Boundary cases: smallest, largest, empty, or limiting values.
  • Invalid cases: inputs that violate the specification.
  • Adversarial cases: inputs likely to expose assumptions or weaknesses.

For the `largest` function, tests should include a single-element list, repeated values, negative values, and an empty list. Testing should be connected to requirements rather than chosen randomly.

3. How Python Programs Execute

3.1 Source code, bytecode, and runtime behavior

Python source code is written in text files, conventionally ending in `.py`. In the widely used CPython implementation, source is parsed and compiled into an intermediate representation commonly called bytecode. The Python virtual machine then executes that bytecode. The exact internal process can vary by version and implementation, so the conceptual model should not be treated as a universal physical description of every Python system.

A simplified execution sequence is:

1. The operating system starts a Python command.

2. Python initializes its runtime environment.

3. The source is tokenized and parsed.

4. Syntax and other early errors are detected.

5. Code is compiled into an executable internal form.

6. Statements are executed by the runtime.

7. Imported modules are located, loaded, and initialized as required.

A program can fail at several stages. A syntax error occurs when code violates the language grammar. A runtime exception occurs while valid code is executing, such as attempting to divide by zero or access a missing dictionary key. A logic error occurs when the program runs but produces an incorrect result.

3.2 Names, objects, and types

Python variables are better understood as names bound to objects rather than as fixed boxes containing values. For example:

```python

x = 10

x = "ten"

```

The name `x` is first associated with an integer object and later with a string object. Python is dynamically typed: type information is associated with objects and checked during execution. This does not mean that Python has no types. Integers, strings, lists, functions, and user-defined instances all have types, and operations must be compatible with those types.

Python is also strongly typed in the practical sense that it generally does not silently combine unrelated types in arbitrary ways. For example, adding an integer to a string raises an exception rather than automatically guessing a conversion.

3.3 Modules, packages, and environments

A module is a Python file containing definitions and executable statements. A package is a structure used to organize related modules. The standard library supplies modules for tasks such as file handling, dates, mathematics, data serialization, and operating-system interaction.

Third-party packages extend Python’s capabilities. Examples include NumPy for numerical arrays, pandas for tabular data, Matplotlib for visualization, scikit-learn for classical machine learning, and PyTorch for tensor computation and deep learning. Package versions and dependencies must be managed carefully because a program may depend on particular interfaces or behaviors.

A virtual environment is an isolated environment containing a Python interpreter and installed packages for a project. Isolation reduces conflicts between projects that require different versions. A common workflow is:

```bash

python -m venv .venv

```

The activation command differs by operating system. After activation, packages can be installed with `python -m pip install package_name`. In professional work, dependencies should be recorded in a file or managed by an appropriate project tool so that environments can be reproduced.

4. Python Workspaces and Development Tools

4.1 The interactive interpreter

The interactive interpreter, often called the REPL (read–eval–print loop), reads an expression or statement, evaluates it, displays a result when appropriate, and waits for more input. It is useful for experimentation and learning:

```text

>>> 2 + 3

5

>>> name = "Ada"

>>> name.upper()

'ADA'

```

The REPL provides immediate feedback, but commands entered there are not automatically organized into a maintainable program. It is therefore best suited to exploration, small calculations, and checking language behavior.

4.2 Scripts

A script is a saved Python file that can be executed repeatedly. For example, a file named `temperature.py` might contain:

```python

celsius = float(input("Temperature in Celsius: "))

fahrenheit = celsius * 9 / 5 + 32

print(fahrenheit)

```

A script supports version control, testing, reuse, and automation. It can be run from a terminal with a command such as `python temperature.py`, although the exact command may be `python3` on some systems.

A professional script commonly separates reusable logic from execution logic:

```python

def celsius_to_fahrenheit(celsius):

return celsius * 9 / 5 + 32

if __name__ == "__main__":

value = float(input("Temperature in Celsius: "))

print(celsius_to_fahrenheit(value))

```

The conditional protects the interactive part from running automatically when the file is imported as a module.

4.3 Notebooks

A notebook combines executable code, text, mathematical notation, visualizations, and output. Jupyter notebooks are widely used in data science and machine learning because they support exploratory, incremental analysis.

Notebooks have advantages: they make explanations and results visible together, support rapid experimentation, and are effective for teaching and communicating analyses. They also have risks. Cells can be executed out of order, hidden state can affect results, and large outputs can make version control difficult. Important work should eventually be converted into tested modules, scripts, or reproducible pipelines.

4.4 Integrated development environments

An integrated development environment (IDE) combines an editor with tools such as syntax highlighting, code navigation, debugging, testing, and environment management. Examples include IDLE, Visual Studio Code with Python extensions, and PyCharm.

An IDE does not replace understanding. It can identify syntax problems, but it cannot determine whether an algorithm matches a poorly specified requirement. Students should learn both tool-assisted workflows and the underlying command-line concepts.

4.5 Basic command-line practice

The command line is a text-based interface for interacting with the operating system. Common operations include:

  • displaying the current directory;
  • listing files;
  • changing directories;
  • creating or removing directories;
  • running Python programs;
  • installing packages;
  • redirecting output and examining error messages.

Commands vary across Windows, macOS, and Linux, so users should consult platform documentation. Python-specific commands should preferably be invoked through the selected interpreter, for example `python -m pip`, because this reduces confusion when multiple Python installations exist.

4.6 Documentation and help

Reliable programmers use documentation rather than relying exclusively on memory or search results. Important resources include:

  • the official Python language reference;
  • the Python standard-library documentation;
  • documentation for third-party packages;
  • function docstrings and `help()`;
  • project README files and changelogs;
  • issue trackers and release notes.

Documentation should be evaluated for version compatibility, authorship, maintenance status, and security implications. Copying code without understanding licensing, assumptions, or input handling is a professional risk.

5. Python Implementations

Python is a language specification and a family of implementations. The implementation is the software that translates or executes Python programs.

CPython

CPython is the reference implementation and the most widely deployed implementation. It is written primarily in C and provides access to a large ecosystem of extension modules. It is usually the default choice for general development.

PyPy

PyPy is an alternative implementation with a just-in-time compilation system designed to improve performance for some long-running pure-Python programs. Performance depends on workload, libraries, and program structure; PyPy is not automatically faster in every situation.

MicroPython and CircuitPython

MicroPython and CircuitPython are implementations designed for microcontrollers and resource-constrained hardware. They provide a Python-like programming experience but do not implement the entire desktop Python standard library. They are useful in embedded systems, education, and physical computing.

Jython and IronPython

Jython targets the Java Virtual Machine, while IronPython targets the .NET ecosystem. They can facilitate integration with libraries in those environments, although compatibility with CPython-specific extensions may differ.

Implementation choice affects available libraries, performance, operating-system integration, debugging tools, and deployment. Code that uses only well-supported language features may be portable, but assumptions about native extensions, file paths, concurrency, or performance can reduce portability.

6. Python Application Domains

Python is used across many domains because it balances readability, expressiveness, and library support.

  • Automation: file processing, system administration, report generation, and task scheduling.
  • Web development: server-side applications and APIs using frameworks such as Django and Flask.
  • Data analysis: cleaning, transforming, summarizing, and visualizing datasets.
  • Scientific computing: numerical simulation, optimization, and research workflows.
  • Artificial intelligence and machine learning: model training, evaluation, data preparation, and deployment support.
  • Education: introductory programming and computational experimentation.
  • Testing and quality assurance: unit tests, integration tests, and browser automation.
  • Embedded and physical computing: sensors, robotics, and microcontrollers through specialized implementations.

Python is not always the best choice. A mobile application, hard real-time controller, memory-constrained service, or extremely performance-sensitive numerical kernel may require another language or a hybrid architecture. Python programs can also call optimized code written in C, C++, Rust, or other languages, so language choice is often a system-design decision rather than an all-or-nothing choice.

7. Illustrative Case: Automating a University Attendance Report

Background

This illustrative case concerns a department that receives attendance records as comma-separated files from several classes. Staff members manually calculate attendance percentages and identify students requiring support.

Problem

Manual processing is slow and error-prone. Files may contain missing names, invalid attendance counts, duplicate records, or inconsistent course identifiers. The department needs a repeatable process that produces a report while preserving an audit trail.

Analysis

The problem is decomposed into file discovery, parsing, validation, aggregation, classification, and report generation. Abstraction suggests that each responsibility should be represented by a separate function. The specification must define how duplicate records are handled and what minimum attendance percentage triggers review.

A possible algorithm is:

1. Read each input record.

2. Validate that required fields are present.

3. Confirm that attended sessions and total sessions are integers.

4. Reject records where total sessions are zero or attendance exceeds total sessions.

5. Aggregate valid records by student and course.

6. Calculate attendance percentage for each aggregate.

7. Mark records below the policy threshold.

8. Write a report containing accepted records, rejected records, and reasons.

If attendance is represented by attended sessions `a` and total sessions `t`, with `t > 0`, the percentage is

`attendance percentage = 100 × a / t`.

The condition `t > 0` is essential because division by zero is undefined. The formula assumes that sessions are counted consistently and that each session has equal weight.

Approach and solution

A Python implementation could use the `csv` module for parsing, dictionaries for aggregation, and functions such as `read_records`, `validate_record`, and `build_report`. Tests should include valid records, missing fields, zero sessions, impossible counts, duplicate records, and non-ASCII names.

The report should not silently discard invalid data. Instead, it should record the input row, the detected problem, and the processing decision. This supports accountability and correction.

Outcome

A well-designed system reduces repetitive work and makes the calculation consistent. It does not eliminate the need for staff judgment: a low attendance percentage may have legitimate explanations, and access to the report should be restricted because attendance data is personal information.

Learning points

The case demonstrates that programming begins with specification and decomposition. Python syntax is only one part of the solution. Validation, traceability, testing, privacy, and communication with domain users are equally important.

8. Challenges, Limitations, and Professional Practice

Python’s readability can encourage beginners to underestimate software complexity. A short program may still contain security vulnerabilities, incorrect assumptions, or untested edge cases. Dynamic typing accelerates experimentation but can allow certain errors to appear only during execution. Package dependencies can introduce compatibility and supply-chain risks.

Best practices include:

  • use meaningful names and small, cohesive functions;
  • validate external input;
  • write tests for normal, boundary, and invalid cases;
  • use version control;
  • isolate project dependencies;
  • document assumptions and interfaces;
  • format and lint code consistently;
  • review exceptions rather than hiding them with broad `except` clauses;
  • avoid storing secrets directly in source code;
  • keep dependencies updated and assess their provenance;
  • design for accessibility, maintainability, and reproducibility.

In AI and machine-learning applications, additional concerns arise. Data may contain personal or sensitive information. Models may reproduce bias present in training data. A Python notebook that produces a high accuracy score may still be unsuitable for deployment if the evaluation data leaks information from the future or if important groups are underrepresented. Computational thinking therefore includes questioning data, assumptions, and consequences—not merely optimizing code.

9. Contemporary Developments

Python development increasingly involves automated testing, type annotations, package managers, containers, cloud platforms, notebooks, and AI-assisted programming tools. Type annotations can improve documentation and enable static analysis, although they do not by themselves guarantee correctness. Continuous integration can automatically run tests and quality checks whenever code changes.

AI coding assistants may suggest functions, tests, or explanations. They can increase productivity, but generated code may contain subtle defects, insecure practices, licensing concerns, or fabricated APIs. Developers remain responsible for reviewing, testing, and governing the resulting software. In university and professional contexts, the use of such tools should follow institutional policies and preserve academic and data confidentiality.

Chapter Summary

Computational thinking provides a foundation for programming by emphasizing problem specification, algorithms, decomposition, abstraction, pattern recognition, and generalization. An algorithm is a finite and unambiguous procedure; a Python program is a language-specific implementation of such a procedure. Decomposition divides complex work into coherent components, while abstraction hides unnecessary implementation detail behind functions, modules, and APIs.

Python programs may be explored interactively, saved as scripts, developed in notebooks, or managed within IDEs. Understanding the command line, documentation, virtual environments, and testing is essential for professional development. Python implementations include CPython, PyPy, MicroPython, CircuitPython, Jython, and IronPython, each with different compatibility and performance characteristics.

Python supports automation, web development, data analysis, scientific computing, AI and machine learning, testing, education, and embedded systems. Its strengths do not remove the need for specification, validation, security, privacy protection, reproducibility, and critical evaluation. Effective Python programming combines language knowledge with sound computational reasoning and responsible engineering practice.

Key Terms

Computational thinking: A systematic approach to problem solving using computational concepts and methods.

Algorithm: A finite, unambiguous, and effective procedure for solving a problem.

Specification: A statement of required behavior, inputs, outputs, and constraints.

Decomposition: Breaking a complex problem into smaller, manageable components.

Abstraction: Representing essential features while hiding unnecessary detail.

Generalization: Designing a solution that applies to a broader class of problems.

Pseudocode: A structured, language-independent description of an algorithm.

Control flow: The order in which program instructions are executed.

Syntax error: An error caused by violating the grammar of a programming language.

Runtime exception: An error raised while a syntactically valid program is executing.

Logic error: A defect that causes an incorrect result without necessarily stopping execution.

Interpreter: Software that executes a programming language or its intermediate representation.

REPL: An interactive read–eval–print loop for evaluating code incrementally.

Script: A saved program file intended for execution.

Notebook: An interactive document combining code, text, and outputs.

IDE: An integrated development environment containing editing and development tools.

Module: A Python file containing definitions and executable code.

Virtual environment: An isolated Python installation and package context for a project.

CPython: The reference and most widely used Python implementation.

API: An interface through which software components communicate.

Review Questions

Short Answer Questions

1. What is computational thinking, and how does it differ from merely writing code?

2. Define an algorithm and identify two properties of a good algorithm.

3. Explain the difference between decomposition and abstraction.

4. What is the purpose of a Python virtual environment?

5. Name two limitations or risks associated with notebooks.

Long Answer Questions

1. Explain how a problem can be transformed from an informal requirement into a tested Python program. Include specification, decomposition, algorithm design, implementation, and testing.

2. Compare the interactive interpreter, scripts, notebooks, and IDEs. Explain when each is most appropriate.

3. Describe the conceptual stages involved when a Python program is executed, and distinguish syntax errors, runtime exceptions, and logic errors.

4. Compare CPython, PyPy, and MicroPython in terms of purpose, compatibility, and likely application context.

5. Discuss Python’s suitability for AI and machine-learning development, including its strengths, limitations, and ethical responsibilities.

Analytical / Application Questions

1. Design a decomposition and pseudocode algorithm for a program that reads examination marks, rejects invalid values, calculates a class average, and reports the highest and lowest marks. State your assumptions.

2. A notebook produces a correct result only when cells are run in a particular order. Analyze why this occurs and propose a workflow for converting the analysis into a reproducible software component.

3. A university attendance system reports students with zero total sessions as having zero percent attendance. Identify the conceptual and implementation problem, propose a corrected rule, and explain the privacy and governance issues that should also be considered.

Multiple Choice Questions with Answers

Question 1

Which statement best defines an algorithm?

A. A programming language used to write software

B. A finite, unambiguous, and effective procedure for solving a problem

C. A graphical user interface for running code

D. A file containing only data

Correct Answer: B. A finite, unambiguous, and effective procedure for solving a problem

Question 2

What is the primary purpose of decomposition?

A. To hide all errors from users

B. To convert Python into machine code

C. To divide a complex problem into manageable components

D. To eliminate the need for testing

Correct Answer: C. To divide a complex problem into manageable components

Question 3

Which activity is an example of abstraction?

A. Using sum(marks) without implementing its internal addition process

B. Changing a variable name repeatedly

C. Deleting all documentation

D. Running every statement manually

Correct Answer: A. Using sum(marks) without implementing its internal addition process

Question 4

Which tool is most appropriate for quick, interactive experimentation with Python expressions?

A. A linker

B. A REPL

C. A spreadsheet printer

D. A hardware debugger only

Correct Answer: B. A REPL

Question 5

What is a major risk of executing notebook cells out of order?

A. The Python language grammar changes

B. The operating system is automatically replaced

C. Hidden state can make results difficult to reproduce

D. All package installations are permanently removed

Correct Answer: C. Hidden state can make results difficult to reproduce

Question 6

Which implementation is the reference and most widely used Python implementation?

A. CPython

B. MicroPython

C. Jython

D. IronPython

Correct Answer: A. CPython

Question 7

Why are virtual environments useful?

A. They guarantee that every algorithm is correct

B. They isolate project interpreters and package dependencies

C. They replace the need for source files

D. They prevent all runtime exceptions

Correct Answer: B. They isolate project interpreters and package dependencies

Question 8

If attended sessions are 18 and total sessions are 20, what is the attendance percentage using 100 × attended / total?

A. 80%

B. 85%

C. 90%

D. 95%

Correct Answer: C. 90%

Question 9

Which error occurs when valid code performs an operation such as division by zero during execution?

A. A syntax error

B. A runtime exception

C. A formatting convention

D. A documentation error

Correct Answer: B. A runtime exception

Question 10

Which practice best supports reproducible Python projects?

A. Keeping dependencies undocumented

B. Running code only in an unrecorded notebook state

C. Recording dependencies and using version control

D. Suppressing all exceptions

Correct Answer: C. Recording dependencies and using version control

Programming in Python
Chapter 1 of 15