From JavaScript to Python: Understanding the Collection Landscape
As a JavaScript developer diving into Python, you'll find many familiar concepts with important nuances. Python's collection types share similarities with JavaScript's arrays and objects but differ in significant ways that affect how you structure and manipulate data.
This guide will help you map your JavaScript knowledge to Python's collection types, highlighting key similarities, important differences, and Python-specific features that might surprise you. We'll cover how Python's lists, tuples, dictionaries, and sets compare to JavaScript's arrays and objects, with practical examples to reinforce the concepts.
Understanding these parallels and distinctions will accelerate your Python learning curve and help you write more idiomatic Python code while leveraging your JavaScript expertise.
Collection Types at a Glance: JavaScript vs Python
Here's a high-level comparison of the main collection types in both languages:
| JavaScript | Python Equivalent(s) | Primary Purpose |
|---|---|---|
| Array | List, Tuple | Ordered sequence of items |
| Object | Dictionary | Key-value pairs |
| Set | Set | Collection of unique values |
| Map | Dictionary | Key-value pairs with any key type |
Let's dive deeper into each of these comparisons to understand the nuances.
JavaScript Arrays vs Python Lists and Tuples
JavaScript arrays and Python lists both store ordered collections of items, but there are significant differences in behavior and available methods.
Key Similarities
- Both are ordered (items have a specific position)
- Both are indexed from 0
- Both can contain mixed data types
- Both are dynamically sized
- Both provide methods for common operations like adding/removing elements
Side-by-Side Comparison
Here's how common array operations translate between JavaScript and Python:
| Operation | JavaScript | Python |
|---|---|---|
| Creating an empty collection | const arr = []; |
arr = [] |
| Creating with initial values | const arr = [1, 2, 3, 'four']; |
arr = [1, 2, 3, 'four'] |
| Accessing an element | arr[0] |
arr[0] |
| Length/size | arr.length |
len(arr) |
| Adding to the end | arr.push(item) |
arr.append(item) |
| Removing from the end | arr.pop() |
arr.pop() |
| Checking if item exists | arr.includes(item) |
item in arr |
| Finding an item's index | arr.indexOf(item) |
arr.index(item) |
| Slicing/Extracting portion | arr.slice(start, end) |
arr[start:end] |
| Iterating | for (const item of arr) {...} |
for item in arr: ... |
| Mapping | arr.map(x => x * 2) |
[x * 2 for x in arr] (list comprehension) |
| Filtering | arr.filter(x => x > 5) |
[x for x in arr if x > 5] |
| Reducing | arr.reduce((a,b) => a+b, 0) |
sum(arr) or from functools import reduce; reduce(lambda a,b: a+b, arr) |
Key Differences
1. Python distinguishes between mutable Lists and immutable Tuples
# File: list_vs_tuple.py
# Location: ~/python_examples/week2/
# Python lists (mutable, like JavaScript arrays)
fruits = ["apple", "banana", "cherry"]
fruits[0] = "apricot" # OK - lists can be modified
fruits.append("date") # Adds to the end
# Python tuples (immutable)
coordinates = (10, 20, 30)
# coordinates[0] = 15 # Error - tuples can't be modified
# coordinates.append(40) # Error - no append method
# JavaScript has no direct equivalent to tuples
2. Python slicing is more powerful than JavaScript's slice()
# File: slicing_examples.py
# Location: ~/python_examples/week2/
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Basic slicing (similar to JavaScript)
first_three = numbers[0:3] # [0, 1, 2]
# Slicing with step (no direct JS equivalent)
every_second = numbers[::2] # [0, 2, 4, 6, 8]
# Negative indices (from the end)
last_three = numbers[-3:] # [7, 8, 9]
# Reversing with slice
reversed_list = numbers[::-1] # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# JavaScript equivalent would be:
# const reversed = [...numbers].reverse();
3. Python list comprehensions have no direct JavaScript equivalent
# File: comprehensions.py
# Location: ~/python_examples/week2/
numbers = [1, 2, 3, 4, 5]
# Python list comprehension (map equivalent)
doubled = [x * 2 for x in numbers] # [2, 4, 6, 8, 10]
# Python list comprehension (filter equivalent)
evens = [x for x in numbers if x % 2 == 0] # [2, 4]
# Python list comprehension (map + filter)
doubled_evens = [x * 2 for x in numbers if x % 2 == 0] # [4, 8]
# JavaScript equivalents:
# const doubled = numbers.map(x => x * 2);
# const evens = numbers.filter(x => x % 2 === 0);
# const doubledEvens = numbers.filter(x => x % 2 === 0).map(x => x * 2);
4. Python has no arrow functions, but uses lambda for simple functions
# File: lambda_examples.py
# Location: ~/python_examples/week2/
numbers = [1, 2, 3, 4, 5]
# Python's sorted with key function
desc_order = sorted(numbers, reverse=True) # [5, 4, 3, 2, 1]
# Using lambda (similar to arrow function, but more limited)
custom_sort = sorted(numbers, key=lambda x: abs(x - 3))
# Sorts by distance from 3: [3, 2, 4, 1, 5]
# In JavaScript:
# const customSort = numbers.sort((a, b) => Math.abs(a - 3) - Math.abs(b - 3));
When to Use Tuples Instead of Lists
As a JavaScript developer, you might wonder when to use tuples since JavaScript has no equivalent. Here are common use cases:
- Immutable data: When you want to ensure data can't be changed
- Dictionary keys: Lists can't be dictionary keys, but tuples can
- Function returns: Returning multiple values from a function
- Data integrity: Representing fixed structures like coordinates (x, y, z)
# File: tuple_usage.py
# Location: ~/python_examples/week2/
# Multiple return values
def get_dimensions():
return (1920, 1080) # Returns width, height as tuple
width, height = get_dimensions() # Tuple unpacking
print(f"Width: {width}, Height: {height}")
# Dictionary with tuple keys
locations = {
(40.7128, -74.0060): "New York",
(34.0522, -118.2437): "Los Angeles",
(41.8781, -87.6298): "Chicago"
}
# Find location by coordinates
coords = (40.7128, -74.0060)
print(f"Location: {locations[coords]}")
Real-world application: In a web application, you might use tuples to represent configuration settings that shouldn't change during execution, such as screen breakpoints, color scheme values, or API endpoint URLs. This provides a safeguard against accidental modification.
JavaScript Objects vs Python Dictionaries
JavaScript objects and Python dictionaries both provide key-value mappings, but with notable differences in syntax, behavior, and capabilities.
Key Similarities
- Both store key-value pairs
- Both allow dynamic addition and removal of pairs
- Both provide methods to check for key existence
- Both can be nested (contain other objects/dictionaries as values)
Side-by-Side Comparison
| Operation | JavaScript | Python |
|---|---|---|
| Creating an empty collection | const obj = {}; |
obj = {} |
| Creating with initial values | const obj = {name: 'Alice', age: 30}; |
obj = {'name': 'Alice', 'age': 30} |
| Accessing a value | obj.name or obj['name'] |
obj['name'] (no dot notation for arbitrary keys) |
| Setting a value | obj.name = 'Bob' or obj['name'] = 'Bob' |
obj['name'] = 'Bob' |
| Checking if key exists | 'name' in obj |
'name' in obj |
| Getting keys | Object.keys(obj) |
obj.keys() or list(obj.keys()) |
| Getting values | Object.values(obj) |
obj.values() or list(obj.values()) |
| Getting entries | Object.entries(obj) |
obj.items() or list(obj.items()) |
| Merging objects | {...obj1, ...obj2} |
{**obj1, **obj2} or obj1 | obj2 (Python 3.9+) |
| Default value if key missing | obj.name || 'Unknown' |
obj.get('name', 'Unknown') |
| Iterating | for (const [key, value] of Object.entries(obj)) {...} |
for key, value in obj.items(): ... |
Key Differences
1. Python dictionaries require hashable keys (strings, numbers, tuples, etc.)
# File: dictionary_keys.py
# Location: ~/python_examples/week2/
# String keys (like JavaScript objects)
user = {'name': 'Alice', 'age': 30}
# Numeric keys (rarely used in JavaScript)
counts = {1: 'one', 2: 'two', 3: 'three'}
# Tuple keys (not possible in JavaScript)
coordinates = {(0, 0): 'origin', (1, 0): 'right', (0, 1): 'up'}
# This would cause an error in Python:
# invalid_dict = {[1, 2]: 'value'} # Lists can't be keys (not hashable)
2. Python dot notation is only for attributes/methods, not arbitrary dictionary keys
# File: dict_access.py
# Location: ~/python_examples/week2/
user = {'name': 'Alice', 'age': 30, 'email-address': 'alice@example.com'}
# Square brackets work for any key
print(user['name']) # Alice
print(user['email-address']) # alice@example.com
# Dot notation doesn't work for dictionaries
# print(user.name) # AttributeError
# print(user.email-address) # Syntax Error (- isn't valid in identifiers)
# JavaScript would allow both:
# console.log(user.name); // Alice
# console.log(user['email-address']); // alice@example.com
3. Python dictionaries have useful methods with no direct JavaScript equivalents
# File: dict_methods.py
# Location: ~/python_examples/week2/
user = {'name': 'Alice', 'age': 30}
# Get with default value
email = user.get('email', 'no email provided')
print(email) # 'no email provided'
# JavaScript equivalent:
# const email = user.email || 'no email provided';
# Set default and get
role = user.setdefault('role', 'user')
print(role) # 'user'
print(user) # {'name': 'Alice', 'age': 30, 'role': 'user'}
# JavaScript has no direct equivalent; would need:
# if (!user.role) user.role = 'user';
# const role = user.role;
# Pop item (remove and return)
age = user.pop('age')
print(age) # 30
print(user) # {'name': 'Alice', 'role': 'user'}
# JavaScript would need:
# const age = user.age;
# delete user.age;
4. Python dictionaries maintain insertion order (since Python 3.7)
# File: dict_ordering.py
# Location: ~/python_examples/week2/
# Python 3.7+ dictionaries maintain insertion order
colors = {
'red': '#FF0000',
'green': '#00FF00',
'blue': '#0000FF'
}
# Keys will be returned in the order they were inserted
for color in colors:
print(color) # 'red', 'green', 'blue' in that order
# In JavaScript, prior to ES2015, object property order was not guaranteed
# Modern JavaScript does generally preserve insertion order for string/symbol keys
5. Python dictionary comprehensions provide concise creation
# File: dict_comprehensions.py
# Location: ~/python_examples/week2/
names = ['Alice', 'Bob', 'Charlie']
# Dictionary comprehension
name_lengths = {name: len(name) for name in names}
print(name_lengths) # {'Alice': 5, 'Bob': 3, 'Charlie': 7}
# JavaScript equivalent would be:
# const nameLengths = Object.fromEntries(names.map(name => [name, name.length]));
Real-world application: In a web application, you might use dictionaries to maintain a cache of API responses where the URL is the key and the response data is the value. Python's dictionary methods like get() with a default value simplify the logic for checking if a response exists in the cache before making a new request.
JavaScript Sets vs Python Sets
JavaScript and Python both have Set types that store unique values, but with some syntax and feature differences.
Key Similarities
- Both guarantee uniqueness of elements
- Both have fast membership testing
- Both provide methods for common set operations
- Both can store mixed types
Side-by-Side Comparison
| Operation | JavaScript | Python |
|---|---|---|
| Creating an empty set | const mySet = new Set(); |
my_set = set() |
| Creating from values | const mySet = new Set([1, 2, 3]); |
my_set = {1, 2, 3} or my_set = set([1, 2, 3]) |
| Adding an item | mySet.add(item) |
my_set.add(item) |
| Removing an item | mySet.delete(item) |
my_set.remove(item) or my_set.discard(item) |
| Checking if item exists | mySet.has(item) |
item in my_set |
| Getting size/length | mySet.size |
len(my_set) |
| Union | new Set([...set1, ...set2]) |
set1 | set2 or set1.union(set2) |
| Intersection | new Set([...set1].filter(x => set2.has(x))) |
set1 & set2 or set1.intersection(set2) |
| Difference | new Set([...set1].filter(x => !set2.has(x))) |
set1 - set2 or set1.difference(set2) |
| Clearing | mySet.clear() |
my_set.clear() |
| Iterating | for (const item of mySet) {...} |
for item in my_set: ... |
Key Differences
1. Python sets have more built-in operations with operator syntax
# File: set_operations.py
# Location: ~/python_examples/week2/
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# Union (all elements from both sets)
union = a | b
print(union) # {1, 2, 3, 4, 5, 6}
# Intersection (elements in both sets)
intersection = a & b
print(intersection) # {3, 4}
# Difference (elements in a but not in b)
difference = a - b
print(difference) # {1, 2}
# Symmetric difference (elements in either set but not both)
sym_diff = a ^ b
print(sym_diff) # {1, 2, 5, 6}
# JavaScript would need helper functions or more verbose syntax for these
2. Python set comprehensions for concise creation
# File: set_comprehensions.py
# Location: ~/python_examples/week2/
numbers = [1, 2, 2, 3, 4, 4, 5]
# Create a set of squares of even numbers
even_squares = {x**2 for x in numbers if x % 2 == 0}
print(even_squares) # {4, 16}
# JavaScript equivalent:
# const evenSquares = new Set(numbers.filter(x => x % 2 === 0).map(x => x ** 2));
3. Python sets can only contain hashable items
# File: set_hashable.py
# Location: ~/python_examples/week2/
# This works - tuples are hashable
valid_set = {(1, 2), (3, 4), (5, 6)}
# This would cause an error
# invalid_set = {[1, 2], [3, 4]} # Lists are not hashable
# JavaScript allows any value type in Sets, including objects and arrays
4. Python sets have additional useful methods
# File: set_methods.py
# Location: ~/python_examples/week2/
a = {1, 2, 3}
b = {1, 2, 3, 4, 5}
# Check if a is subset of b
print(a.issubset(b)) # True
print(a <= b) # True (operator syntax)
# Check if b is superset of a
print(b.issuperset(a)) # True
print(b >= a) # True (operator syntax)
# Update a set in-place (union)
a |= {4, 5}
print(a) # {1, 2, 3, 4, 5}
# Remove items from a set in-place (difference)
a -= {4, 5}
print(a) # {1, 2, 3}
# JavaScript Sets have less built-in functionality
Real-world application: In a user permission system, you might use sets to represent and compare user roles and capabilities. For example, checking if a user has sufficient permissions might involve testing if their permission set is a superset of the required permissions set for an action, which is elegantly expressed with user_permissions >= required_permissions.
Practical Translation Examples
Let's walk through some common JavaScript patterns and their Python equivalents to solidify these concepts.
Example 1: Processing a List of Records
JavaScript:
// users.js
const users = [
{ id: 1, name: 'Alice', age: 28, active: true },
{ id: 2, name: 'Bob', age: 22, active: false },
{ id: 3, name: 'Charlie', age: 31, active: true },
{ id: 4, name: 'Diana', age: 25, active: false }
];
// Get active users
const activeUsers = users.filter(user => user.active);
// Get names of users over 25
const olderUserNames = users
.filter(user => user.age > 25)
.map(user => user.name);
// Create a map for quick ID lookup
const userMap = users.reduce((map, user) => {
map[user.id] = user;
return map;
}, {});
// Get a user by ID
const user = userMap[2]; // Bob's record
console.log(activeUsers);
console.log(olderUserNames);
console.log(user);
Python:
# File: users.py
# Location: ~/python_examples/week2/
users = [
{'id': 1, 'name': 'Alice', 'age': 28, 'active': True},
{'id': 2, 'name': 'Bob', 'age': 22, 'active': False},
{'id': 3, 'name': 'Charlie', 'age': 31, 'active': True},
{'id': 4, 'name': 'Diana', 'age': 25, 'active': False}
]
# Get active users
active_users = [user for user in users if user['active']]
# Get names of users over 25
older_user_names = [user['name'] for user in users if user['age'] > 25]
# Create a dictionary for quick ID lookup
user_map = {user['id']: user for user in users}
# Get a user by ID
user = user_map[2] # Bob's record
print(active_users)
print(older_user_names)
print(user)
Example 2: Handling Nested Data
JavaScript:
// products.js
const products = {
electronics: {
smartphone: [
{ brand: 'Apple', model: 'iPhone 13', price: 999 },
{ brand: 'Samsung', model: 'Galaxy S21', price: 899 }
],
laptop: [
{ brand: 'Apple', model: 'MacBook Pro', price: 1299 },
{ brand: 'Dell', model: 'XPS 13', price: 999 }
]
},
clothing: {
shirts: [
{ brand: 'Nike', size: 'M', price: 29.99 },
{ brand: 'Adidas', size: 'L', price: 24.99 }
]
}
};
// Find all Apple products
const appleProducts = [];
Object.keys(products).forEach(category => {
Object.keys(products[category]).forEach(subcategory => {
products[category][subcategory].forEach(product => {
if (product.brand === 'Apple') {
appleProducts.push({
category,
subcategory,
...product
});
}
});
});
});
// Calculate total price of all products
let totalPrice = 0;
Object.values(products).forEach(category => {
Object.values(category).forEach(subcategory => {
subcategory.forEach(product => {
totalPrice += product.price;
});
});
});
console.log(appleProducts);
console.log(`Total price: $${totalPrice}`);
Python:
# File: products.py
# Location: ~/python_examples/week2/
products = {
'electronics': {
'smartphone': [
{'brand': 'Apple', 'model': 'iPhone 13', 'price': 999},
{'brand': 'Samsung', 'model': 'Galaxy S21', 'price': 899}
],
'laptop': [
{'brand': 'Apple', 'model': 'MacBook Pro', 'price': 1299},
{'brand': 'Dell', 'model': 'XPS 13', 'price': 999}
]
},
'clothing': {
'shirts': [
{'brand': 'Nike', 'size': 'M', 'price': 29.99},
{'brand': 'Adidas', 'size': 'L', 'price': 24.99}
]
}
}
# Find all Apple products
apple_products = []
for category_name, category in products.items():
for subcategory_name, items in category.items():
for item in items:
if item['brand'] == 'Apple':
# Create a copy and add category info
product_info = item.copy()
product_info['category'] = category_name
product_info['subcategory'] = subcategory_name
apple_products.append(product_info)
# Alternative using list comprehension (more advanced)
apple_products_alt = [
{**item, 'category': cat, 'subcategory': subcat}
for cat, category in products.items()
for subcat, items in category.items()
for item in items
if item['brand'] == 'Apple'
]
# Calculate total price of all products
total_price = 0
for category in products.values():
for items in category.values():
for item in items:
total_price += item['price']
print(apple_products)
print(f"Total price: ${total_price}")
Example 3: Handling Unique Values and Set Operations
JavaScript:
// students.js
const mathStudents = ['Alice', 'Bob', 'Charlie', 'Diana'];
const scienceStudents = ['Bob', 'Diana', 'Eve', 'Frank'];
const englishStudents = ['Alice', 'Charlie', 'Grace'];
// Students taking both math and science
const mathAndScience = mathStudents.filter(
student => scienceStudents.includes(student)
);
// Students taking any subject
const allStudents = [
...new Set([...mathStudents, ...scienceStudents, ...englishStudents])
];
// Students taking only math (not science or English)
const onlyMath = mathStudents.filter(
student => !scienceStudents.includes(student) &&
!englishStudents.includes(student)
);
console.log('Math and Science:', mathAndScience);
console.log('All Students:', allStudents);
console.log('Only Math:', onlyMath);
Python:
# File: students.py
# Location: ~/python_examples/week2/
math_students = {'Alice', 'Bob', 'Charlie', 'Diana'}
science_students = {'Bob', 'Diana', 'Eve', 'Frank'}
english_students = {'Alice', 'Charlie', 'Grace'}
# Students taking both math and science
math_and_science = math_students & science_students
# Students taking any subject
all_students = math_students | science_students | english_students
# Students taking only math (not science or English)
only_math = math_students - (science_students | english_students)
print('Math and Science:', math_and_science)
print('All Students:', all_students)
print('Only Math:', only_math)
Real-world application: The set operations example mirrors how you might analyze user engagement across different features of an application. For instance, you could identify users who engage with both your mobile and web platforms (intersection), users who have abandoned one platform entirely (difference), or the total active user base across all platforms (union).
Performance Considerations
As you move from JavaScript to Python, it's useful to understand performance differences between comparable operations:
| Operation | JavaScript Performance | Python Performance | Notes |
|---|---|---|---|
| Item lookup by index | O(1) in Array | O(1) in List/Tuple | Similar performance |
| Item lookup by value | O(n) in Array O(1) in Set |
O(n) in List/Tuple O(1) in Set |
Similar performance |
| Property/Key lookup | O(1) in Object | O(1) in Dictionary | Similar performance |
| Iteration | Generally slower | Generally faster | Python's for loops are implemented in C |
| Array/List manipulation | Array methods can be inefficient for large datasets | List comprehensions are optimized and often faster | Python's list comprehensions often outperform equivalent JS array methods |
| String operations | Generally good performance | String concatenation can be slow for large operations | Use ''.join() in Python for concatenating many strings |
Performance Tips When Transitioning
- Use appropriate collections: In Python, always use sets for membership testing when order doesn't matter
- Leverage comprehensions: List/dict comprehensions are usually faster than equivalent for loops
- Be cautious with string concatenation: Use ''.join(items) instead of += for building strings
- Know when to use dictionaries: If you're using arrays with indexOf in JS, consider dictionaries in Python
- Consider generators for large datasets: Python generators can help with memory usage
# File: performance_examples.py
# Location: ~/python_examples/week2/
# Efficient string concatenation
words = ['Python', 'is', 'awesome', 'for', 'data', 'processing']
# Inefficient (like JavaScript's +=)
result = ''
for word in words:
result += word + ' '
# Efficient (Python's way)
better_result = ' '.join(words)
# Efficient membership testing
large_list = list(range(10000))
large_set = set(large_list)
# Slow (like JavaScript array.includes)
def find_in_list(item):
return item in large_list # O(n)
# Fast (like JavaScript Set.has)
def find_in_set(item):
return item in large_set # O(1)
# Generator for memory efficiency
def first_n_squared(n):
# Returns a generator, not a list
return (x**2 for x in range(1, n+1))
# More memory-efficient than:
# def first_n_squared_list(n):
# return [x**2 for x in range(1, n+1)]
Common Pitfalls for JavaScript Developers
When transitioning from JavaScript to Python, be aware of these common stumbling blocks:
Mutable Default Arguments
# File: mutable_defaults.py
# Location: ~/python_examples/week2/
# WRONG: This doesn't work as expected
def add_to_list(item, my_list=[]):
my_list.append(item)
return my_list
print(add_to_list("a")) # ['a']
print(add_to_list("b")) # ['a', 'b'] - Surprise! The list persists
# RIGHT: Use None as default and create list inside function
def add_to_list_properly(item, my_list=None):
if my_list is None:
my_list = []
my_list.append(item)
return my_list
print(add_to_list_properly("a")) # ['a']
print(add_to_list_properly("b")) # ['b'] - Each call gets a fresh list
Copy vs. Reference Behavior
# File: copy_reference.py
# Location: ~/python_examples/week2/
# Lists and dictionaries are mutable and assigned by reference
original_list = [1, 2, 3]
reference_to_original = original_list # Creates a reference, not a copy
reference_to_original.append(4)
print(original_list) # [1, 2, 3, 4] - Original is modified!
# Creating copies
import copy
# Shallow copy
shallow_copy = original_list.copy() # or list(original_list) or original_list[:]
shallow_copy.append(5)
print(original_list) # Still [1, 2, 3, 4] - Original unchanged
# Deep copy (for nested structures)
nested = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(nested)
deep_copy[0][0] = 99
print(nested) # [[1, 2], [3, 4]] - Original unchanged
# JavaScript behaves similarly, but developers often forget this applies to Python too
Truthiness Differences
# File: truthiness.py
# Location: ~/python_examples/week2/
# Python vs JavaScript truthiness differences
# In JavaScript: 0, '', null, undefined, NaN are falsy
# In Python:
# Empty collections are falsy
print(bool([])) # False (like JavaScript)
print(bool({})) # False (like JavaScript)
print(bool(set())) # False
# But zero-like numerics and empty strings are also falsy
print(bool(0)) # False (like JavaScript)
print(bool(0.0)) # False
print(bool('')) # False (like JavaScript)
# None is falsy (Python's null equivalent)
print(bool(None)) # False
# In Python, all other values are truthy, including:
print(bool('0')) # True (string containing '0')
print(bool([0])) # True (list containing 0)
print(bool({0})) # True (set containing 0)
# Logical operators return the last value evaluated, not just True/False
print([] or "default") # "default" (similar to JavaScript)
print([1, 2] or "default") # [1, 2] (similar to JavaScript)
String Immutability
# File: string_immutability.py
# Location: ~/python_examples/week2/
# Strings are immutable in Python
greeting = "Hello"
# This doesn't work
# greeting[0] = "h" # TypeError: 'str' object does not support item assignment
# Instead, create a new string
greeting = "h" + greeting[1:]
print(greeting) # "hello"
# For more complex string manipulation, use string methods or formatting
name = "Alice"
greeting = f"Hello, {name}!" # f-strings (like JS template literals)
print(greeting) # "Hello, Alice!"
# JavaScript strings are also immutable, but this is a common confusion point
Function Arguments: Named vs. Positional
# File: function_arguments.py
# Location: ~/python_examples/week2/
# Python supports both positional and named arguments
def create_profile(name, age, city="Unknown", country=None):
profile = {
"name": name,
"age": age,
"city": city
}
if country:
profile["country"] = country
return profile
# Positional arguments
profile1 = create_profile("Alice", 30)
# Named arguments (any order)
profile2 = create_profile(age=25, name="Bob", country="USA")
# Mix of positional and named (positional must come first)
profile3 = create_profile("Charlie", 22, country="Canada")
print(profile1)
print(profile2)
print(profile3)
# JavaScript traditionally used object parameter for named arguments:
# function createProfile({ name, age, city = 'Unknown', country = null }) {...}
Leveraging Your JavaScript Knowledge in Python
As you dive deeper into Python, your JavaScript experience provides a strong foundation for understanding collections and data manipulation. Here are some final tips for making a smooth transition:
- Embrace Pythonic idioms: Rather than writing JavaScript in Python, learn Python's preferred approaches (comprehensions, built-in functions, etc.)
- Leverage operator syntax: Python's operators for dictionaries and sets can make your code more readable
- Use the REPL: Python's interactive interpreter is great for experimenting with collections
- Explore the standard library: Python's standard library has many powerful tools for working with collections
- Practice with real examples: Convert JavaScript code you're familiar with to Python to build fluency
Remember that both languages have their strengths. JavaScript's functional programming features and Python's clear, concise syntax each excel in different contexts. By understanding both, you'll have a versatile toolkit for solving a wide range of programming problems.
As you continue your Python journey, you'll discover that the concepts you learned in JavaScript—like iteration, transformation, and filtering—apply in Python as well, just with different syntax and sometimes with more elegant built-in solutions.
Exercises for Practice
Put your knowledge to the test by translating these JavaScript snippets to Python:
Exercise 1: User Filtering
// Convert this JavaScript code to Python
const users = [
{ name: 'Alice', age: 25, roles: ['admin', 'user'] },
{ name: 'Bob', age: 32, roles: ['user'] },
{ name: 'Charlie', age: 19, roles: ['user', 'moderator'] },
{ name: 'Diana', age: 40, roles: ['user'] }
];
// Get user names who are either admins or over 30
const specialUsers = users
.filter(user => user.roles.includes('admin') || user.age > 30)
.map(user => user.name);
console.log(specialUsers); // ['Alice', 'Bob', 'Diana']
Exercise 2: Word Frequency Counter
// Convert this JavaScript code to Python
const text = "the quick brown fox jumps over the lazy dog fox fox";
const words = text.toLowerCase().split(' ');
// Count word frequencies
const wordCounts = {};
for (const word of words) {
wordCounts[word] = (wordCounts[word] || 0) + 1;
}
// Find the most frequent word
let mostFrequentWord = '';
let highestCount = 0;
for (const [word, count] of Object.entries(wordCounts)) {
if (count > highestCount) {
mostFrequentWord = word;
highestCount = count;
}
}
console.log(`Most frequent word: "${mostFrequentWord}" (${highestCount} times)`);
Exercise 3: Nested Data Transformation
// Convert this JavaScript code to Python
const schools = [
{
name: 'Lincoln High',
departments: ['Math', 'Science', 'English'],
teachers: [
{ name: 'Ms. Johnson', subject: 'Math', students: 32 },
{ name: 'Mr. Davis', subject: 'Science', students: 28 },
{ name: 'Mrs. Garcia', subject: 'English', students: 30 }
]
},
{
name: 'Washington Middle',
departments: ['History', 'Art', 'Music'],
teachers: [
{ name: 'Mr. Brown', subject: 'History', students: 25 },
{ name: 'Ms. Wilson', subject: 'Art', students: 20 },
{ name: 'Mr. Lee', subject: 'Music', students: 22 }
]
}
];
// Create a map of teachers by subject across all schools
const teachersBySubject = {};
schools.forEach(school => {
school.teachers.forEach(teacher => {
if (!teachersBySubject[teacher.subject]) {
teachersBySubject[teacher.subject] = [];
}
teachersBySubject[teacher.subject].push({
name: teacher.name,
school: school.name,
students: teacher.students
});
});
});
console.log(teachersBySubject);
Try implementing these exercises yourself to practice the concepts we've covered!