Chapters Three and Four Python Program/Notes¶
The Method¶
What’s up? From now on I’m gonna be doing this like this. 1. Take some notes on the chapter. 2. Plug the notes into AI and ask for a program and explain how it uses my notes. 3. Profit.
The Notes¶
Chapter 3 - The Function Object¶
A function is defined using def.
Functions are arguably the most important built in object in python.
Usually used for stuff that you’d need to do more than once.
Functions don’t need return statements.
Variables defined in the function are part of the local table, and can only be used in that function.
Pass by object’s are a use of the local table.
Functions are objects just like everything else in python or most oop languages.
Local variables come and go but attributes are forever.
Attributes are “adjectives” given to “nouns” aka objects.
Functions don’t have names, just variables that reference them. We call that anonymous.
Functions can reference themselves.
A function object is an example of callable. Any object in Python can be made callable by defining the __call__ method.
Chapter 4 - Scope, Lifetime and Closure¶
Python functions exist even when the function isn’t being executed.
Global variables can be used anywhere in a program, local can only be used where they’re created.
You have to declare variables as global if you want them to be global (global myGlobalVar).
This is because assignment creates local variables by default.
Innerfunctions are normal and are functionally (see what I did there?) a local variable to the parent function.
Innerfunctions have access to the outerfunctions variables as if they were global.
Nonlocal just stops a definition from being local.
Closure captures the variables that are in scope at the time a function is defined and makes them available for use when the function is executed.
Closure isn’t always needed.
Closure provides functions access to a private state variable, a self reference, and context to callback functions.
Example Program Demonstrating:¶
Function objects
Scope and lifetime
Local vs global variables
Inner functions
nonlocal
Closures
Callable objects
The Program¶
# ----------------------------
# Global Variable
# ----------------------------
counter = 0 # Global variables can be used anywhere
# ----------------------------
# Basic Function Definition
# ----------------------------
def greet(name):
# Local variable (exists only inside function)
message = f"Hello, {name}!"
print(message)
# No return statement needed
# ----------------------------
# Function as Object
# ----------------------------
def square(x):
return x * x
# Functions don't really have names —
# the variable "square" just references the function object
another_reference = square
# ----------------------------
# Function Referencing Itself (Recursion)
# ----------------------------
def factorial(n):
if n <= 1:
return 1
return n * factorial(n) # Function referencing itself
# ----------------------------
# Using global keyword
# ----------------------------
def increment_global():
global counter # Required to modify global variable
counter += 1
# ----------------------------
# Inner Function + Closure
# ----------------------------
def make_multiplier(factor):
# "factor" becomes part of a closure
def multiply(number):
return number * factor # Access outer function variable
return multiply # Returning inner function
# Create closure
double = make_multiplier(2)
triple = make_multiplier(3)
# ----------------------------
# nonlocal example
# ----------------------------
def outer():
count = 0
def inner():
nonlocal count # Prevents new local variable creation
count += 1
return count
return inner
counter_function = outer()
# ----------------------------
# Making a Callable Object
# ----------------------------
class Adder:
def __init__(self, value):
self.value = value # Attribute (adjective of object)
def __call__(self, other):
return self.value + other
add_five = Adder(5)
# ----------------------------
# Program Execution
# ----------------------------
if __name__ == "__main__":
greet("Alice")
print(square(4))
print(another_reference(5))
print(factorial(5))
increment_global()
print(counter)
print(double(10))
print(triple(10))
print(counter_function())
print(counter_function())
print(add_five(10))
Explanation of Important Concepts¶
Chapter 3 - The Function Object¶
Function defined using
def-greet(),square(),factorial(), etc.Functions are objects -
another_reference = squareproves functions are objects. - The function itself has no permanent name — variables reference it.Functions don’t need return statements -
greet()prints but returns nothing.Local variables -
messageinsidegreet()exists only during execution.Pass-by-object reference -
square(x)receives a reference to an object.Functions can reference themselves -
factorial()is recursive.Callable objects -
Adderdefines__call__so instances behave like functions.Attributes are forever -
self.valueis stored on the object, not temporary like local variables.
Chapter 4 - Scope, Lifetime and Closure¶
Functions exist even when not executing -
squareand others exist in memory before being called.Global vs Local -
counteris global. -messageis local.Assignment creates local variables - Without
global counter, Python would create a new local variable.Inner functions -
multiply()andinner()are local to their outer functions.Inner functions access outer variables -
multiply()usesfactorfrommake_multiplier().nonlocal -
nonlocal countallows modification of outer function variable.Closure -
doubleremembersfactor = 2. -tripleremembersfactor = 3. - Even aftermake_multiplierfinishes, the variable remains alive.Closure provides private state -
counter_functionkeeps its own privatecount.
Summary¶
This program demonstrates:
Functions as first-class objects
Anonymous function references
Recursion
Global vs local scope
Inner functions
nonlocal
Closures maintaining state
Custom callable objects using
__call__
This directly implements nearly every important concept from Chapters 3 and 4 in one cohesive example.