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.