03open 25 min

Functions, modules, and packages: a different kind of project shape

Translate from Node's file/module ecosystem into Python's function style, module imports, and package structure.

by the end of this lesson you can

  • Uses a normal Python function definition
  • Does not invent unnecessary module-level wrapper objects
  • Keeps import and call patterns simple

Overview

JavaScript and Node developers often think in terms of files, exports, package boundaries, and framework conventions. Python's modules and packages solve similar problems, but the structure and cultural defaults feel different.

In JavaScript/Node, you often

organize code around exported functions, object literals, and package-driven boundaries, with CommonJS or ESM shaping how modules connect.

In Python, the common pattern is

to lean on simple modules, explicit imports, and package directories without carrying over Node-specific export habits.

why this difference matters

A lot of early Python awkwardness comes from trying to make modules look and feel like JavaScript modules instead of letting Python's import model stay straightforward.

JavaScript/Node

export function greet(name) {
  return `hello ${name}`;
}

Python

def greet(name):
    return f"hello {name}"

Deeper comparison

JavaScript/Node version

import { readFile } from "node:fs/promises";

export async function loadConfig(path) {
  const raw = await readFile(path, "utf8");
  return JSON.parse(raw);
}

Python version

import json

def load_config(path):
    with open(path, "r", encoding="utf-8") as file:
        return json.load(file)

Reflect

What changes when you stop thinking in terms of exports and start thinking in terms of Python modules and package imports?

what a strong answer notices

A strong answer mentions simpler module surfaces, fewer explicit export lists, and an easier time reading what a file contributes to the package.

Rewrite

Rewrite this small Node module into a Python module and keep the public API obvious without JavaScript-style export ceremony.

Rewrite this JavaScript/Node

export const normalize = (value) => value.trim().toLowerCase();

what good looks like

  • Uses a normal Python function definition
  • Does not invent unnecessary module-level wrapper objects
  • Keeps import and call patterns simple

Practice

Sketch a small Python package layout for a CLI tool you would originally have written in Node. Explain where utilities, commands, and entry logic should live.

success criteria

  • Uses modules and packages naturally
  • Keeps responsibilities separated without JavaScript export patterns leaking through
  • Explains how someone would import or run the code

Common mistakes

  • Trying to reproduce export syntax or index-file patterns from Node in Python.
  • Over-structuring a small Python package before the code needs it.
  • Treating Python imports as if they behave like ESM path conventions.

takeaways

  • A lot of early Python awkwardness comes from trying to make modules look and feel like JavaScript modules instead of letting Python's import model stay straightforward.
  • A strong answer mentions simpler module surfaces, fewer explicit export lists, and an easier time reading what a file contributes to the package.
  • Uses modules and packages naturally