AW Dev Rethought

Truth can only be found in one place: the code - Robert C. Martin

🧠 Python DeepCuts — 💡 Function Objects Deep Dive


Description:

In Python, functions are not just blocks of code — they are objects.

That means they:

  • have attributes
  • carry state
  • can be passed around
  • can even capture variables

Understanding this unlocks how decorators, closures, and callbacks really work.


🧩 Functions Are First-Class Objects

A function behaves like any other object.

def greet():
    return "hello"

type(greet), callable(greet)

This allows:

  • passing functions as arguments
  • returning functions from functions
  • storing functions in data structures

🧠 The __code__ Object

Every function carries a __code__ object — its internal blueprint.

def add(a, b):
    return a + b

code = add.__code__
code.co_argcount, code.co_varnames

It contains:

  • argument count
  • variable names
  • compiled bytecode

This is how Python knows how to execute the function.


🔄 Default Arguments (__defaults__)

Default values are stored separately from the code.

def greet(name="Guest"):
    return name

greet.__defaults__

This explains:

  • why defaults persist across calls
  • how mutable default bugs happen

🧬 Closures (__closure__)

Functions can capture variables from outer scopes.

def outer(x):
    def inner():
        return x
    return inner

fn = outer(10)
fn.__closure__[0].cell_contents

Closures store:

  • references to captured variables
  • inside cell objects

This is the foundation of decorators and function factories.


🔍 Function Metadata

Functions carry useful metadata:

def sample():
    """Example"""
    pass

sample.__name__, sample.__doc__, sample.__module__

This is used by:

  • debuggers
  • frameworks
  • documentation tools

🧠 Functions as Data

Because functions are objects, they can be used dynamically.

def execute(fn, x, y):
    return fn(x, y)

This enables:

  • higher-order functions
  • callbacks
  • flexible APIs

✅ Key Points

  • Functions are full objects in Python
  • __code__ stores execution details
  • __defaults__ holds default arguments
  • __closure__ stores captured variables
  • Functions can be passed, stored, and returned

Functions don’t just run — they carry structure and state.


Code Snippet:

import inspect

def greet():
    return "hello"

print(type(greet), callable(greet))

def add(a, b):
    return a + b

code = add.__code__
print(code.co_argcount, code.co_varnames)

def greet(name="Guest"):
    return name

print(greet.__defaults__)

def outer(x):
    def inner():
        return x
    return inner

fn = outer(10)
print(fn.__closure__[0].cell_contents)

def sample():
    """Example function"""
    pass

print(sample.__name__, sample.__doc__, sample.__module__)

def execute(fn, x, y):
    return fn(x, y)

print(execute(add, 2, 3))

Link copied!

Comments

Add Your Comment

Comment Added!