1. Mutability: Mutable vs. Immutable Objects¶
Core Concept¶
In Python, data types are either mutable (can be changed after creation) or immutable (cannot be changed).
Immutable Types:
int,float,str,tupleMutable Types:
list,dict,set
Example¶
# Immutable Example
num = 10
print(id(num)) # Memory address of num
num = 20
print(id(num)) # New memory address
# Mutable Example
lst = [1, 2, 3]
print(id(lst)) # Memory address of lst
lst.append(4)
print(id(lst)) # Same memory address, content changed4302105816
4302106136
4369398848
4369398848
Immutable types are safer for concurrent programming.
Mutable types are more flexible but require caution to avoid unintended changes.
2. Scoping Rules: LEGB (Local, Enclosing, Global, Built-in)¶
Core Concept¶
Python uses the LEGB rule (Local, Enclosing, Global, Built-in) to determine the scope of a variable. Refer to the provided example and consider creating your own flowchart to visualize how Python resolves variable scope.
Definitions¶
Local: Defined inside a function.
Enclosing: Defined in the enclosing function for nested functions.
Global: Defined at the top level of a script/module.
Built-in: Predefined by Python (e.g.,
print,len).
Example¶
def outer() -> None:
mytext = 'enclosing'
def inner():
nonlocal mytext
mytext = 'modified enclosing'
print(mytext) # Prints: modified enclosing
inner()
print(mytext) # Prints: modified enclosing
mytext = 'global' #not a good practice at all, only for explaining the concept
outer()
print(mytext) # Prints: globalmodified enclosing
modified enclosing
global
Understanding scope prevents bugs caused by unintended variable shadowing or overwriting.
3. Dynamic Typing and Type Hints¶
Core Concept¶
Python variables are dynamically typed, meaning a variable can change its type during runtime. This flexibility is one of Python’s core features but requires careful handling to avoid type-related errors.
Example¶
num = 10 # Integer
mytext = "Hello" # String
lst = [1, 2, 3] # ListType Hints¶
Type hints provide clarity and can help with debugging.
def greet(name: str) -> str:
return f"Hello, {name}!"Dynamic typing offers flexibility, while type hints improve readability and debugging. Tools like mypy can catch type mismatches during development, enhancing code reliability. For example, in large collaborative projects, type hints help team members understand expected inputs and outputs of functions without additional documentation.
4. Custom Objects as Variables¶
Core Concept¶
Variables in Python can reference objects of custom classes.
Example¶
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
person = Person("Alice", 30)
print(person.name, person.age)Alice 30
Custom objects enable encapsulation and reusability in your code. For instance, in a payroll system, defining an Employee class with attributes like name and salary streamlines operations compared to using separate variables for each employee.
5. Debugging Common Variable Errors¶
Example Errors¶
UnboundLocalError: Referencing a local variable before assignment. This error occurs because Python treats variables assigned within a function as local, even if they share the same name as a global variable.
def foo():
print(num)
num = 10
foo()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Cell In[6], line 4
2 print(num)
3 num = 10
----> 4 foo()
Cell In[6], line 2, in foo()
1 def foo():
----> 2 print(num)
3 num = 10
UnboundLocalError: cannot access local variable 'num' where it is not associated with a valueTypeError: Unsupported operations between types.
Debugging Tips¶
Use
print()statements to check variable values.Use a debugger (e.g.,
pdbor an IDE).