2 CompSci 101L - 9/14/25

0.0(0)
studied byStudied by 0 people
GameKnowt Play
learnLearn
examPractice Test
spaced repetitionSpaced Repetition
heart puzzleMatch
flashcardsFlashcards
Card Sorting

1/87

encourage image

There's no tags or description

Looks like no tags are added yet.

Study Analytics
Name
Mastery
Learn
Test
Matching
Spaced

No study sessions yet.

88 Terms

1
New cards

Algorithm

A step-by-step procedure or formula for solving a problem or completing a task in programming and computer science.

2
New cards

Program

A collection of instructions written in a programming language that executes a specific task or solves a problem.

3
New cards

Input + Output

Input is data given to a program for processing.
Output is data that is displayed on the screen or that is sent to a file / other device.

4
New cards

Conditional Execution

Check for certain conditions and execute the appropriate sequence of statements.

5
New cards

Value

A data element that a program processes, storing a specific item of information, which can be passed to functions and is used in computations.

6
New cards

Data Types

Categories of data that determine the kind of operations that can be performed on them, such as integers, floats, or strings.

Integer — Whole numbers, positive or negative, without fractions.
Float — Numbers that contain decimal points.
String — A sequence of characters used to represent text.

7
New cards

Function — ‘type’

A classification that defines the nature of a function's return value, such as integer, float, or string.

Code — type()

8
New cards

Function — Type Conversion Functions

Functions that convert one data type to another, enabling operations across different data types in programming.

Code — int(), float(), str()

9
New cards

Variable

A named storage location in a program that can hold a value and allows programmers to reference or modify that value during execution.

When reading or writing code, say to yourself “n is assigned 17” or “n gets the value 17” or “n is a reference to the object 17” or “n refers to the object 17”. Don’t say “n equals 17”.

A variable is an abstract concept that enables data storage and retrieval. It can change throughout program execution, representing values that the program manipulates.

Variable names can contain both letters and digits, but they have to begin with a letter or an underscore. Although it is legal to use uppercase letters, by convention we don’t. If you do, remember that case matters. Bruce and bruce are different variables.

Variables are assigned to values with the assignment token, ‘=’.

10
New cards

Statement

An instruction that the Python interpreter can execute. Statements do not return a value.

11
New cards

Expression

A combination of values, variables, operators, and calls to functions. 

Expressions need to be evaluated. If you ask Python to print an expression, the interpreter evaluates the expression and displays the result. 

12
New cards

Operators and Operands

Operators are special tokens that represent computations.
Operands are the values the operator works on.

+, -, and * all mean the same in mathematics.
** is the token for exponentialism.
// is integer division.
% is the modulus operator.

13
New cards

// (integer division)

A division operation that returns the quotient without any remainder, discarding the fractional part of the result.

14
New cards

% (modulus operator)

A mathematical operator that returns the remainder of the division of one number by another.

15
New cards

Order of Operations

16
New cards

Reassignment of Variables

The process of updating the value stored in a variable after it has been initially assigned, allowing for dynamic changes in a program's execution.

17
New cards

Updating Variables

The act of changing the value of a variable during program execution, enabling programs to adapt to new data or conditions.

18
New cards

Operations on Strings

You cannot perform mathematical operations on strings, even if the strings look like numbers.

The ‘+’ operator does work with strings, but it represents concatenation, not addition.
The * operator also works, and performs repetition.

Operator Precedence (Order of Operations):

  • * (repetition) happens before + (concatenation), just like in math. 

  • Use parentheses to force concatenation first. 

19
New cards

Concatenation (Strings)

The operation of joining two or more strings together to form a single string, typically using the '+' operator in many programming languages. The two strings are linked end-to-end.

20
New cards

Repetition (Strings)

The operation of repeating a string multiple times, often using the '*' operator in programming languages. This results in a new string composed of the original string concatenated with itself the specified number of times.

One of the operands has to be a string and the other has to be an integer.

21
New cards

Function

A named sequence of statements that belong together.

The syntax for a function definition is:
def name(parameters):
statements

  • def → keyword that starts a function definition

  • name → function’s name

  • parameters → placeholders for information the function needs

    • The parameter list may be empty, or it may contain any number of parameters separated from one another by commas. 

  • statements → the code that runs when the function is called

22
New cards

Compound Statements

A group of statements that can be executed as a single unit, typically using control structures like loops or conditionals in programming. They allow for structured programming by combining multiple actions into one block.

23
New cards

Parameters vs. Arguments

  • Parameters → Formal parameters, names used inside the function definition. 

  • Arguments → Actual parameters, the real values you pass when you call the function. 

24
New cards

Defining vs. Calling

  • Defining → Stores it for later. 

  • Calling → Actually runs the function. 

25
New cards

if name == "__main__":

This line checks if the Python file is being run directly and not imported as a module, allowing for the execution of code within that block.

A Python convention. 

  • Code under it must also be intended. 

  • Think of it as: this tells Python where the main program starts.

26
New cards

Function — ‘max’

Can be sent any number of arguments, separated by commas, and will return the maximum value sent.

Code — max()

27
New cards

Fruitful Functions

Functions that return a value after execution, allowing the result to be used later in the program.

Takes in input (arguments), does some work inside, then hands back a result. 

  • A non-fruitful function (sometimes called a procedure) just does something (like printing text) but does not give back a result. 

  • Use “return” to send data back. 

28
New cards

Local Variables

Variables defined within a function that are accessible only within that function's scope. They lose their value once the function execution is complete.

29
New cards

Global Variables

Variables that are defined outside of any function, accessible throughout the entire program.

Shadowing → If a local variable has the same name as a global, the local “shadows” the global. This means inside the function, Python will always use the local. 

  • The global variable cannot be accessed by Python because the local variable will be found first.

Parameters Reassigned Inside a Function: 

  • Even if you reassign a parameter inside the function, it only affects the local version. The global variable you passed in does not change. 


Reasons to Avoid Globals: 

  • Using globals makes code confusing. 

  • Functions become dependent on outside state. 

  • Always pass values as parameters instead of relying on globals. 

30
New cards

Return Statements

Used to send a value back to the caller of a function. It allows a function to output a result which can be stored and used later.

The return statement not only causes the function to return a value, but it also returns the flow of control back to the place in the program where the function call was made. 

  • The call to a function terminates after the execution of a return statement. 

  • All Python functions return the value “None” unless there is an explicit return statement with a value other than “None”. 

    • If you use “print”, that value will not be returned to the place where the call was made. 

31
New cards

Flow of Execution

The order in which statements are executed in a program, typically controlled by function calls, conditionals, and loops. Understanding flow of execution is crucial for predicting and debugging program behavior.

Function definitions do not alter the flow of execution of the program, but statements inside the function are not executed until the function is called. 

  • When we get to the end of the program, it terminates. 

  • You will read the “def” statements as you are scanning, but you should skip the body of the function until you reach a point where the function is called. 

  • When inside a function, you might call another function. 

  • Follow the flow of calls, not just top-to-bottom text. 

32
New cards

Composition

A method of combining simple functions or structures to create a more complex function or structure. It allows for building complex behavior by composing smaller, reusable components.

Calling one function from inside another function. 

  • It is a way to build bigger functions out of smaller ones. Makes code reusable. 

  • Example is using “distance” + “area” to create “area2”. 

33
New cards

The Random Module

A Python library that implements pseudo-random number generators for various distributions, enabling users to generate random numbers and choices. It provides functions such as random(), randint(), and choice().

Random number generators are based on a deterministic algorithm – repeatable and predictable. So, they’re called pseudo-random generators. They are not genuinely random, as they start with a seed value. 

  • Each time you ask for another random number, you’ll get one based on the current seed attribute, and the state of the seed (which is one of the attributes of the generator) will be updated.


You must include “import random” to access the random module.

34
New cards

Function — random.random()

Returns a floating-point number in the range [0.0, 1.0). 

  • [ ] → inclusive (0.0 is possible)

  • ( ) → exclusive (1.0 is not possible)

  • The numbers are uniformly distributed (all equally likely).

  • You can scale the result by multiplying (e.g., print(random.random() * 5) gives numbers in [0.0, 5.0)). 

35
New cards

Function — random.randrange(start, stop)

  • Returns a random integer between “start” and “stop  - 1”. 

  • Works like range; includes the lower bound but excludes the upper bound. 

  • All values in the range are equally likely. 

36
New cards

Boolean Values

Values representing True or False states, often used in conditionals and logical operations in programming.

The Python type for storing true and false values is called “bool”. 

  • There are only two boolean values. They are True and False. They are both Boolean literals. 

    • Capitalization matters. 

    • They are not strings, and they are not surrounded by quotes. 

37
New cards

Boolean Expressions

Something that evaluates to True or False. 

  • Comparison operators are the main way we form boolean expressions. 

  • The equality operator, ==, compares two values and produces a boolean value. 

    • This is one of six common comparison operators. 

    • = is an assignment operator.

    • An equality test is symmetric, but assignment is not. For example, if a == 7 then 7 == a. But in Python, the statement a = 7 is legal and 7 = a is not.

38
New cards

Comparison Operators

39
New cards

Logical Operators

Symbols that combine boolean expressions and determine logical outcome.

 

  1. or → True if at least one condition is True.

    1. In words we might say: “number equal to 5 or 6 or 7”. However, if we translate this into Python, number == 5 or 6 or 7. You cannot take a shortcut.

  2. and → True only if both conditions are True. 

  1. not → Reverses (negates) a boolean value. 

40
New cards

Logical Opposites

Boolean values that are inverse to each other, where one is True if the other is False.

41
New cards

Precedence of Operators

Precedence → The order in which Python evaluates operators when there are no parentheses. 

  • Arithmetic first → relational next → logical last. 

  • Parentheses can always be used to make order explicit (and improve readability).

42
New cards

Conditional Execution — Binary Selection (‘if’ statement)

Selection Statements / Conditional Statements → Give the ability to check conditions and change the behavior of the program accordingly. 

  • The simplest form of selection is the “if” statement. This is sometimes referred to as binary selection since there are two possible paths of execution.


Condition → The boolean expression after the “if” statement. If it is true, then the immediately following indented statements get executed. 

  • The “if” statement consists of a header line and a body. The header line begins with the keyword “if” followed by a boolean expression and ends with a colon (:). 

  • The more indented statements that follow are called a block. 

  • There is no limit on the number of statements that can appear under the two clauses of an “if” statement, but there has to be at least one statement in each block.

43
New cards

Omitting the Else Clause — Unary Selection

Unary Selection (if without else) → Only need to do something if a condition is True. 

  • If the condition is False, the program just skips the block and continues normally. 

  • There is only one possible path of execution. 


A unary selection is a type of decision-making structure where a program evaluates a condition and executes a block of code only if the condition is true. If the condition is false, the program simply skips the block and continues with the rest of the code.

Unlike a full if–else structure, unary selection omits the else clause, meaning no action is taken if the condition is false.

Example:
x = 10

if x > 5: # unary selection

print("x is greater than 5")

print("done")

44
New cards

Nested Conditionals

A nested conditional is a decision-making structure in which one conditional statement is placed inside another. This allows the program to test multiple conditions in a hierarchical or step-by-step way, where the second (inner) condition is only checked if the first (outer) condition is true.

Key Points:

  • One if (or if–else) statement is placed inside the block of another.

  • Conditions are evaluated in sequence, giving a hierarchical flow of logic.

  • Useful when decisions depend on earlier conditions being true.

  • Can lead to deeply indented code, so clarity is important.

45
New cards

Chained Conditionals

A chained conditional is a decision-making structure where multiple conditions are evaluated in sequence using if, elif, and else statements. This allows for the execution of different blocks of code based on the first true condition encountered.

Uses ifelifelse to chain together multiple branches.

  • Conditions are checked top to bottom:

    • The first true condition executes, and the rest are skipped.

    • If none are true, the else (if present) runs.

  • Makes code clearer than deeply nested conditionals when testing multiple alternatives.

  • Only one branch will be able to run, and Python checks each condition in order.

  • There can be any number of “elif” statements, but at most one final “else”, which must come last. This “else” statement is optional. 

46
New cards

Using Boolean Functions in Conditionals

A Boolean function is a function that returns a Boolean value (True or False). When used in conditionals, Boolean functions simplify code by separating the logic test from the control flow. This makes programs easier to read, maintain, and reuse.

47
New cards

Simple (Primitive) Data Types

Simple (or primitive) data types are the most basic kinds of data built into a programming language. They represent single values (not collections or structures) and are the fundamental building blocks for all other data types.

Key Points:

  • Primitive = cannot be broken down into simpler data within the language.

  • Used to store simple values like numbers, text, or truth values.

  • Operations on primitive types are usually very fast because they’re directly supported by the computer’s memory and processor.

  • The exact list of primitive types varies between programming languages.

💻 Examples in Python:

  • int → integers (e.g., 42, -7, 0)

  • float → floating-point numbers / decimals (e.g., 3.14, -2.5)

  • bool → Boolean values (e.g., True, False)

48
New cards

Collection Data Types

Collection data types are data structures that can store multiple values together in a single variable. Unlike primitive types, which hold only one value, collections group values so they can be organized, accessed, and manipulated efficiently.

  • Hold multiple elements (can be homogeneous or heterogeneous, depending on the language).

  • Support operations like indexing, iteration, searching, adding, and removing.

  • Make it easier to manage large or related sets of data.

  • Come in different forms (ordered vs unordered, mutable vs immutable).

  • String (str) → A sequence of characters. 

  • List (list) → A sequence of items, which could be numbers, strings, or even other lists. An example is [1, 2, 3]. 

  • Collections can be treated as a whole thing (“hello world”) or piece by piece (“hello[0] gives “h”).

49
New cards

String

An ordered collection of characters. 

  • Characters have positions (indexes) from left to right, starting at 0. 

    • “cat” → index 0 = “c”

  • Strings are sequential, meaning their order matters. 


Empty String → A string that has zero characters. 

  • It is written as “” or ‘’. 

50
New cards

Index Operator — Strings

Indexing:

  • Indexing Operator → Square brackets [ ] used to select a single character from a string. 

  • Strings are sequences so each character has a position number (index). 

  • Indexes start at 0, not 1. 

  • The indexing can be any integer expression, like 2 + 1. 

  • Indexing always returns a string of length 1. Python has no separate “character” type. 

Negative Indexing:

  • You can also count backwards using negative numbers. 

  • -1 = last character, -2 = second-to-last, etc. 

51
New cards

Function — ‘length’

The length function returns the number of elements (or characters) in a collection or string. It’s used to quickly determine the size of data stored in a variable.

Key Points:

  • Measures how many items are in a sequence or collection.

  • Works on strings, lists, tuples, sets, dictionaries, and other iterable objects.

Code — len()

52
New cards

Slice Operator

An operator used to access a subsequence of a string or collection by specifying a start, stop, and optionally a step value. It allows the retrieval of multiple elements at once using a specified range of indexes.

In Python, the slice operator uses square brackets with a colon (:) to specify start, stop, and optionally step values.

Key Points:

  • General form: sequence[start:stop]

  • start → index where the slice begins (inclusive, default = 0)

  • stop → index where the slice ends, does not include it (exclusive, default = length of sequence)

  • step → interval between elements (default = 1)

  • Works on any sequence type (string, list, tuple, range).

  • Does not modify the original sequence; creates a new one.

Omitting Indices

  • If you leave out the start index, Python assumes the slice begins at the start of the sequence (0).

  • If you leave out the stop index, Python assumes the slice continues until the end of the sequence.

  • If you omit both, [:] makes a shallow copy of the entire sequence.

Out-of-Range Indexes

  • Slicing is forgiving: if start or stop goes beyond the sequence length, Python automatically adjusts it.

  • Instead of throwing an error, it just returns as much as possible.

  • This behavior is different from single-element indexing (e.g., word[100]), which raises an IndexError.

nums = [0, 1, 2, 3, 4]

print(nums[2:10]) # [2, 3, 4] → stop beyond range, no error

print(nums[-10:3]) # [0, 1, 2] → start below range, adjusted

print(nums[100:200])# [] → empty list, since no elements exist

Slice Operator with Lists: 

  • Syntax → list[start:end]

  • Works exactly like string slices. 

  • Starts at index “start” and goes up to but not including index “end”. 

53
New cards

String Comparison

The comparison operators (==, <, >, etc.) work with strings. They are based on lexicographical order. 

Lexicographical Order:

  • Strings are compared like dictionary order (alphabetical), but with a difference. All uppercase letters come before lowercase letters. 

  • There is case-sensitivity when comparing strings. 

Ordinal Value:

  • Each character has a numeric code (ordinal value) behind it. 

  • ord() → converts a character into its integer code

  • chr() → converts an integer into its character equivalent


The Space Character:

  • Space (“ “) is a real character. 

  • The ordinal value of space = 32. 

  • Spaces affect comparisons and string length. 

54
New cards

The ‘in’ and ‘not in’ Operators — Strings

The in and not in operators are used to check for membership in a sequence or collection. They test whether a value exists (or does not exist) in strings, lists, tuples, sets, or dictionaries, returning a Boolean value (True or False).

Key Points:

  • in → evaluates to True if the element exists in the collection.

  • not in → evaluates to True if the element does not exist in the collection.

  • Works with all Python sequences and collections (string, list, tuple, set, dict).

  • Very useful for conditional statements, loops, and filtering.

55
New cards

List and Elements

A sequential collection of Python data values. 

  • Each value has an index (its position in the list). 

  • Lists are written with square brackets [ ], and elements are separated by commas. 

Elements → The values in a list. 

  • Elements can be any type → numbers, strings, booleans, even other lists. 

Lists vs. Strings:

  • Both are sequences (ordered collections), and both can be accessed using indexes. 

  • Strings only contain characters, while lists can contain any type of data (even a mix in one list). 

Nested Lists → A list inside another list. 

Sublist → The inner list. 

Empty List → A list with no elements. Written as [ ]. 

Assigning Lists to Variables: 

  • You can store lists in variables, just like numbers or strings. 

56
New cards

List Length

len() with Lists:

  • Just like strings, len() tells you the length of a list. 

  • The length of a list is the number of top-level elements. 

  • Sublists count as one element. 

57
New cards

Index Operator — Lists

Index Operator with Lists:

  • The same as with strings; use square brackets [ ]. 

  • The number inside the bracket is the index. 

  • Indexing starts at 0. 

  • Can utilize negative indexing, just like with strings. 

  • The expression inside [ ] can be any integer expression. 

58
New cards

The ‘in’ and ‘not in’ Operators — Lists

  • “in” and “not in” are boolean operators that test membership in a sequence. 

    • “in” → Checks if an element is inside a list. 

    • “not in” → Checks if an element is not inside a list. 

  • Both return a boolean value (True or False). 

59
New cards

Debugging

Bug → Any programming error. 

Debugging → The process of finding and fixing those errors. 

Types of Errors: 

  1. Syntax Errors → Mistakes in the rules of the language. 

    1. Forgetting a colon : in an if statement. 

    2. Caught before the program runs. 

  2. Runtime Errors → Errors that happen while the program is running. 

    1. Dividing by zero, or trying to access lst[10] when the list only has 5 elements. 

  3. Semantic Errors → The program runs without crashing, but it doesn’t do what you intended. 

    1. Writing x * y when you meant x + y. 

Other Types of Errors:

ParseError → A syntax error. Python can’t even parse your code. 

  • Typical Causes:

    • Missing parentheses, quotation marks, or commas. 

    • Unbalanced parentheses.

TypeError → You’re trying to combine incompatible data types.

  • Typical Causes:

    • Adding a string and an integer. 

    • Using arithmetic operators on the wrong type. 

NameError → You used a variable or function name that Python doesn’t recognize. 

  • Typical Causes:

    • Typos in variable names. 

    • Using a variable before giving it a value. 

ValueError → You passed a value to a function, but the value was not valid for that function. 

  • Typical Causes:

Debugging → The process of finding and fixing errors in your code. 

  • Form a hypothesis about what is wrong, modify your code, run the program again. 

  • If the result matches your prediction, you’re closer to a fix. 

  • If not, form a new hypothesis and repeat. 

  • Make small changes, testing immediately, and always keep the program in a “working state”. 

Incremental Programming → Building a program step by step, debugging as you go. 

Debugging Interludes → Special sections with targeted debugging advice. 

Incremental Success → Building programs piece by piece with frequent small victories. 

Motivation Loop → Each solved problem gives you the energy to solve the next one. 

60
New cards

Syntax Errors

  • Occur when Python cannot parse your code because it violates the language’s syntax rules.

  • Detected before the program runs.

  • Examples: missing colon, unmatched parentheses, misspelled keywords.

Every syntax error prevents the program from running. 

  • If an error is found Python displays an error message, and quits execution immediately. 

  • No part of the program will run until all syntax errors are fixed. 

61
New cards

Runtime Errors

Occur while the program is running (not before). 

  • The program looks okay at first, but when executed, something goes wrong. 

  • These are also called exceptions because they signal that something exceptional (and bad) occurred. 

Characteristics: 

  • The program runs up to the point of the error. 

  • Python stops at the error point and shows an exception message. 


62
New cards

Semantic Errors

Occurs when your program runs without crashing, but produces the wrong result. 

  • The code is syntactically correct, but there is an issue with the logic / meaning of the code. 

  • The code does what you told it, but not what you intended. 

63
New cards

Subscriptable Objects

What “subscriptable” means

  • A subscriptable object is any object that supports indexing.

  • Examples of subscriptable objects:

    • Strings"hello"[0]'h'

    • Lists[1,2,3][1]2

    • Tuples(10,20,30)[2]30

    • Dictionaries{"a":1}["a"]1

  • Non-subscriptable objects: types that don’t support indexing.

    • int, float, bool, etc. → you can’t do 10[0] or 3.14[1].

# Indexing a non-subscriptable type

x = 10

x[0] # TypeError: 'int' object is not subscriptable

64
New cards

ValueError vs. TypeError


💡 Quick memory trick:

  • ValueError“I got the right kind of thing, but the value doesn’t work.”

  • TypeError“This kind of thing can’t do that operation at all.”

65
New cards

Strings are Immutable

Strings Cannot be Modified:

  • Strings in Python are immutable → Once created, they cannot be changed. 

  • You cannot use indexing [ ] on the left side of an assignment to replace a character. 

  • A TypeError occurs, because Python doesn’t allow changing the type’s structure (in this case, strings). Strings must stay exactly as they are. 

Correct Approach:

  • Instead of editing a string in place, you must build a new string. 

  • Use concatenation (+) and slicing to create the variation you want. 

66
New cards

Function — ‘id’

  • The id() function in Python returns a unique identifier (an integer) for an object.

  • This identifier is the object’s memory address (or a unique constant that acts like it) during its lifetime.

Code — id(object)

  • Object — any variable, list, string, function, etc.

67
New cards

Lists are Mutable

Unlike strings, lists are mutable → This means we can change an item in a list by accessing it directly as part of the assignment statement. 

  • We can update one of the list items by using the indexing operator (square brackets) on the left side of an assignment. 


Item Assignment → An assignment to an element of a list. 

  • Item assignment does not work for strings. Recall that strings are immutable. 

Using the Slice Operator → By combining assignment with the slice operator, we can update several elements at once. 

Assigning an Empty List → We can also remove elements from a list by assigning the empty list to them. 


Inserting Elements → We can insert elements into a list by squeezing them into an empty slice at the desired location. 

68
New cards

Variables and Objects

  • Variable → Doesn’t store the value directly, but stores a reference to an object. 

  • Object → Something a variable can refer to. 

Checking Identity with “is”:

  • Use the “is” operator to test if two variables refer to the same object in memory. 

    • Why True → Since strings are immutable, Python can optimize resources by making two names that refer to the same string literal value refer to the same object.

  • This is not the case with lists. 

    • “a” and “b” have the same value, but do not refer to the same object. 

  • A list is a collection of references. 

    • The variable “a” is a reference to a collection of references. 

    • Those references actually refer to the integer values in the list. 

  • Even though “a” and “b” are two different lists (two different collections of references), the integer objects are shared by both. 

    • Like strings, integers are also immutable so Python optimizes and lets everyone share the same object for some commonly used small integers. 

    • The integers may still be shared in memory because integers (like strings) are immutable. 

69
New cards

‘is’ Operator vs. ‘==’

  • is → tests whether two variables point to the same object in memory.

  • == → tests whether two variables have the same value, regardless of whether they are the same object.

Tips for Memorization:

  • is → “Are these two names pointing to the same house?”

  • == → “Do these two houses have the same furniture inside?”

  • Use is for identity checks (often with None: if x is None:).

  • Use == for value comparisons (most equality checks in programs).

70
New cards

Aliasing

Since variables are references, assigning one variable to another makes them both point to the same object. 

  • Because the same list has two different names, a and b, we say that it is aliased. 

    • Changes made with one alias affect the other. 

  • If a = [81, 82, 83] and b = a, print (a is b) → True, since both a and b now refer to the same list in memory. 

When Aliasing is a Problem:

  • With mutable objects (like lists), aliasing can lead to unintended side effects. 

    • You may accidentally change a value in one place, not realizing it changes another variable as well. 

  • With immutable objects (like strings, integers), aliasing is safe because the object can’t be changed anyway. 

Tips for Memorization:

  • Mutable objects + aliasing → shared changes

  • Immutable objects + aliasing → safe, since any “change” creates a new object

  • Use id() to check if two variables point to the same object:



Explanation:

  1. Initially, both x and y reference the same object (10).

  2. Integers are immutable, so when you “change” y, Python creates a new object for y.

  3. x still points to the original object.

Key point:

  • Immutable objects (int, str, tuple) do not allow in-place modification, so aliasing doesn’t produce shared changes.

  • Unlike mutable objects (lists, dicts), modifying y does not affect x.

71
New cards

Cloning Lists

Why Clone Lists?

  • If you just do b = a, then a and b are aliases. They point to the same list. Changing one changes the other. 

  • To avoid this, you need a separate copy of the list. This process is called cloning. 

Cloning with Slice:

  • The easiest way to clone is to use the slice operator [ : ]. 

  • Taking a full slice ( a[ : ] ) creates a new list with the same elements. 

Cloning vs. Aliasing:

  • Cloning → Making a new object that has the same contents as the original. Two variables have separate objects with the same content. 

    • Slice operator is the quickest way to clone a list. 

    • a == b → True (they have the same values)

    • a is b → False (they are different objects in memory)

  • Aliasing → Two variables share the same object. 

    • a == b → True (they have the same values)

    • a is b → True (they are the same objects in memory)

72
New cards

Repetition and References

  1. Repetition of Immutable Objects

  • Safe and behaves as expected because immutable objects cannot be changed.

  1. Repetition of Mutable Objects

  • Be careful! Repetition creates multiple references to the same object, not independent copies.

  • Repetition with Nested Lists → Repeated References

    • When you repeat a list that contains a list, Python repeats the reference to that inner list, not independent copies. When we allow a list to refer to another list, problems can arise. 

Avoiding Aliasing → How to Get Independent Sublists

  • Make copies of the inner list instead of repeating the same reference. 

  • Changing one sublist won’t affect the others. 

73
New cards

The ‘for’ Loop

Definition:

  • A for loop is a control flow statement used to iterate over a sequence or iterable (like a list, tuple, string, or range).

  • It executes a block of code repeatedly for each item in the sequence.


Key Points:

  • Loops over each element directly, no manual indexing needed.

  • Works with any iterable: lists, tuples, strings, dictionaries, sets, ranges.

  • Can include an optional else clause, executed if the loop completes normally (without break).

  • Nested for loops are possible for iterating over multi-dimensional data.

  • Loop Variable → ‘name’ in the example. 

    • Temporarily holds the current item from the sequence. 

  • Python List → The sequence being iterated over, inside [ ]. 

  • Loop Body → The indented code under the ‘for’ statement. 

    • Runs once per item in the list. 

  • Iteration Process → Python checks if there are items left to process. 

    • If yes, assigns the next item to the loop variable and executes the loop body. 

    • If no, the loop terminates and execution moves on. 

  • Terminating Condition → The point at which no items remain, so the loop stops. 

    • At the end of each execution of the body of the loop, Python returns to the ‘for’ statement, to see if there are more items to be handled.

Iterating Without Using the Loop Variable: 

  • Sometimes the loop variable isn’t actually used inside the loop. 


74
New cards

Control Flow — The ‘for’ Loop

Control Flow → The order in which the program’s statements are executed by the interpreter. 

  • You can think of this as “Python’s moving finger” that points to each line in turn. 

    • The flow of execution has been sequential so far. 

      • One statement at a time, top to bottom. 

      • This continues as long as statements are indented the same amount. 

Sequential vs. Iterative Control Flow:

  • Sequential Flow → Runs straight through the code, one statement after another. 

  • ‘for’ Loop Flow → Introduces indented sub-statements (the loop body) after the loop heading. These are executed multiple times according to the iteration rules. 

75
New cards

Function — Range

  • The range() function generates a sequence of numbers.

  • It is commonly used in for loops to iterate a specific number of times.

  • Returns a range object, which is an immutable sequence of numbers.

Range Object: Immutable Sequence of Numbers

  • When you call range(), Python does not create a list of all numbers immediately.

  • Instead, it creates a range object, which represents the sequence of numbers without storing them all in memory.

  • Immutable means you cannot change the numbers inside a range object after it’s created.

Code — range(stop)

  • Default Behavior:

    • range(N) → starts at 0, ends at N-1

    • range(4) produces 0,1,2,3

    • With range(N), a sequence N items long, but since we start at 0, the last number is N-1. 

    • With range(start, stop), the sequence begins at ‘start’ and continues as long as the number is less than ‘stop’. 

  • Range objects are lazy → they generate elements one by one when needed. 

    • To force evaluation, wrap with list(). 

      • list(range(4)) → [0, 1, 2, 3]


Code — range(start, stop, step)

  • start → first number in the sequence (default = 0)

  • stop → end of the sequence (exclusive)

  • step → difference between consecutive numbers (default = 1)

Adding a Step: 

  • General Form → range(start, beyondLast, step)

  • ‘Step’ defines the increment (positive or negative). 

76
New cards

The Accumulator Pattern

  • The accumulator pattern is a programming technique where a variable is used to collect or accumulate results while iterating through a sequence.

  • Commonly used for summing numbers, concatenating strings, counting items, or building lists.

Earlier, squaring ‘n’ was done with multiplication (n * n). 

  • The new approach is using repeated addition instead of multiplication. 

  • Generalizing → to compute n², add ‘n’ to itself ‘n’ times. 

How the Algorithm Works:

  • Start with a running total initialized at 0. 

  • Use a ‘for’ loop to repeat the process ‘n’ times. 

  • Each time through the loop, add ‘n’ to the running total. 

  • After the loop ends, the running total holds the result of n². 

The Accumulator Pattern → A common programming pattern where a variable is repeatedly updated (accumulated) inside a loop. 

  1. Initialize the accumulator variable (often set to 0 for sums, or 1 for products). 

  2. Update the accumulator inside the loop (add, multiply, or otherwise modify). 

  3. Result → When the loop ends, the accumulator holds the final value. 

Accumulator Variable → The variable (here, ‘runningtotal’) that stores the ongoing result. 

If you put ‘runningtotal = 0’ inside the loop instead of before it, it resets to 0 every time the loop begins. The accumulator never grows beyond one update. 

77
New cards

Modifying Program — The Accumulator Pattern

78
New cards

Methods — Strings

  • String methods are built-in functions in Python that operate on string objects to perform actions such as modifying, searching, or formatting text.

  • They are called using dot notation: string.method(arguments).

  • Strings are immutable, so most methods return a new string rather than modifying the original.

Why / When Guide: 

  • Normalization → strip(), then lower() to compare user input. 

  • Alignment for Display → ljust / rjust / center when printing tables. 

  • Safe Searching → find / rfind when it is normal / possible that the substring might not be there; index / rindex when the substring must be present, as absence is a bug. 

  • Counting → count() for quick frequency checks (remember: non-overlapping). 

  • Bulk Edits → replace() for global changes; use ‘n’ when you only want the first few.

79
New cards

String Method — split() + join()

  • split() → divides a string into a list of substrings based on a separator (default is whitespace).

  • join() → combines elements of a list (or any iterable of strings) into a single string, using the string it’s called on as the separator.

80
New cards

String Method — format()

  • The format() method allows you to insert variables or expressions into a string.

  • Provides flexible string formatting for readability, alignment, precision, and more.

  • Works with placeholders marked by {} inside the string.

  • Strings remain immutable; format() returns a new string.

  • Think of {} as blanks to fill in.

  • Positional {0}, {1} → fill based on order.

  • Keyword {name} → fill based on named argument.

  • You are able to mix numbered and named, but avoid mixing unnumbered {} with numbered {0} in the same string.

  • Useful for creating readable, formatted output instead of concatenation.

81
New cards

Traversal

Traversal → Processing a collection one item at a time from start to finish. 

  • With strings, traversal means visiting each character in order (left → right). 

82
New cards

How ‘for’ Works “By Item”

  • A for loop in Python iterates directly over the items in a sequence (like a list, string, or tuple) or any iterable object.

  • A ‘for’ loop can iterate directly over items of any sequence (lists, strings, ranges). 

  • The loop variable takes each item in turn; the loop body runs once per item. 

  • Since a string is a sequence of characters, the ‘for’ loop iterates over every character automatically. 

83
New cards

The Accumulator Pattern - Strings

  • The accumulator pattern with strings means starting with an empty string and then building it step by step inside a loop.

  • Each iteration adds (concatenates) more characters or words to the string.

  • Since strings are immutable, each update creates a new string stored back in the accumulator variable.

Steps:

  1. Initialize an empty string ("").

  2. Loop through items (like characters or words).

  3. Update the string by concatenating the current item.

  4. Use the final result after the loop ends.

Use of ‘not in’ → Helps avoid the use of a very large ‘if’ statement that checks each of the individual vowel characters. 

84
New cards

Methods — Lists

  • List methods are built-in functions that operate on lists, allowing you to add, remove, sort, or otherwise modify list elements.

  • They are called using dot notation: list.method(arguments).

  • Unlike strings, lists are mutable, so many methods modify the list in place instead of returning a new one.

85
New cards

List Methods — Types

List methods in Python can be grouped by how they behave:

  1. Mutator Methods → Change (mutate) the list directly, no return value (return None).

  2. Return Methods → Do not change the list; instead, they return information or a new object.

  3. Hybrid Methods → Change the list and also return a useful value.

  • Mutator = a worker who rearranges the warehouse but doesn’t report back.

  • Return = a worker who only gives you information but doesn’t touch anything.

  • Hybrid = a worker who rearranges something and hands you a piece of it.

1. Mutator Methods (change the list, return None):

  • append(x) → adds item to end.

  • extend(iterable) → adds multiple items.

  • insert(i, x) → inserts at index.

  • remove(x) → removes first occurrence.

  • sort() → sorts list in place.

  • reverse() → reverses list in place.

  • clear() → empties the list.


2. Return Methods (don’t change the list):

  • index(x) → returns index of x.

  • count(x) → counts occurrences of x.

  • copy() → returns a shallow copy.

3. Hybrid Methods (change list + return value):

  • pop(i) → removes item at index i (default: last) and returns it.

86
New cards

List Methods — Returning ‘None’

Methods like ‘append’, ‘sort’, and ‘reverse’ all return ‘None’. This means that re-assigning ‘mylist’ to the result of sorting ‘mylist’ will result in losing the entire list.

 

87
New cards

Append vs. Concatenate — Lists

Append → Mutates in place, changes the same list object. Adds one item as a single element.

Concatenation with ‘+’ → Creates a new list, you must assign the result. The right-hand side must be a list (not a bare string). 

Step 1: Initial assignment

  • origlist = [45, 32, 88]

  • A list object [45, 32, 88] is created in memory.

  • The variable name origlist now refers (points) to this list object.

Step 2: Concatenation

  • The expression origlist + ["cat"] is evaluated.

  • In Python, the + operator on lists does not mutate the original list.

  • Instead, it creates a brand-new list object that contains:


Step 3: Reassignment

  • The result of origlist + ["cat"] (the new list) is assigned back to the variable origlist.

  • Now, origlist points to the new list object.

  • The old list [45, 32, 88] still exists in memory, but nothing is pointing to it anymore (unless you had another variable referring to it).

  • Since no variables reference the old list, Python’s garbage collector will eventually clean it up.

Key Idea:

  • Mutating: Methods like .append() or .extend() change the list in place without creating a new one.

  • Concatenation with +: Creates a new list object and then reassigns the variable.

88
New cards

Nested Lists

A list that contains another list as an element. 

Accessing Items:

Modifying Elements Inside a Nested List:

  • Mutate the inner list directly through the outer reference. 

Length and Slicing: