跪拜 Guibai
← Back to the summary

Python for JavaScript Devs: A Side-by-Side Syntax and Toolchain Map

Frontend Developers Quickly Getting Started with Python

image.png

I have some previous Python development experience, but I haven't written it much for two or three years. Recently, while working on some AI-related projects, I've been using Python frequently. As a frontend developer, I don't want to spend a lot of time learning Python from scratch, so I plan to quickly get up to speed by comparing frontend and Python syntax. This analogical learning approach can be applied in many fields beyond just learning Python. Besides introducing how to quickly pick up Python, the more important point of this article is to share this rapid learning mindset.

Small print reminder: This sharing is just a quick-start, basic introduction, not anything advanced. Experts, please go easy. I will also continue to supplement this sharing during my learning process.

Preface

Python and JavaScript are actually very similar; both are weakly typed languages, and their ecosystems share many similarities. My habit is that whenever I want to achieve a certain effect during Python development, I first think about it using a frontend mindset.

For example, in frontend development, I can quickly switch between multiple Node.js versions using nvm to flexibly run projects with different versions. How is this done in Python projects? Answer: pyenv or conda.

Another example: In frontend, third-party packages are referenced and managed through npm. How is this done in Python projects? Answer: pip.

Or a reverse analogy: What are Python lists and dictionaries? A Python list can be understood as an array in JavaScript, and a dictionary is like an object in JavaScript.

With this kind of analogy, you'll find that frontend developers actually don't need to spend a lot of time learning to quickly get started with Python. You can perfectly well learn while developing.

1. Environment and Toolchain

1.1 Environment Installation

Frontend uses nvm to manage multiple Node.js versions. The Python ecosystem has two mainstream solutions: the built-in venv and anaconda (I habitually use anaconda). So, I'll first introduce the installation of anaconda here. Personally, I don't recommend installing Python directly, just as I don't recommend installing Node directly for frontend development; instead, I recommend installing version management tools like nvm.

If you don't like using anaconda, you can also choose to use venv. Here is some comparison content: image.png

Download from the Anaconda official website

image.png

Download and install directly from the official website. Anaconda has two versions: a full version and a mini version. If you are not a heavy user, my suggestion is to download miniconda, which is sufficient. After downloading, you can use the following commands:

# Create an environment with a specified Python version, equivalent to nvm's `nvm install v20.xx.xx` for installing a version
conda create -n myenv python=3.12

# Activate environment (analogous to nvm use), equivalent to `nvm use xxx` version
conda activate myenv

# Deactivate environment
conda deactivate

# List all environments, equivalent to `nvm list`
conda env list

# Export environment (analogous to package.json + node version lock)
conda env export > environment.yml

# Restore environment from file
conda env create -f environment.yml

Note: The commands above use nvm for analogy. It's also necessary to supplement the differences from nvm. Conda's environment activation is terminal-specific. For example, when you open a terminal and execute conda activate myenv, the next time you open a terminal, you will still need to activate it again. It's a one-time effect, unlike nvm, where after executing nvm use xxx, the global node version is switched.

If you must set the Python version globally like nvm, find conda's installation directory, locate the Python executable for the specified version, and add it to your global environment variables.

1.2 Core Tool Comparison Table

Python Ecosystem Node.js Ecosystem Description
python node Runtime
pip npm Package manager
conda / pyenv nvm / fnm Version management tool
pip install xxx npm install xxx Install dependency package
pip uninstall xxx npm uninstall xxx Uninstall dependency package
pip freeze > requirements.txt npm ls --depth=0 Export currently installed packages
requirements.txt package.json Project dependency manifest (simple scenario)
pyproject.toml package.json Project dependency manifest (standard scenario)
pip install -r requirements.txt npm install Install all dependencies from manifest
python -m venv .venv npm install (creates node_modules) Initialize project local dependency environment
.venv/ node_modules/ Project local dependency directory
python --version node --version Check runtime version
pip --version npm --version Check package manager version
python script.py node script.js Run script
python -i node (REPL) Interactive interpreter
which python which node Check current interpreter path

1.3 Virtual Environment ↔ node_modules

Core Analogy:

Node.js:   Project root/node_modules/    ← Generated after npm install, local dependencies
Python:    Project root/.venv/           ← Generated after python -m venv .venv, local interpreter + dependencies

The difference is that Python's virtual environment not only isolates dependencies but also isolates the Python interpreter itself and pip. Each project has a completely independent copy of Python.

# Create virtual environment (analogous to the effect of npm init + npm install)
python -m venv .venv

# Activate virtual environment (Windows)
.venv\Scripts\activate
# Activate virtual environment (macOS / Linux)
source .venv/bin/activate

# After activation, `which python` will point to the Python in .venv/
# Packages installed via pip will also only be installed into .venv/

# Deactivate virtual environment
deactivate

Frontend Habit Analogy: Activating venv ≈ entering an npm workspaces sub-package directory; npm install will only affect the current workspace.


2. Basic Syntax Comparison

2.1 Variables and Basic Types

# ---------- Python ----------      # ---------- JavaScript ----------

# Variable declaration (no need for let/const/var)
name = "hello"                       # let name = "hello";
count = 42                           # let count = 42;
PI = 3.14                            # const PI = 3.14;
is_done = True                       # let isDone = true;
nothing = None                       # let nothing = null;  (None ≈ null)

# Type checking
type(name)   # <class 'str'>          # typeof name    // 'string'
isinstance(name, str)  # True        # name instanceof String  // false (primitive type)

2.2 Strings

# ---------- Python ----------       # ---------- JavaScript ----------

name = "Alice"
f"Hello, {name}!"                    # `Hello, ${name}!`
"Hello, {}!".format(name)            # "Hello, " + name + "!"

# Multi-line strings
text = """                           # const text = `
Multi-line                           # Multi-line
text                                  # text
"""                                  # `;

# Common methods
"hello".upper()    # "HELLO"        # "hello".toUpperCase()
"HELLO".lower()    # "hello"        # "HELLO".toLowerCase()
"  hi  ".strip()   # "hi"           # "  hi  ".trim()
"a,b,c".split(",") # ['a','b','c']  # "a,b,c".split(",")
",".join(["a","b","c"]) # "a,b,c"   # ["a","b","c"].join(",")
"abc".startswith("a")  # True       # "abc".startsWith("a")
"abc".endswith("c")    # True       # "abc".endsWith("c")
"hello" in "hello world"  # True    # "hello world".includes("hello")
len("hello")  # 5                    # "hello".length

2.3 Numbers and Booleans

# ---------- Python ----------       # ---------- JavaScript ----------

# Operations are the same: + - * / // (floor division) % **
10 / 3    # 3.333...                 # 10 / 3    // 3.333...
10 // 3   # 3  (floor division)      # Math.floor(10 / 3)  // 3
10 % 3    # 1                        # 10 % 3    // 1
2 ** 10   # 1024                     # 2 ** 10   // 1024

# Booleans (note capitalization)
True, False                          # true, false
not True       # False               # !true
True and False # False               # true && false
True or False  # True                # true || false

# "Falsy" values in boolean context (Python is stricter)
# Falsy: False, None, 0, 0.0, "", [], {}, set(), ()
# Note: [] and {} are falsy in Python — use `if my_list:` directly to check

2.4 Lists ↔ Arrays

# ---------- Python ----------       # ---------- JavaScript ----------

items = [1, 2, 3]                    # const items = [1, 2, 3];
items[0]         # 1                 # items[0]
items[-1]        # 3 (last element)  # items[items.length - 1]
items[0:2]       # [1, 2] (slicing)  # items.slice(0, 2)

# Common operations
items.append(4)     # [1,2,3,4]      # items.push(4)
items.pop()         # 4, items becomes [1,2,3]  # items.pop()
items.insert(0, 0)  # [0,1,2,3]      # items.unshift(0)
items.remove(2)     # [0,1,3]         # No direct equivalent method, need splice+indexOf
len(items)          # 3              # items.length
3 in items          # True           # items.includes(3)

# List comprehensions (one of Python's most practical syntax sugars)
[x*2 for x in range(5)]  # [0,2,4,6,8]  # [0,1,2,3,4].map(x => x*2)
[x for x in range(10) if x % 2 == 0]   # [0,2,4,6,8]   # Equivalent to .filter().map()

2.5 Dictionaries ↔ Objects / Map

# ---------- Python ----------       # ---------- JavaScript ----------

user = {                             # const user = {
    "name": "Alice",                 #   name: "Alice",
    "age": 25                        #   age: 25
}                                    # };

user["name"]    # "Alice"           # user["name"]  or user.name
user.get("name")  # "Alice"         # user?.name
user.get("email", "N/A")  # "N/A"   # user.email ?? "N/A"

# Iteration
for key in user:                     # for (const key in user)
    print(key, user[key])            #   console.log(key, user[key])

for key, val in user.items():        # for (const [key, val] of Object.entries(user))
    print(key, val)                  #   console.log(key, val)

# Merging dictionaries
{**a, **b}           # Python 3.5+  # { ...a, ...b }
a | b                 # Python 3.9+  # { ...a, ...b }

# keys / values
user.keys()          # dict_keys     # Object.keys(user)
user.values()        # dict_values   # Object.values(user)

2.6 Tuples ↔ Immutable Arrays (readonly tuple)

# ---------- Python ----------       # ---------- TypeScript ----------

point = (3, 4)                       # const point: [number, number] = [3, 4];
x, y = point      # Destructuring    # const [x, y] = point;

# Tuples are immutable
# point[0] = 5    # ❌ Error         # point[0] = 5;  // JS arrays can be modified...

# Single-element tuple note the comma
single = (42,)    # Comma is required, otherwise (42) is just the number 42

2.7 Sets ↔ Set

# ---------- Python ----------       # ---------- JavaScript ----------

tags = {"a", "b", "c"}               # const tags = new Set(["a", "b", "c"]);
tags.add("d")                        # tags.add("d")
"a" in tags  # True                  # tags.has("a")

# Set operations
a = {1, 2, 3}
b = {2, 3, 4}
a & b   # {2, 3}   Intersection      # No built-in intersection operation
a | b   # {1,2,3,4} Union            #
a - b   # {1}       Difference       #

2.8 Control Flow

# ---------- Python ----------       # ---------- JavaScript ----------

# if / elif / else
if score >= 90:                      # if (score >= 90) {
    grade = "A"                      #   grade = "A";
elif score >= 80:                    # } else if (score >= 80) {
    grade = "B"                      #   grade = "B";
else:                                # } else {
    grade = "C"                      #   grade = "C";
                                     # }

# Ternary expression
x = "yes" if ok else "no"            # const x = ok ? "yes" : "no";

# for loop (Python's for only iterates, not C-style three-part)
for item in items:                   # for (const item of items)
    print(item)                      #   console.log(item);

for i in range(5):                   # for (let i = 0; i < 5; i++)
    print(i)                         #   console.log(i);

for i, val in enumerate(items):      # items.forEach((val, i) => { ... })
    print(i, val)

# while
while count > 0:                     # while (count > 0) {
    count -= 1                       #   count--;
                                     # }

# No do-while, no switch-case (Python 3.10 introduced match-case similar to switch)
match status:
    case 200:
        print("OK")
    case 404:
        print("Not Found")
    case _:                          # default
        print("Unknown")

2.9 Functions

# ---------- Python ----------       # ---------- JavaScript ----------

def greet(name):                     # function greet(name) {
    return f"Hello, {name}"          #   return `Hello, ${name}`;
                                     # }

# Default parameters
def greet(name="World"):             # function greet(name = "World") {
    return f"Hello, {name}"          #   return `Hello, ${name}`;
                                     # }

# Variadic parameters *args ↔ ...rest
def sum_all(*args):                  # function sumAll(...args) {
    return sum(args)                 #   return args.reduce((a,b) => a+b, 0);
                                     # }

# Keyword arguments **kwargs ↔ object destructuring
def create_user(**kwargs):           # function createUser({ name, age } = {}) {
    print(kwargs.get("name"))        #   console.log(name);
                                     # }

# Anonymous functions lambda ↔ arrow functions
square = lambda x: x * x             # const square = x => x * x;

# Common use case: sort key
items.sort(key=lambda x: x["age"])   # items.sort((a, b) => a.age - b.age);

# No hoisting! Functions must be defined before they are called

2.10 Exception Handling

# ---------- Python ----------       # ---------- JavaScript ----------

try:                                 # try {
    result = 10 / 0                  #   const result = 10 / 0;
except ZeroDivisionError as e:       # } catch (e) {
    print(f"Division by zero error: {e}") #   console.log(`Error: ${e.message}`);
except Exception as e:               # }
    print(f"Other error: {e}")       # // JS can only catch one, need instanceof to differentiate
else:                                # // Python-specific else: executes when no exception occurs
    print("Everything is fine")
finally:                             # } finally {
    print("Executes whether there is an exception or not") #   console.log("finally");
                                     # }

# Raise exception
raise ValueError("Invalid parameter") # throw new Error("Invalid parameter");

2.11 Classes

# ---------- Python ----------       # ---------- JavaScript ----------

class Animal:                        # class Animal {
    def __init__(self, name):        #   constructor(name) {
        self.name = name             #     this.name = name;
                                     #   }
    def speak(self):                 #   speak() {
        return f"{self.name}..."     #     return `${this.name}...`;
                                     #   }
                                     # }

class Dog(Animal):                   # class Dog extends Animal {
    def __init__(self, name, breed): #   constructor(name, breed) {
        super().__init__(name)       #     super(name);
        self.breed = breed           #     this.breed = breed;
                                     #   }
    def speak(self):                 #   speak() {
        return f"{self.name} woof"   #     return `${this.name} woof`;
                                     #   }
                                     # }

# All methods require the self parameter (analogous to JS's this, but explicitly passed)
# Private attribute convention: prefix _ or __
# self._secret = 1    # Conventionally private (analogous to JS _secret convention)
# self.__private = 1  # Name mangling, truly private (but can be bypassed)

3. Modules and Package Management

3.1 import ↔ require / import

# ---------- Python ----------         # ---------- JavaScript ----------

# Import entire module
import os                              # const os = require("os");
os.path.join("a", "b")                # os.path.join("a", "b")

# Import specific content
from os import path                    # const { join } = require("path");
from os.path import join, exists       # const { join, exists } = require("path");

# Alias
import numpy as np                     # const np = require("numpy");  // No native alias support
from math import sqrt as sq            # // JS requires manual: const sq = Math.sqrt;

# Import all (not recommended, pollutes namespace)
from math import *                     # // No direct equivalent in JS

3.2 Package Management Comparison

Python Node.js Description
pip install requests npm install axios Install and write to dependencies
pip install requests==2.28 npm install [email protected] Install specific version
requirements.txt package.json (dependencies) Project dependency manifest
pip freeze npm ls --depth=0 View installed packages
pip install -r requirements.txt npm install Install from manifest
.venv/ node_modules/ Local dependency directory
pip list npm list --depth=0 List installed packages
pip uninstall requests npm uninstall axios Uninstall package

3.3 pyproject.toml (Modern Python Project Standard)

Earlier, requirements.txt was used as an analogy for package.json, but a more accurate comparison is pyproject.toml:

# pyproject.toml                               # package.json
[project]                                      # {
name = "my-project"                            #   "name": "my-project",
version = "1.0.0"                              #   "version": "1.0.0",
dependencies = [                               #   "dependencies": {
    "fastapi>=0.100",                          #     "fastapi": "^0.100",
    "uvicorn>=0.23",                           #     "uvicorn": "^0.23"
]                                              #   },
                                               #
[project.optional-dependencies]                #   "devDependencies": {
dev = [                                        #     "pytest": "^7.0",
    "pytest>=7.0",                             #     "ruff": "^0.1"
    "ruff>=0.1",                               #   }
]                                              # }

[tool.pytest.ini_options]                      # // jest config is usually in jest.config.js
testpaths = ["tests"]                          #

4. Common Standard Library Quick Reference

Python "comes with batteries included" — the standard library is much richer than Node.js's, often eliminating the need for third-party packages.

4.1 File and Path Operations

Python (Standard Library) Node.js (Standard Library)
import os require("os")
os.path.join("a", "b") path.join("a", "b")
os.path.dirname(p) path.dirname(p)
os.path.basename(p) path.basename(p)
os.path.exists(p) fs.existsSync(p)
os.makedirs("a/b", exist_ok=True) fs.mkdirSync("a/b", { recursive: true })
os.listdir(".") fs.readdirSync(".")

For file reading and writing, pathlib (Python 3.4+, more modern) is recommended:

from pathlib import Path

# Path joining (analogous to path.join)
p = Path("src") / "app" / "main.py"    # src/app/main.py

# Read and write files
text = Path("file.txt").read_text(encoding="utf-8")
Path("file.txt").write_text("hello", encoding="utf-8")

# Traverse directory (analogous to fs.readdirSync recursive)
for f in Path("src").rglob("*.py"):
    print(f)

5. Project Structure

5.1 Typical Project Layout Comparison

Node.js Project:

my-project/
├── node_modules/          # Dependencies
├── src/
│   ├── routes/
│   ├── services/
│   └── index.js           # Entry point
├── package.json
├── .env
├── .gitignore
└── README.md

Python Project:

my-project/
├── .venv/                 # Dependencies (analogous to node_modules)
├── src/                   # Source code (or use package name)
│   ├── __init__.py        # Marks as a package (analogous to package.json's "main" + ESM)
│   ├── routes/
│   │   ├── __init__.py
│   │   └── users.py
│   ├── services/
│   │   ├── __init__.py
│   │   └── user_service.py
│   └── main.py            # Entry point
├── tests/
│   ├── __init__.py
│   └── test_users.py
├── pyproject.toml         # Project configuration (analogous to package.json)
├── requirements.txt       # Dependency manifest (old style, still common)
├── .env
├── .gitignore
└── README.md

5.2 __init__.py ↔ package.json exports

__init__.py indicates that the current directory is a package, similar to how a directory in Node.js containing a package.json or index.js identifies it as a module entry point. Python 3.3+ supports implicit namespace packages (can exist without __init__.py), but it's customary to keep it, especially when there is initialization logic.

6. Asynchronous Programming

6.1 Core Concept Comparison

Python JavaScript
async def async function
await await
asyncio.run(main()) main().catch(console.error)
asyncio.gather(*tasks) Promise.all(tasks)
asyncio.create_task() Directly fn() returns a Promise
asyncio.sleep(1) setTimeout + Promise
Coroutine Promise
Event Loop Event Loop (libuv)

6.2 Code Comparison

# ---------- Python ----------         # ---------- JavaScript ----------

import asyncio                         #
                                       #
async def fetch_user(id: int):         # async function fetchUser(id) {
    await asyncio.sleep(1)             #   await new Promise(r => setTimeout(r, 1000));
    return {"id": id, "name": "A"}     #   return { id, name: "A" };
                                       # }
async def main():                      # async function main() {
    # Concurrent execution             #
    users = await asyncio.gather(      #   const users = await Promise.all([
        fetch_user(1),                 #     fetchUser(1),
        fetch_user(2),                 #     fetchUser(2),
    )                                  #   ]);
    print(users)                       #   console.log(users);
                                       # }
asyncio.run(main())                    # main();

6.3 Key Differences

Difference Point Python JavaScript
Coroutine start method Does not automatically execute before await call Promise starts executing upon creation, await just waits for the result
Top-level await Wrapped by asyncio.run() Node/Deno natively supports top-level await
Concurrency model Single-threaded + coroutines (truly only one thread running) Single-threaded + event loop (same)
CPU-intensive tasks Requires multiprocessing or thread pool Requires Worker Threads
Web framework async support FastAPI / aiohttp / Sanic (mature) Express itself is not natively async, Koa is async-first

7. Build and Deployment

7.1 Bundling vs Non-bundling

Node.js projects are usually bundled (Webpack/Vite/esbuild) before deployment, while Python projects generally do not bundle — deploy source code + dependencies directly.

Node.js Python
npm run build → dist/ No build step, deploy source code directly
Webpack / Vite / esbuild No bundler (or compile with Cython/Nuitka)
.js/.ts.min.js minified bundle .py runs directly

7.2 Dependency Management (Production)

# Node.js
npm ci --production          # Strictly install according to lock file, only install dependencies

# Python
pip install -r requirements.txt    # Install all dependencies
# Or use pip-tools to generate precisely locked requirements.txt
pip-compile pyproject.toml         # Generate requirements.txt (with exact versions of all transitive dependencies)
pip install -r requirements.txt    # Install according to locked versions

7.3 Common Deployment Methods

Method Node.js Python
Direct run node server.js python app.py
Process daemon PM2 systemd / supervisor
Reverse proxy + WSGI/ASGI nginx → node nginx → gunicorn/uvicorn → app
Containerization Docker Docker
Serverless AWS Lambda / Vercel AWS Lambda / Google Cloud Functions

Analogy Summary

When switching from Node.js to Python, just remember these points:

  1. Indentation is curly braces — Python uses indentation to define code blocks, forget about {}.
  2. venv ≈ node_modules + an independent copy of node — Isolated per project.
  3. pip install -r requirements.txtnpm install — Install dependencies.
  4. pyproject.tomlpackage.json — Project configuration (modern way).
  5. def defines functions, class defines classes — Same as JS, but syntax slightly differs.
  6. Python comes with batteries included — The standard library is extremely rich; check the standard library first when you need something.
  7. Type annotations are optional but highly recommended — Combined with Pydantic, Python can have runtime safety far exceeding TS.
  8. No bundling, deploy source code directly — Say goodbye to Webpack/Vite.
  9. uv pip install xxx is faster and more modern — Analogous to pnpm add xxx.

Mindset Summary

This learning method is for when you want to get up to speed quickly. When you need to become an expert in a certain field, I still hope that after getting started, you can maintain a humble attitude, study and learn more, and solidify your foundation.

The analogical learning method is just to help everyone get started quickly, get feedback quickly, and make it easier to persist. Otherwise, for programmers, with so many languages, how much time would it take to learn several more? Moreover, you don't necessarily need to be proficient in every language at work. We only need to be proficient in the ones we commonly use at work, and then use analogical learning for other languages.

Comments

Top 1 from juejin.cn, machine-translated. The original thread is authoritative.

王三岁_

Great article, thanks for sharing.