Python vs JavaScript Data Types Comparison

For JavaScript Developers Learning Python

Session Overview

Welcome, JavaScript developers! This guide will help you understand how Python data types compare to JavaScript data types. We'll explore the similarities, differences, and unique features of both languages to ease your transition to Python programming. By understanding these comparisons, you'll be able to apply your JavaScript knowledge while quickly adapting to Python's conventions.

Fundamental Differences

Before diving into specific data types, let's understand some fundamental differences between Python and JavaScript:

Type Systems

// JavaScript
let x = "5";
let y = x * 2;  // y = 10, implicit conversion from string to number

# Python
x = "5"
y = x * 2  # Results in "55", not 10 (string duplication)
y = int(x) * 2  # Now y = 10, explicit conversion needed

Variable Declaration

// JavaScript
let name = "Alice";
const age = 30;

# Python
name = "Alice"
age = 30  # No declaration keywords needed

Truthy and Falsy Values

// JavaScript
if (0) console.log("This won't print");  // 0 is falsy
if ("0") console.log("This will print");  // "0" is truthy

# Python
if 0: print("This won't print")  # 0 is falsy
if "0": print("This will print")  # "0" is truthy

Analogy: Type Systems as Communication Styles

Think of the difference between JavaScript and Python's type systems like different communication styles:

  • JavaScript is like a flexible, accommodating friend who tries to understand what you mean even if you mix languages or use vague terms. They'll make educated guesses about your meaning.
  • Python is like a precise friend who speaks clearly but expects you to be explicit. They won't guess what you mean if you mix languages - you need to translate properly.

Both friends are helpful, but they have different expectations about how you communicate with them.

Primitive Data Types

Numbers

JavaScript Python Key Differences
Number - represents both integers and floating-point numbers

BigInt - for arbitrarily large integers (newer)
int - integers with unlimited precision

float - 64-bit floating-point numbers

complex - complex numbers (a + bj)
• Python has separate int and float types

• Python int has unlimited precision (like BigInt)

• Python has built-in complex numbers

• No NaN or Infinity literals in Python (use float("nan"), float("inf"))
// JavaScript
let num = 42;           // Number
let float = 3.14;       // Number
let bigInt = 1234567890123456789012345678901234567890n;  // BigInt
let notANumber = NaN;   // NaN is a special Number value
let infinity = Infinity;  // Also a special Number value

# Python
num = 42                # int
float_num = 3.14        # float
big_int = 1234567890123456789012345678901234567890  # Still an int, no special syntax
complex_num = 3 + 4j    # complex
not_a_number = float("nan")  # Need to use float() function
infinity = float("inf")  # Need to use float() function

Strings

JavaScript Python Key Differences
String - sequence of characters

Can use single or double quotes

Template literals with backticks
str - immutable sequence of characters

Can use single, double, or triple quotes
• Python strings are immutable (can't be changed after creation)

• Python has triple quotes for multiline strings ("""text""")

• Python uses f-strings for string interpolation (f"Hello {name}")

• Python has no separate character type
// JavaScript
let singleQuoted = 'Hello';
let doubleQuoted = "World";
let template = `Hello, ${name}!`;  // Template literal
let multiline = `This is a
multiline string`;

# Python
single_quoted = 'Hello'
double_quoted = "World"
f_string = f"Hello, {name}!"  # f-string (similar to template literals)
multiline = """This is a
multiline string"""  # Triple quotes

Booleans and None/Null

JavaScript Python Key Differences
true and false (lowercase)

null - explicit absence of value

undefined - uninitialized variable
True and False (capitalized)

None - represents absence of value
• Python booleans are capitalized

• Python has None but no equivalent of undefined

None, False, and 0 are different but all falsy
// JavaScript
let isActive = true;
let noValue = null;
let uninitialized;  // undefined

// Type checking
typeof true;        // "boolean"
typeof null;        // "object" (a historical JavaScript bug)
typeof undefined;   // "undefined"

# Python
is_active = True
no_value = None

# Type checking
type(True)          # 
type(None)          # 

Collection Data Types

Arrays vs Lists

JavaScript Arrays Python Lists Key Differences
Mutable, ordered collections

Can contain mixed types

Methods: push, pop, shift, unshift, slice, splice, etc.
Mutable, ordered collections

Can contain mixed types

Methods: append, extend, insert, remove, pop, etc.
• Python doesn't have push (use append)

• Python uses extend instead of concat

• Python's slice syntax is list[start:end]

• Python doesn't have splice - you use slicing assignment
// JavaScript
let arr = [1, 2, 3, "four", true];
arr.push(5);            // Add to end: [1, 2, 3, "four", true, 5]
arr.pop();              // Remove from end: [1, 2, 3, "four", true]
arr.unshift(0);         // Add to beginning: [0, 1, 2, 3, "four", true]
arr.shift();            // Remove from beginning: [1, 2, 3, "four", true]
let sliced = arr.slice(1, 3);   // [2, 3]
arr.splice(1, 1, "two");  // Replace: [1, "two", 3, "four", true]

# Python
arr = [1, 2, 3, "four", True]
arr.append(5)          # Add to end: [1, 2, 3, "four", True, 5]
arr.pop()              # Remove from end: [1, 2, 3, "four", True]
arr.insert(0, 0)       # Add to beginning: [0, 1, 2, 3, "four", True]
arr.pop(0)             # Remove from beginning: [1, 2, 3, "four", True]
sliced = arr[1:3]      # [2, 3]
arr[1:2] = ["two"]     # Replace: [1, "two", 3, "four", True]

Objects vs Dictionaries

JavaScript Objects Python Dictionaries Key Differences
Key-value pairs (keys are strings or symbols)

Object literal syntax: {key: value}

Methods: Object.keys(), Object.values(), etc.
Key-value pairs (keys can be any immutable type)

Dict literal syntax: {key: value}

Methods: keys(), values(), items(), etc.
• Python dict keys can be any hashable type, not just strings

• Python dict methods are called on the object, not from a global object

• Python has useful methods like get() with default value

• Python dict comprehensions: {k:v for k, v in ...}
// JavaScript
let person = {
    name: "Alice",
    age: 30,
    "likes python": true
};

// Accessing properties
person.name;            // "Alice"
person["likes python"];  // true

// Methods
Object.keys(person);    // ["name", "age", "likes python"]
Object.values(person);  // ["Alice", 30, true]

// Checking if a key exists
"name" in person;       // true

# Python
person = {
    "name": "Alice",
    "age": 30,
    "likes python": True
}

# Accessing properties
person["name"]          # "Alice"
person["likes python"]  # True
# person.name          # Error! No dot notation for arbitrary keys

# Methods
person.keys()           # dict_keys(["name", "age", "likes python"])
person.values()         # dict_values(["Alice", 30, True])
person.items()          # dict_items([("name", "Alice"), ("age", 30), ("likes python", True)])

# Getting with default (no KeyError)
person.get("height", 165)  # 165 (default value if key doesn't exist)

# Checking if a key exists
"name" in person        # True

Analogy: Dictionaries vs Objects

Think of JavaScript objects and Python dictionaries as different types of organizers:

  • JavaScript objects are like filing cabinets where all the labels must be text or symbols. You can access files by opening a specific drawer (dot notation) or by using their label (bracket notation).
  • Python dictionaries are like advanced filing systems where labels can be almost anything (numbers, tuples, strings, etc.) as long as they don't change. You have to use the label lookup system (brackets) to find files, but it comes with many built-in organization helpers (methods).

JavaScript Sets vs Python Sets

JavaScript Sets Python Sets Key Differences
Collection of unique values

Methods: add, delete, has, etc.

Limited mathematical set operations
Collection of unique, hashable objects

Methods: add, remove, discard, etc.

Rich set of mathematical operations
• Python sets can only contain hashable objects

• Python has robust mathematical set operations (union, intersection, etc.)

• Python has set comprehensions: {x for x in ...}

• Python has immutable frozenset type
// JavaScript
let set = new Set([1, 2, 3, 3]);  // Set(3) {1, 2, 3}
set.add(4);             // Set(4) {1, 2, 3, 4}
set.has(2);             // true
set.delete(3);          // Set(3) {1, 2, 4}

// Set operations (ES6+)
let set1 = new Set([1, 2, 3]);
let set2 = new Set([3, 4, 5]);
let union = new Set([...set1, ...set2]);  // Set(5) {1, 2, 3, 4, 5}

# Python
set_a = {1, 2, 3, 3}    # {1, 2, 3}
set_a.add(4)            # {1, 2, 3, 4}
2 in set_a              # True
set_a.remove(3)         # {1, 2, 4}

# Set operations
set1 = {1, 2, 3}
set2 = {3, 4, 5}
union = set1 | set2     # {1, 2, 3, 4, 5}
intersection = set1 & set2  # {3}
difference = set1 - set2    # {1, 2}
symmetric_diff = set1 ^ set2  # {1, 2, 4, 5}

Maps vs Python Dictionaries

// JavaScript Map
let map = new Map();
map.set("key1", "value1");
map.set(42, "value2");  // Keys can be any type
map.get("key1");        // "value1"
map.has(42);            // true
map.delete("key1");     // true

# Python Dictionary (Equivalent to JavaScript Map)
dict_a = {}
dict_a["key1"] = "value1"
dict_a[42] = "value2"   # Keys can be any hashable type
dict_a["key1"]          # "value1"
42 in dict_a            # True
del dict_a["key1"]      # Removes the key

Other Collection Types in Python

Python has several collection types that don't have direct JavaScript equivalents:

# Tuple - immutable sequence
coordinates = (10, 20)  # Can't be modified after creation
first_coord = coordinates[0]  # Access like lists

# Named Tuple - immutable with named fields
from collections import namedtuple
Person = namedtuple('Person', ['name', 'age'])
alice = Person('Alice', 30)
alice.name  # 'Alice' - access by name
alice[0]    # 'Alice' - access by index

# Deque - efficient append/pop at both ends
from collections import deque
queue = deque([1, 2, 3])
queue.append(4)      # Add to right: [1, 2, 3, 4]
queue.appendleft(0)  # Add to left: [0, 1, 2, 3, 4]

# Counter - count occurrences
from collections import Counter
c = Counter("hello")  # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})

Functions and Classes

Functions

JavaScript Functions Python Functions Key Differences
Function declarations or expressions

Arrow functions for concise syntax

Functions are objects with properties
Functions defined with def keyword

Lambda expressions for simple functions

Functions are first-class objects
• Python uses def instead of function

• Python's lambda is more limited than arrow functions

• Python supports advanced parameter features like default values, keyword arguments, and unpacking

• Python functions can have docstrings
// JavaScript Function
function add(a, b) {
    return a + b;
}

// Arrow function
const multiply = (a, b) => a * b;

// Default parameters
function greet(name = "friend") {
    return `Hello, ${name}!`;
}

// Rest parameters
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

# Python Function
def add(a, b):
    return a + b

# Lambda expression (similar to arrow function)
multiply = lambda a, b: a * b

# Default parameters
def greet(name="friend"):
    return f"Hello, {name}!"

# Variable arguments (*args and **kwargs)
def sum(*numbers):
    return sum(numbers)

def person_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

Classes and Objects

JavaScript Classes Python Classes Key Differences
ES6 class syntax

Prototype-based inheritance

Constructor method
Class definition with class keyword

Class-based inheritance

__init__ method as constructor
• Python requires explicit self parameter for methods

• Python uses __init__ instead of constructor

• Python has special "dunder" methods (__str__, __repr__, etc.)

• Python supports multiple inheritance
// JavaScript Class
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    
    greet() {
        return `Hello, my name is ${this.name}`;
    }
    
    // Static method
    static create(name, age) {
        return new Person(name, age);
    }
}

// Inheritance
class Employee extends Person {
    constructor(name, age, title) {
        super(name, age);
        this.title = title;
    }
    
    work() {
        return `${this.name} is working as a ${this.title}`;
    }
}

// Usage
const alice = new Person("Alice", 30);
console.log(alice.greet());

# Python Class
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def greet(self):
        return f"Hello, my name is {self.name}"
    
    # Static method
    @staticmethod
    def create(name, age):
        return Person(name, age)

# Inheritance
class Employee(Person):
    def __init__(self, name, age, title):
        super().__init__(name, age)
        self.title = title
    
    def work(self):
        return f"{self.name} is working as a {self.title}"

# Usage
alice = Person("Alice", 30)
print(alice.greet())

Type Conversion and Checking

Type Conversion

JavaScript Python
Number(value) or +value
String(value) or value.toString()
Boolean(value) or !!value
Array.from(value)
Object.entries(obj), Object.fromEntries(entries)
int(value), float(value)
str(value)
bool(value)
list(value), tuple(value)
dict(items)
// JavaScript
let num = Number("42");    // 42
let str = String(42);      // "42"
let bool = Boolean(1);     // true
let arr = Array.from("abc");  // ["a", "b", "c"]
let obj = Object.fromEntries([["a", 1], ["b", 2]]);  // {a: 1, b: 2}

# Python
num = int("42")          # 42
str_val = str(42)        # "42"
bool_val = bool(1)       # True
arr = list("abc")        # ["a", "b", "c"]
dict_val = dict([("a", 1), ("b", 2)])  # {"a": 1, "b": 2}

Type Checking

JavaScript Python
typeof value - primitive types
value instanceof Constructor - objects
Array.isArray(value) - special case for arrays
type(value) - returns the class/type
isinstance(value, Class) - check inheritance
issubclass(Class, ParentClass) - check class inheritance
// JavaScript
typeof 42;                // "number"
typeof "hello";           // "string"
typeof true;              // "boolean"
typeof undefined;         // "undefined"
typeof {};                // "object"
typeof [];                // "object" (can't distinguish arrays)
typeof null;              // "object" (a JS quirk)

Array.isArray([]);        // true
value instanceof Array;   // true for arrays
value instanceof Object;  // true for any object

# Python
type(42)                 # 
type("hello")            # 
type(True)               # 
type(None)               # 
type({})                 # 
type([])                 # 

isinstance([], list)     # True
isinstance([], object)   # True for any object
issubclass(bool, int)    # True (booleans are a subclass of integers in Python)

Common Pitfalls and Gotchas

Equality Comparisons

// JavaScript has == (loose equality) and === (strict equality)
1 == "1";  // true (loose equality with type coercion)
1 === "1"; // false (strict equality, no type coercion)

// Object equality checks reference, not contents
{} == {};  // false
{} === {}; // false
let obj = {};
obj == obj;  // true

# Python has only == (value equality) and is (identity)
1 == "1"  # False (no type coercion)
1 == 1.0  # True (value equality)

# Object equality checks value, not reference
{} == {}  # True
{} is {}  # False (different objects)
obj = {}
obj is obj  # True

Mutable Default Arguments

// JavaScript - no issue with mutable defaults
function addItem(item, list = []) {
    list.push(item);
    return list;
}

addItem("a");  // ["a"]
addItem("b");  // ["b"]  (new default list each time)

# Python - beware of mutable defaults!
def add_item(item, list=[]):  # DANGER! list created only once
    list.append(item)
    return list

add_item("a")  # ["a"]
add_item("b")  # ["a", "b"]  (same list reused!)

# Correct pattern:
def add_item_safe(item, list=None):
    if list is None:
        list = []
    list.append(item)
    return list

Variable Scoping

// JavaScript - block scope with let/const
function jsScope() {
    if (true) {
        let x = 10;  // Block scoped
        var y = 20;  // Function scoped
    }
    console.log(y);  // 20
    console.log(x);  // ReferenceError: x is not defined
}

# Python - function scope only
def python_scope():
    if True:
        x = 10  # Function scoped
        y = 20  # Function scoped
    print(x)  # 10 - still in scope
    print(y)  # 20 - still in scope

Copying Objects

// JavaScript - shallow copy
let original = {a: 1, b: {c: 2}};
let shallowCopy = {...original};  // ES6 spread syntax
let deepCopy = JSON.parse(JSON.stringify(original));  // Simple deep copy

# Python - shallow copy
original = {'a': 1, 'b': {'c': 2}}
shallow_copy = original.copy()  # or dict(original)
# Python - deep copy
import copy
deep_copy = copy.deepcopy(original)

Practical Examples

Data Processing

// JavaScript
const data = [
    { name: "Alice", age: 30, active: true },
    { name: "Bob", age: 25, active: false },
    { name: "Charlie", age: 35, active: true }
];

// Get active users
const activeUsers = data.filter(user => user.active);

// Map user names to uppercase
const upperNames = data.map(user => user.name.toUpperCase());

// Calculate average age
const averageAge = data.reduce((sum, user) => sum + user.age, 0) / data.length;

# Python
data = [
    {"name": "Alice", "age": 30, "active": True},
    {"name": "Bob", "age": 25, "active": False},
    {"name": "Charlie", "age": 35, "active": True}
]

# Get active users
active_users = [user for user in data if user["active"]]

# Map user names to uppercase
upper_names = [user["name"].upper() for user in data]

# Calculate average age
average_age = sum(user["age"] for user in data) / len(data)

Asynchronous Code

// JavaScript - Promises and async/await
function fetchData() {
    return fetch('https://api.example.com/data')
        .then(response => response.json());
}

// With async/await
async function getData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Error:', error);
    }
}

# Python - asyncio and async/await
import asyncio
import aiohttp

async def fetch_data():
    async with aiohttp.ClientSession() as session:
        async with session.get('https://api.example.com/data') as response:
            return await response.json()

# With async/await
async def get_data():
    try:
        data = await fetch_data()
        return data
    except Exception as e:
        print(f"Error: {e}")

# Running async code
asyncio.run(get_data())

Practice Exercises

Exercise 1: Type Conversion

Write functions in both JavaScript and Python to:

  1. Convert a list of mixed values to their corresponding string representations
  2. Filter out all falsy values from a collection
  3. Calculate the sum of all numeric values in a mixed-type collection

Exercise 2: Data Transformation

Given a list of objects/dictionaries representing people:

  1. Filter to find all people over 30
  2. Transform the data to a format grouping people by age ranges
  3. Sort the list by name in alphabetical order

Exercise 3: Class Conversion

Take a JavaScript class you've written before and convert it to a Python class, ensuring it follows Python conventions and best practices.

Best Practices for JavaScript Developers Learning Python

# Good Pythonic code example
def process_user_data(users, min_age=18):
    """Process user data to get active users above a minimum age."""
    active_adults = [
        user for user in users
        if user["active"] and user["age"] >= min_age
    ]
    
    # Group by age decade
    by_decade = {}
    for user in active_adults:
        decade = user["age"] // 10 * 10
        if decade not in by_decade:
            by_decade[decade] = []
        by_decade[decade].append(user)
    
    return {
        "active_adult_count": len(active_adults),
        "by_decade": by_decade,
        "average_age": sum(user["age"] for user in active_adults) / len(active_adults) if active_adults else 0
    }

Next Steps for JavaScript Developers

Now that you understand the key differences between Python and JavaScript data types, here are some next steps to deepen your Python knowledge:

  1. Explore the Standard Library: Python's built-in modules like collections, itertools, and functools offer powerful tools
  2. Learn Generators and Iterators: These Python features can replace many array operations in JavaScript
  3. Dive into Decorators: Python's decorator pattern is powerful and widely used
  4. Understand Python's Context Managers: The with statement provides elegant resource management
  5. Try Type Annotations: If you're used to TypeScript, exploring Python's typing module can help
  6. Learn Dependency Management: Understand pip, virtual environments, and requirements.txt

Additional Resources

In our next session, we'll explore control flow in Python, including conditionals, loops, and exception handling, and how they compare to JavaScript's control flow mechanisms.