Skip to content

Python vs. JavaScript: A Guide to Functions

Functions are the fundamental building blocks for organizing and reusing code in any programming language. This document provides an in-depth exploration of the core similarities and differences between Python and JavaScript regarding function definition, parameter handling, return values, and context.

References:


Core Differences at a Glance

FeaturePythonJavaScript
Definition Keyworddeffunction / => (arrow functions)
Anonymous Functionslambda (single expression, limited functionality)function() {} / () => {} (full functionality)
Number of ArgumentsStrict (must match definition or raises error)Flexible (can be more or less; missing are undefined)
Named/Keyword ArgumentsNative support (func(name="a"))Not supported (simulated by passing an object)
Arbitrary Arguments*args (positional) and **kwargs (keyword)...rest (rest parameters)
Instance Reference in MethodsExplicit self as the first argumentImplicit this context, whose value is dynamic
Multiple Return ValuesAchieved by returning a tuple and auto-unpackingAchieved by returning an array or object and destructuring

1. Function Definition and Invocation

Basic Syntax

Python: Uses the def keyword, followed by the function name, a parameter list, a colon (:), and an indented code block.

python
def greet(name):
    return f"Hello, {name}!"

message = greet("Alice")
print(message) # -> "Hello, Alice!"

JavaScript: Traditionally uses the function keyword, followed by the function name, a parameter list, and a code block enclosed in curly braces {}.

javascript
function greet(name) {
  return `Hello, ${name}!`;
}

let message = greet("Alice");
console.log(message); // -> "Hello, Alice!"

Function Expressions and Anonymous Functions

Python: lambda Python's anonymous functions use the lambda keyword but are very limited: they can only contain a single expression, not multiple statements.

python
# A lambda function that takes two arguments and returns their sum
add = lambda x, y: x + y
print(add(2, 3)) # -> 5

# Often used in higher-order functions
numbers = [1, 2, 3, 4]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled) # -> [2, 4, 6, 8]

JavaScript: Arrow Functions => (ES6+) JavaScript's anonymous functions (especially arrow functions) are fully featured and can contain arbitrarily complex code blocks. Arrow functions not only have a concise syntax but also change the binding behavior of this.

javascript
// Arrow function expression
const add = (x, y) => x + y;
console.log(add(2, 3)); // -> 5

// Used in higher-order functions
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(x => x * 2);
console.log(doubled); // -> [2, 4, 6, 8]

// Arrow function with a multi-line body
const complex_func = (a, b) => {
    const sum = a + b;
    return sum / 2;
};

2. Parameter Handling

Strictness of Argument Count

Python: Strict The number of arguments passed when calling a function must strictly match the number of parameters defined, otherwise a TypeError is raised.

python
def multiply(a, b):
    return a * b

# multiply(5) # -> TypeError: multiply() missing 1 required positional argument: 'b'
# multiply(5, 2, 1) # -> TypeError: multiply() takes 2 positional arguments but 3 were given

JavaScript: Flexible You can pass more or fewer arguments than defined.

  • Fewer: Un-passed parameters default to undefined.
  • More: Excess arguments are ignored but can be accessed via the arguments object or rest parameters (...).
javascript
function multiply(a, b) {
  console.log(`a=${a}, b=${b}`);
  return a * b;
}

multiply(5);      // -> a=5, b=undefined  -> NaN
multiply(5, 2, 1);  // -> a=5, b=2          -> 10 (the extra 1 is ignored)

Default Parameters

Both languages support default parameters with nearly identical syntax.

Python:

python
def create_user(name, is_admin=False):
    print(f"User: {name}, Admin: {is_admin}")

create_user("Bob") # -> User: Bob, Admin: False

JavaScript:

javascript
function createUser(name, isAdmin = false) {
  console.log(`User: ${name}, Admin: ${isAdmin}`);
}

createUser("Bob"); // -> User: Bob, Admin: false

Named/Keyword Arguments (Python-specific)

Python: This is a powerful feature that allows the caller to pass arguments in the form parameter_name=value, thus not having to worry about the order of the parameters.

python
def create_database(host, port, username, password):
    # ...
    print(f"Connecting to {host}:{port} with user {username}")

# Using keyword arguments, the order can be changed
create_database(
    username="admin",
    password="123",
    port=5432,
    host="localhost"
)

JavaScript: No native keyword arguments. However, this behavior can be elegantly simulated by passing an object as an argument, a very common pattern in the JS community.

javascript
function createDatabase({ host, port, username, password }) {
  // ...
  console.log(`Connecting to ${host}:${port} with user ${username}`);
}

// Pass an object; the order of keys doesn't matter
createDatabase({
  username: "admin",
  password: "123",
  port: 5432,
  host: "localhost"
});

Arbitrary Number of Arguments

Python: *args and **kwargs

  • *args: Gathers all unmatched positional arguments into a tuple.
  • **kwargs: Gathers all unmatched keyword arguments into a dictionary (dict).
python
def process_data(*args, **kwargs):
    print("Positional args:", args)
    print("Keyword args:", kwargs)

process_data(1, "hello", True, user="root", id=101)
# Positional args: (1, 'hello', True)
# Keyword args: {'user': 'root', 'id': 101}

JavaScript: Rest Parameters (...rest) Gathers all remaining arguments into an Array.

javascript
function processData(firstArg, ...rest) {
  console.log("First arg:", firstArg);
  console.log("Rest of args:", rest);
}

processData(1, "hello", true, { user: "root", id: 101 });
// First arg: 1
// Rest of args: [ 'hello', true, { user: 'root', id': 101 } ]

3. Return Values

Multiple Return Values

Python: A Python function can easily return multiple values, which is essentially returning a tuple that is automatically unpacked upon assignment.

python
def get_user_info():
    return "Alice", 30, "alice@example.com" # Actually returns ("Alice", 30, ...)

name, age, email = get_user_info()
print(name) # -> "Alice"

JavaScript: This is simulated by returning an array or an object and using destructuring.

javascript
// Returning via an array
function getUserInfoAsArray() {
  return ["Alice", 30, "alice@example.com"];
}
const [name, age, email] = getUserInfoAsArray();

// Returning via an object (more readable)
function getUserInfoAsObject() {
  return { name: "Alice", age: 30, email: "alice@example.com" };
}
const { name, age, email } = getUserInfoAsObject();

4. Scope and Context: self vs. this

The way an instance refers to itself in object-oriented class methods is fundamentally different.

Python: self In Python, an instance method must explicitly take the instance itself as its first argument, conventionally named self.

python
class Circle:
    def __init__(self, radius):
        self.radius = radius # self is explicit

    def get_area(self): # self must be the first argument
        return 3.14 * self.radius ** 2

JavaScript: this In JavaScript, this is an implicit contextual keyword whose value is dynamic and depends on how the function is called. This is one of the most complex and critical concepts in JS.

javascript
class Circle {
  constructor(radius) {
    this.radius = radius; // this is implicit
  }

  getArea() { // this is not passed as an argument
    return 3.14 * this.radius ** 2;
  }
}

5. A Deeper Look at Lambda: Python's Design Philosophy

While we introduced lambda earlier, understanding the design philosophy behind it is crucial for truly mastering Python. lambda is often misused by beginners because it looks like a shorter alternative to def, which it is not.

References: What is the purpose of Lambda expressions? - Python Discourse

The Core Purpose of lambda: Anonymity

The core purpose of lambda is to create anonymous functions. You can think of it as a nameless, single-use "utility function." When you need a simple function but don't want to go through the trouble of defining a full, named function for a one-time use, lambda is the right tool.

Common Misuse

A very typical misuse is assigning a lambda expression to a variable:

python
# Not recommended
add = lambda x, y: x + y

This completely defeats the "anonymous" purpose of lambda. It has several significant disadvantages:

  1. Poor Readability: A def statement clearly indicates "I am defining a function," whereas a lambda assignment is more obscure.
  2. Difficult Debugging: If an error occurs in a function add defined with def, the traceback will clearly state in function add. When a lambda function errors, you'll only see a generic <lambda>, which makes debugging much harder in complex code.
  3. Limited Functionality: lambda cannot contain docstrings or type annotations.

The correct approach is to use def if you need a reusable function:

python
# Recommended
def add(x, y):
    """Returns the sum of two numbers."""
    return x + y

This follows the principles of the Zen of Python: "Explicit is better than implicit" and "Readability counts."

The Right Use Case: As an Argument to Higher-Order Functions

The real power of lambda shines when it's used as an argument to a higher-order function (a function that takes other functions as arguments).

Example: Using sorted() with the key argument Suppose you have a list of dictionaries and you want to sort it by the "age" key of each dictionary:

python
people = [
    {'name': 'Alice', 'age': 30},
    {'name': 'Bob', 'age': 25},
    {'name': 'Charlie', 'age': 35}
]

# Use a lambda to provide a temporary, simple key function
sorted_people = sorted(people, key=lambda person: person['age'])

# sorted_people -> [{'name': 'Bob', 'age': 25}, ...]

In this example, the required sorting logic is very simple ("get the value of the 'age' key from the dictionary"). Defining a full def get_age(person): return person['age'] would be redundant. lambda perfectly plays the role of a temporary, anonymous, functional tool here.

Design Limitation: Single Expression

A lambda function body can only contain a single expression. It cannot contain if statements, for loops, print(), or other multi-statement logic.

This limitation is intentional. It forces lambda to remain simple. If your logic requires more than a single expression, the designers of Python believe you should define a clearer, more fully-featured def function instead.

Conclusion: lambda is Not a Replacement for def

  • def: Is for defining named, reusable, and relatively complete functions. This is the standard and preferred way to create functions.
  • lambda: Is for creating anonymous, single-use, and extremely simple single-expression functions, primarily for use as arguments to higher-order functions.

lambda is a sharp little knife in the Python toolbox, suitable for specific, delicate operations, but it should not be seen as a replacement for the "chef's knife" that is def.