PONY λ M2 Modula-2

JavaScript.CodeCompared.To/Python

An interactive executable cheatsheet comparing JavaScript and Python

JavaScript (ES2025) Python 3.13
Output & Running
Hello, World
console.log("Hello, World!");
print("Hello, World!")
Python's print() is the equivalent of console.log() — both append a trailing newline. Python statements end at the newline, with no semicolons and no braces; indentation defines structure.
Printing multiple values
const name = "Alice"; const age = 30; console.log(name, age); console.log(`${name} is ${age}`);
name = "Alice" age = 30 print(name, age) print(f"{name} is {age}")
Python f-strings (f"...") interpolate with {...}, the counterpart to JavaScript template literals. Like console.log(), Python's print() separates multiple arguments with spaces.
Comments
// a single-line comment /* A multi-line block comment. */ console.log("done");
# a single-line comment """ A multi-line string, often used as a block comment or docstring. """ print("done")
Python uses # for single-line comments and has no dedicated block-comment syntax — a triple-quoted string serves that role and doubles as a documentation string when placed at the top of a function or module.
Variables & Types
Declaring variables
let message = "hi"; let count = 3; count = count + 1; console.log(message, count);
message = "hi" count = 3 count = count + 1 print(message, count)
Python has no declaration keyword — assignment both creates and binds a variable, so there is no let or const. The idiomatic naming convention is snake_case rather than JavaScript's camelCase.
Constants
const MAX_RETRIES = 3; console.log(MAX_RETRIES);
MAX_RETRIES = 3 print(MAX_RETRIES)
Python has no real const — an all-caps name is only a convention signalling "do not reassign," and nothing in the language enforces it, unlike JavaScript's const.
Dynamic typing
let value = 42; console.log(typeof value); value = "now a string"; console.log(typeof value);
value = 42 print(type(value)) value = "now a string" print(type(value))
Both languages are dynamically typed. Python's type() built-in returns the class object (e.g. <class 'int'>), where JavaScript's typeof returns a string.
null and undefined vs. None
let result = null; let notAssigned; console.log(result === null, notAssigned === undefined);
result = None print(result is None)
Python collapses JavaScript's two empty values (null and undefined) into a single None. The idiomatic test is is None, using identity rather than ==.
Multiple assignment & swapping
let [first, second] = [1, 2]; [first, second] = [second, first]; console.log(first, second);
first, second = 1, 2 first, second = second, first print(first, second)
Python's tuple unpacking needs no brackets: first, second = 1, 2. The swap idiom a, b = b, a is the direct counterpart to JavaScript's array-destructuring swap.
Strings
String interpolation
const name = "World"; console.log(`Hello, ${name}!`); console.log(`2 + 2 = ${2 + 2}`);
name = "World" print(f"Hello, {name}!") print(f"2 + 2 = {2 + 2}")
Python f-strings embed expressions in {...}, just as JavaScript template literals use ${...}. The f prefix is required — a plain string does not interpolate.
Concatenation & repetition
const greeting = "ab" + "cd"; const line = "-".repeat(5); console.log(greeting, line);
greeting = "ab" + "cd" line = "-" * 5 print(greeting, line)
Both concatenate with +. For repetition Python overloads the * operator ("-" * 5), which is more concise than JavaScript's repeat() method.
Common string methods
const text = "Hello World"; console.log(text.toUpperCase()); console.log(text.toLowerCase()); console.log(text.replace("World", "Py"));
text = "Hello World" print(text.upper()) print(text.lower()) print(text.replace("World", "Py"))
Python spells these upper() and lower() rather than toUpperCase()/toLowerCase(). Note that Python's replace() replaces all occurrences by default, whereas JavaScript's string replace() changes only the first.
Slicing & substrings
const word = "javascript"; console.log(word.slice(0, 4)); console.log(word.slice(-6));
word = "javascript" print(word[0:4]) print(word[-6:])
Python uses bracket slice syntax word[start:end] instead of a slice() method, and it supports a third "step" value (word[::2]) that JavaScript has no direct equivalent for.
Split & join
const csv = "a,b,c"; const parts = csv.split(","); console.log(parts); console.log(parts.join("-"));
csv = "a,b,c" parts = csv.split(",") print(parts) print("-".join(parts))
A famous gotcha: Python's join() is called on the separator ("-".join(parts)), not on the list, which is the reverse of JavaScript's parts.join("-").
Multi-line strings
const poem = `Roses are red Violets are blue`; console.log(poem);
poem = """Roses are red Violets are blue""" print(poem)
Python's triple-quoted strings ("""...""") span multiple lines, serving the same purpose as JavaScript's backtick template literals.
Numbers
Arithmetic & division
console.log(7 + 2, 7 - 2, 7 * 2); console.log(7 / 2); console.log(Math.floor(7 / 2)); console.log(7 % 2);
print(7 + 2, 7 - 2, 7 * 2) print(7 / 2) print(7 // 2) print(7 % 2)
Python distinguishes true division (/, always a float) from floor division (//, integer result), so you write 7 // 2 instead of Math.floor(7 / 2). Python also has a real integer type, unlike JavaScript's single number type.
Exponentiation
console.log(2 ** 10);
print(2 ** 10)
The ** exponentiation operator is identical in both languages. Python integers have unlimited precision, so 2 ** 1000 computes exactly rather than overflowing.
Parsing & truncating
console.log(parseInt("42"), parseFloat("3.14")); console.log(Math.trunc(3.9));
print(int("42"), float("3.14")) print(int(3.9))
Python converts with the int() and float() built-ins. Unlike JavaScript's parseInt(), which stops at the first non-digit, Python's int("42abc") raises a ValueError — conversion is strict.
Math functions
console.log(Math.sqrt(16), Math.floor(3.7), Math.ceil(3.2));
import math print(math.sqrt(16), math.floor(3.7), math.ceil(3.2))
Python's math functions live in the math module, which you must import, rather than on a global object like JavaScript's Math.
Formatting numbers
const amount = 1234.5; console.log(amount.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2, }));
amount = 1234.5 print(f"{amount:,.2f}")
Python's format mini-language packs grouping and precision into a compact spec ({amount:,.2f}), far terser than JavaScript's toLocaleString() options object.
Arrays & Lists
Creating & indexing
const fruits = ["apple", "banana", "cherry"]; console.log(fruits[0], fruits[fruits.length - 1], fruits.length);
fruits = ["apple", "banana", "cherry"] print(fruits[0], fruits[-1], len(fruits))
Python lists support negative indexing, so the last element is simply fruits[-1]. Length comes from the len() built-in rather than a .length property.
Adding & removing elements
const numbers = [1, 2, 3]; numbers.push(4); numbers.pop(); numbers.unshift(0); console.log(numbers);
numbers = [1, 2, 3] numbers.append(4) numbers.pop() numbers.insert(0, 0) print(numbers)
Python uses append() where JavaScript uses push(), and insert(0, value) where JavaScript uses unshift(). pop() exists in both.
Slicing arrays
const nums = [0, 1, 2, 3, 4, 5]; console.log(nums.slice(1, 4)); console.log(nums.filter((_, index) => index % 2 === 0));
nums = [0, 1, 2, 3, 4, 5] print(nums[1:4]) print(nums[::2])
List slicing is built into Python's bracket syntax, including a step value: nums[::2] takes every other element, which in JavaScript requires a filter() on the index.
Transforming with map
const numbers = [1, 2, 3, 4]; const doubled = numbers.map(number => number * 2); console.log(doubled);
numbers = [1, 2, 3, 4] doubled = [number * 2 for number in numbers] print(doubled)
The idiomatic Python equivalent of .map() is a list comprehension: [expr for item in iterable]. There is also a map() built-in, but comprehensions are more common and readable.
Filtering elements
const numbers = [...Array(10).keys()]; const evens = numbers.filter(number => number % 2 === 0); console.log(evens);
numbers = list(range(10)) evens = [number for number in numbers if number % 2 == 0] print(evens)
A comprehension's trailing if clause does the work of .filter(). Generating a range is cleaner than in JavaScript: range(10) yields 0 through 9.
Reducing to a single value
const numbers = [1, 2, 3, 4]; console.log(numbers.reduce((total, number) => total + number, 0));
numbers = [1, 2, 3, 4] print(sum(numbers)) from functools import reduce print(reduce(lambda total, number: total + number, numbers, 0))
For the common case of summing, Python offers a built-in sum(). The general fold lives in functools.reduce(), the counterpart to JavaScript's .reduce().
Sorting
const words = ["banana", "apple", "cherry"]; console.log([...words].sort()); console.log([...words].sort((a, b) => a.length - b.length));
words = ["banana", "apple", "cherry"] print(sorted(words)) print(sorted(words, key=len))
Python's sorted() returns a new list and takes a key function instead of a comparator. Crucially, it sorts numbers numerically by default — no comparator needed — avoiding JavaScript's lexicographic-sort surprise.
Spread & rest
const [first, ...rest] = [1, 2, 3, 4]; console.log(first, rest); const combined = [...[1, 2], ...[3, 4]]; console.log(combined);
first, *rest = [1, 2, 3, 4] print(first, rest) combined = [*[1, 2], *[3, 4]] print(combined)
Python's starred expressions (*rest, [*a, *b]) mirror JavaScript's spread and rest syntax for both unpacking and combining sequences.
Sets
const a = new Set([1, 2, 3]); const b = new Set([2, 3, 4]); console.log([...a].filter(value => b.has(value))); console.log([...new Set([...a, ...b])]);
a = {1, 2, 3} b = {2, 3, 4} print(sorted(a & b)) print(sorted(a | b))
Python sets have literal syntax ({1, 2, 3}) and operator overloads for intersection (&) and union (|), which JavaScript's Set lacks — there you fall back to filter and spread.
Objects & Dicts
Creating & accessing
const person = { name: "Alice", age: 30 }; console.log(person.name); console.log(person.email ?? "n/a");
person = {"name": "Alice", "age": 30} print(person["name"]) print(person.get("email", "n/a"))
Python dictionaries use quoted string keys and bracket access (person["name"]) — there is no dot-notation access. dict.get(key, default) supplies a fallback, the role JavaScript's ?? plays.
Adding & updating keys
const scores = {}; scores.math = 95; scores.math += 1; console.log(scores);
scores = {} scores["math"] = 95 scores["math"] += 1 print(scores)
Assigning to a missing key creates it in both languages. Python always uses bracket syntax for dictionary keys, even when the key is a simple identifier.
Iterating entries
const person = { name: "Alice", age: 30 }; for (const [key, value] of Object.entries(person)) { console.log(key, value); }
person = {"name": "Alice", "age": 30} for key, value in person.items(): print(key, value)
Python's dict.items() yields key/value pairs directly, so you do not need an Object.entries() wrapper. Tuple unpacking in the loop header reads naturally.
Keys & values
const counts = { a: 1, b: 2 }; console.log(Object.keys(counts)); console.log(Object.values(counts));
counts = {"a": 1, "b": 2} print(list(counts.keys())) print(list(counts.values()))
Python's dict.keys() and dict.values() return lazy view objects; wrap them in list() to materialize them, whereas JavaScript's Object.keys()/Object.values() already return arrays.
Checking for a key
const config = { debug: true }; console.log("debug" in config); console.log("verbose" in config);
config = {"debug": True} print("debug" in config) print("verbose" in config)
The in operator checks dictionary keys in Python, just as it checks object keys in JavaScript. Unlike JavaScript, Python's in on a list checks for a value, which is usually what you want.
Merging
const defaults = { color: "red", size: "m" }; const overrides = { size: "l" }; const merged = { ...defaults, ...overrides }; console.log(merged);
defaults = {"color": "red", "size": "m"} overrides = {"size": "l"} merged = {**defaults, **overrides} print(merged)
Python's double-star unpacking ({**a, **b}) merges dictionaries exactly like JavaScript's object spread, with later keys winning.
Objects with any key type
const lookup = new Map(); lookup.set([0, 0].join(","), "origin"); lookup.set([1, 2].join(","), "point"); console.log(lookup.get([0, 0].join(",")));
lookup = {(0, 0): "origin", (1, 2): "point"} print(lookup[(0, 0)])
Python dictionary keys can be any hashable value, including tuples — so a coordinate pair works directly as a key. In JavaScript you would reach for a Map and contend with identity comparison for object keys.
Control Flow
if / else if / else
const score = 75; if (score >= 90) { console.log("A"); } else if (score >= 70) { console.log("B"); } else { console.log("C"); }
score = 75 if score >= 90: print("A") elif score >= 70: print("B") else: print("C")
Python drops the parentheses and braces, using a colon and indentation instead, and spells the chained branch elif rather than else if.
Conditional expression
const age = 20; const status = age >= 18 ? "adult" : "minor"; console.log(status);
age = 20 status = "adult" if age >= 18 else "minor" print(status)
Python's conditional expression reads in English order — a if condition else b — rather than JavaScript's C-style condition ? a : b.
Truthiness
const items = []; if (items.length === 0) { console.log("empty"); } const name = ""; console.log(Boolean(name));
items = [] if not items: print("empty") name = "" print(bool(name))
A welcome difference: an empty list, dict, string, or set is falsy in Python, so if not items: tests emptiness directly — no .length check needed. In JavaScript an empty [] is truthy, which trips up newcomers.
Equality
console.log(1 === 1); console.log("1" === 1); console.log("1" == 1);
print(1 == 1) print("1" == 1) print(1 == 1.0)
Python has a single == that compares by value without JavaScript's string-to-number coercion, so "1" == 1 is False. There is no === because none is needed; use is only for identity (such as is None).
Chained comparisons
const x = 5; console.log(1 < x && x < 10);
x = 5 print(1 < x < 10)
Python lets you chain comparisons mathematically: 1 < x < 10 means exactly what it looks like, with no need for the && that JavaScript requires.
switch vs. match
const command = "start"; switch (command) { case "start": console.log("starting"); break; case "stop": console.log("stopping"); break; default: console.log("unknown"); }
command = "start" match command: case "start": print("starting") case "stop": print("stopping") case _: print("unknown")
Python's match (3.10+) is more powerful than JavaScript's switch: each case is self-contained with no fall-through and no break, and it can destructure structures and bind variables. The wildcard case is case _.
Loops & Iteration
Counting loop
for (let index = 0; index < 3; index++) { console.log(index); }
for index in range(3): print(index)
Python has no C-style three-part for loop. You iterate over range(3), which produces 0, 1, 2. There is no ++ operator — use index += 1 when you need manual increment.
Iterating a collection
for (const color of ["red", "green"]) { console.log(color); }
for color in ["red", "green"]: print(color)
Python's for x in collection iterates values directly — the equivalent of JavaScript's for...of. There is no values-vs-keys footgun like JavaScript's for...in.
Index and value together
["red", "green"].forEach((color, index) => { console.log(index, color); });
for index, color in enumerate(["red", "green"]): print(index, color)
Python's enumerate() yields (index, value) pairs — index first, the reverse of the argument order JavaScript's forEach() callback receives.
while loop
let count = 3; while (count > 0) { console.log(count); count -= 1; }
count = 3 while count > 0: print(count) count -= 1
The while loop is nearly identical, aside from Python's colon and indentation in place of parentheses and braces.
break & continue
for (let number = 0; number < 10; number++) { if (number === 3) continue; if (number === 6) break; console.log(number); }
for number in range(10): if number == 3: continue if number == 6: break print(number)
Both break and continue behave the same. Python additionally supports a for...else clause that runs when the loop finishes without breaking — a feature JavaScript has no equivalent for.
Functions
Defining functions
function greet(name) { return `Hi, ${name}`; } console.log(greet("Alice"));
def greet(name): return f"Hi, {name}" print(greet("Alice"))
Python defines functions with def and an indented body rather than the function keyword and braces. The return statement works the same way.
Default arguments
function greet(name, greeting = "Hello") { return `${greeting}, ${name}`; } console.log(greet("Bob")); console.log(greet("Bob", "Hi"));
def greet(name, greeting="Hello"): return f"{greeting}, {name}" print(greet("Bob")) print(greet("Bob", "Hi"))
Default-argument syntax looks the same, but beware: Python evaluates the default once at definition time, so a mutable default like [] is shared across calls — a classic Python pitfall that JavaScript, which re-evaluates each call, does not have.
Keyword arguments
function makeUser(name, { role = "user", active = true } = {}) { return [name, role, active]; } console.log(makeUser("Alice", { role: "admin" }));
def make_user(name, *, role="user", active=True): return (name, role, active) print(make_user("Alice", role="admin"))
Python has true keyword arguments — role="admin" at the call site — so you do not need JavaScript's options-object pattern. The bare * in the signature forces the following parameters to be passed by name.
Variadic arguments
function total(...numbers) { return numbers.reduce((sum, number) => sum + number, 0); } console.log(total(1, 2, 3, 4));
def total(*numbers): return sum(numbers) print(total(1, 2, 3, 4))
Python's *numbers collects extra positional arguments into a tuple, the counterpart to JavaScript's rest parameter. The built-in sum() then adds them up directly.
Collecting named arguments
function describe(attributes) { return attributes; } console.log(describe({ color: "red", size: "m" }));
def describe(**attributes): return attributes print(describe(color="red", size="m"))
Python's **attributes gathers arbitrary keyword arguments into a dict, so callers pass color="red" directly instead of building an options object as in JavaScript.
Returning multiple values
function minMax(numbers) { return [Math.min(...numbers), Math.max(...numbers)]; } const [low, high] = minMax([3, 1, 4, 1, 5]); console.log(low, high);
def min_max(numbers): return min(numbers), max(numbers) low, high = min_max([3, 1, 4, 1, 5]) print(low, high)
Python returns a tuple (the comma makes it one) and unpacks it on assignment, so you rarely build an explicit array. The built-ins min() and max() accept an iterable directly, with no spread needed.
Closures & Higher-Order Functions
Arrow functions & lambdas
const square = value => value * value; console.log(square(5));
square = lambda value: value * value print(square(5))
Python's lambda is limited to a single expression — it cannot contain statements — so it is far more restricted than a JavaScript arrow function. For anything multi-line, define a named function with def.
Closures & captured state
function makeCounter() { let count = 0; return () => { count += 1; return count; }; } const counter = makeCounter(); console.log(counter(), counter());
def make_counter(): count = 0 def increment(): nonlocal count count += 1 return count return increment counter = make_counter() print(counter(), counter())
Both support closures, but Python requires the nonlocal keyword to reassign a variable from an enclosing scope. Without it, count += 1 would raise an error, since Python would treat count as a new local.
Decorators
function shout(func) { return name => func(name).toUpperCase(); } const greet = shout(name => `hi ${name}`); console.log(greet("alice"));
def shout(func): def wrapper(name): return func(name).upper() return wrapper @shout def greet(name): return f"hi {name}" print(greet("alice"))
Python has first-class decorator syntax: @shout above a definition wraps the function and rebinds its name. JavaScript has no built-in equivalent for functions, so you wrap manually with a higher-order function.
Classes & OOP
Class & constructor
class Dog { constructor(name) { this.name = name; } speak() { return `${this.name} says woof`; } } console.log(new Dog("Rex").speak());
class Dog: def __init__(self, name): self.name = name def speak(self): return f"{self.name} says woof" print(Dog("Rex").speak())
Python's constructor is __init__, instances are created without new (just Dog("Rex")), and every method takes an explicit first parameter self — there is no implicit this.
Inheritance & overriding
class Animal { constructor(name) { this.name = name; } describe() { return `${this.name} is an animal`; } } class Cat extends Animal { describe() { return `${this.name} is a cat`; } } console.log(new Cat("Felix").describe());
class Animal: def __init__(self, name): self.name = name def describe(self): return f"{self.name} is an animal" class Cat(Animal): def describe(self): return f"{self.name} is a cat" print(Cat("Felix").describe())
Python declares the base class in parentheses (class Cat(Animal)) rather than with extends. Method overriding works the same way in both.
Calling the parent constructor
class Base { constructor(value) { this.value = value; } } class Derived extends Base { constructor(value) { super(value); this.doubled = value * 2; } } const derived = new Derived(5); console.log(derived.value, derived.doubled);
class Base: def __init__(self, value): self.value = value class Derived(Base): def __init__(self, value): super().__init__(value) self.doubled = value * 2 derived = Derived(5) print(derived.value, derived.doubled)
Python calls the parent initializer explicitly as super().__init__(value). Unlike JavaScript, Python does not force the super call to come before you assign other attributes.
Static methods
class MathHelper { static add(first, second) { return first + second; } } console.log(MathHelper.add(2, 3));
class MathHelper: @staticmethod def add(first, second): return first + second print(MathHelper.add(2, 3))
Python marks class-level methods with the @staticmethod decorator rather than a static keyword. Python also offers @classmethod, which receives the class itself as its first argument.
Computed properties
class Circle { constructor(radius) { this.radius = radius; } get area() { return 3.14159 * this.radius ** 2; } } console.log(Number(new Circle(2).area.toFixed(2)));
class Circle: def __init__(self, radius): self.radius = radius @property def area(self): return 3.14159 * self.radius ** 2 print(round(Circle(2).area, 2))
Python's @property decorator makes a method accessible as a bare attribute (circle.area, no parentheses) — the same effect as a JavaScript get accessor.
String representation
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return `(${this.x}, ${this.y})`; } } console.log(String(new Point(1, 2)));
class Point: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"({self.x}, {self.y})" print(str(Point(1, 2)))
Python's __str__ dunder method controls how an object converts to a string, the role JavaScript's toString() plays. Python also has __repr__ for an unambiguous developer-facing representation.
Error Handling
try / catch vs. try / except
try { const result = 10 / 0; if (!isFinite(result)) { throw new Error("division by zero"); } } catch (error) { console.log("caught:", error.message); }
try: result = 10 / 0 except ZeroDivisionError as error: print("caught:", error)
Python catches errors with except and can name the specific exception type (ZeroDivisionError) — and unlike JavaScript, dividing by zero genuinely raises an error rather than returning Infinity.
Raising errors
function withdraw(amount) { if (amount < 0) { throw new Error("amount must be positive"); } return amount; } try { withdraw(-5); } catch (error) { console.log(error.message); }
def withdraw(amount): if amount < 0: raise ValueError("amount must be positive") return amount try: withdraw(-5) except ValueError as error: print(error)
Python uses raise where JavaScript uses throw, and the standard library provides specific exception types like ValueError and TypeError rather than a single generic Error.
finally
try { console.log("working"); } finally { console.log("cleanup"); }
try: print("working") finally: print("cleanup")
The finally block runs whether or not an exception occurred, identically in both languages.
Custom exception classes
class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; } } try { throw new ValidationError("invalid input"); } catch (error) { console.log("validation:", error.message); }
class ValidationError(Exception): pass try: raise ValidationError("invalid input") except ValidationError as error: print("validation:", error)
A custom Python exception simply subclasses Exception and often needs nothing more than pass, whereas a JavaScript error class typically must call super(message) and set this.name.
Cleanup: callbacks vs. with
function withTag(name, body) { console.log(`<${name}>`); body(); console.log(`</${name}>`); } withTag("p", () => { console.log("hello"); });
from contextlib import contextmanager @contextmanager def tag(name): print(f"<{name}>") yield print(f"</{name}>") with tag("p"): print("hello")
Python's with statement plus a context manager guarantees setup and teardown around a block — used everywhere for files, locks, and transactions. JavaScript has no with for this, so the equivalent is passing a callback.
Iterators & Generators
Generator functions
function* countUp(limit) { let number = 1; while (number <= limit) { yield number; number += 1; } } console.log([...countUp(3)]);
def count_up(limit): number = 1 while number <= limit: yield number number += 1 print(list(count_up(3)))
Both use yield for lazy generators. Python marks a generator simply by using yield anywhere in a normal def — there is no special function* syntax — and materializes it with list().
Pulling values one at a time
function* squares() { for (let number = 0; number < 5; number++) { yield number * number; } } const values = squares(); console.log(values.next().value); console.log(values.next().value);
def squares(): for number in range(5): yield number * number values = squares() print(next(values)) print(next(values))
Python's next() built-in returns the yielded value directly and raises StopIteration when exhausted, whereas JavaScript's .next() returns a { value, done } object.
Async & Promises
async / await
async function main() { console.log("start"); await new Promise(resolve => setTimeout(resolve, 0)); console.log("end"); } main();
import asyncio async def main(): print("start") await asyncio.sleep(0) print("end") asyncio.run(main())
Both use async/await, but Python's event loop is not implicit: you must start it with asyncio.run(main()), whereas a JavaScript runtime always has one running and you simply call main().
Awaiting several tasks
async function fetchValue(value) { return value * 2; } async function main() { const results = await Promise.all([ fetchValue(1), fetchValue(2), fetchValue(3), ]); console.log(results); } main();
import asyncio async def fetch(value): await asyncio.sleep(0) return value * 2 async def main(): results = await asyncio.gather(fetch(1), fetch(2), fetch(3)) print(results) asyncio.run(main())
Python's asyncio.gather() awaits multiple coroutines concurrently and returns their results in order — the counterpart to JavaScript's Promise.all().
Modules
JSON serialization
const data = { name: "Alice", age: 30 }; const text = JSON.stringify(data); console.log(text); console.log(JSON.parse(text).name);
import json data = {"name": "Alice", "age": 30} text = json.dumps(data) print(text) print(json.loads(text)["name"])
Python's JSON support lives in the json module (which you import), with json.dumps() and json.loads() matching JavaScript's global JSON.stringify() and JSON.parse().
Importing across files
// greetings.js export function hello(name) { return `Hi, ${name}`; } // main.js import { hello } from "./greetings.js"; console.log(hello("Alice"));
# greetings.py def hello(name): return f"Hi, {name}" # main.py from greetings import hello print(hello("Alice"))
Python modules need no export — every top-level name is importable, and you pull names in with from module import name. These examples span multiple files, so they cannot run in this single-file runner.