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 -------------- .. code-block:: python # ---------------------------- # 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 ----------------------------------- 1. Function defined using ``def`` - ``greet()``, ``square()``, ``factorial()``, etc. 2. Functions are objects - ``another_reference = square`` proves functions are objects. - The function itself has no permanent name — variables reference it. 3. Functions don't need return statements - ``greet()`` prints but returns nothing. 4. Local variables - ``message`` inside ``greet()`` exists only during execution. 5. Pass-by-object reference - ``square(x)`` receives a reference to an object. 6. Functions can reference themselves - ``factorial()`` is recursive. 7. Callable objects - ``Adder`` defines ``__call__`` so instances behave like functions. 8. Attributes are forever - ``self.value`` is stored on the object, not temporary like local variables. Chapter 4 - Scope, Lifetime and Closure ------------------------------------------ 1. Functions exist even when not executing - ``square`` and others exist in memory before being called. 2. Global vs Local - ``counter`` is global. - ``message`` is local. 3. Assignment creates local variables - Without ``global counter``, Python would create a new local variable. 4. Inner functions - ``multiply()`` and ``inner()`` are local to their outer functions. 5. Inner functions access outer variables - ``multiply()`` uses ``factor`` from ``make_multiplier()``. 6. nonlocal - ``nonlocal count`` allows modification of outer function variable. 7. Closure - ``double`` remembers ``factor = 2``. - ``triple`` remembers ``factor = 3``. - Even after ``make_multiplier`` finishes, the variable remains alive. 8. Closure provides private state - ``counter_function`` keeps its own private ``count``. 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.