- Function definition with arguments and a return type - how to pass arguments to a function and express the return type.
- Function overloading - how to provide multiple different implementations with different sets of arguments
- Default or Optional Arguments - how to provide defaults or express optionality in arguments
- Lambda Functions - defining a lambda function
- Lambda Function Capture - using local in-scope variables inside the lambda function
- Function Type Parameter (Generics) - how to define a function with one or more types as an argument
- Function Type Parameter Constraints - how to define a constraint on the type parameter
Functions
Change TopicTypeScript Functions
Python Language
Function Definition with Arguments and Return Type
TypeScript allows specifying argument types and return types explicitly in function definitions.
function add(x: number, y: number): number { return x + y; } const greet = (name: string): string => `Hello, ${name}!`;
x: number, y: number
: Defines parameter types.: number
after()
specifies the return type.
Function Definition with Arguments and Return Type
Python allows function definitions with optional type hints for parameters and return values.
def add(x: int, y: int) -> int: return x + y def greet(name: str) -> str: return f"Hello, {name}!"
x: int, y: int
- Type hints for parameters.-> int
- Type hint for return value.- Type hints are optional; Python does not enforce them at runtime.
Function Overloading
Function overloading processed at runtime
function add(x: number, y: number): number; function add(x: string, y: string): string; function add(x: any, y: any): any { return x + y; } console.log(add(5, 10)); // 15 console.log(add("Hello, ", "World!")); // "Hello, World!"
Function Overloading
Function overloading not supported explicitly, process at runtime:
def add(x, y=None): if y is None: # Single argument case return x return x + y print(add(5, 10)) # 15 print(add(5)) # 5
Or using Union
:
from typing import Union def add(x: Union[int, str], y: Union[int, str]) -> Union[int, str]: return x + y print(add(5, 10)) # 15 print(add("Hello, ", "World!")) # "Hello, World!"
Or using @singledispatch
:
from functools import singledispatch @singledispatch def process(value): raise NotImplementedError("Unsupported type") @process.register def _(value: int): return f"Processing an integer: {value}" @process.register def _(value: str): return f"Processing a string: {value}" print(process(42)) # "Processing an integer: 42" print(process("Hello")) # "Processing a string: Hello"
Function Default Arguments
function doIt(b: number, a = 1) { return b / a; } console.log("DoIt " + doIt(10) + " " + doIt(10, 2));
Function Default Arguments
def greet(name="World"): print(f"Hello, {name}!") greet() # Hello, World! greet("Alice") # Hello, Alice!
Lambda Functions
const doIt = (b: number, c: number) => a * b; console.log("DoIt " + doIt(10, 5));
Lambda Functions
add = lambda x, y: x + y print(add(3, 4)) # 7
There are some limitations:
- Only one expression, no statements like if, for, print.
- Can hurt readability for anything non-trivial.
- Can't contain annotations or docstrings.
Lambda Function Capture
function createCounter(): () => number { let count = 0; // This variable is captured by the closure return () => { count += 1; return count; }; } const counterA = createCounter(); console.log(counterA()); // 1 console.log(counterA()); // 2 const counterB = createCounter(); console.log(counterB()); // 1 (separate closure) console.log(counterA()); // 3 (original closure still intact)
function makeMultiplier(factor: number): (input: number) => number { // factor is captured by the inner function return (input: number) => input * factor; } const double = makeMultiplier(2); const triple = makeMultiplier(3); console.log(double(5)); // 10 console.log(triple(5)); // 15
Lambda Functions With Capture
Supported...
x = 10 f = lambda: x + 1 print(f()) # 11 x = 20 print(f()) # 21 — uses the updated value of x
But note the following:
funcs = [lambda: i for i in range(3)] print([f() for f in funcs]) # [2, 2, 2] — not [0, 1, 2] # fix by binding i as a default argument for each iteration funcs = [lambda i=i: i for i in range(3)] print([f() for f in funcs]) # [0, 1, 2]
Function Generics
function identity<T>(value: T): T { return value; } console.log(identity<number>(42)); // 42 console.log(identity<string>("Hello")); // "Hello"
Function Generics
from typing import TypeVar T = TypeVar('T') # Generic type placeholder def identity(value: T) -> T: return value print(identity(42)) # 42 print(identity("Hello")) # "Hello"
Function Generics Constraint
And with a constraint:
function getLength<T extends { length: number }>(arg: T): number { return arg.length; } console.log(getLength("Hello")); // 5 console.log(getLength([1, 2, 3])); // 3
Function Generics with Constraint
With a constraint:
from typing import TypeVar, Protocol class HasLength(Protocol): def __len__(self) -> int: ... T = TypeVar('T', bound=HasLength) def get_length(value: T) -> int: return len(value) print(get_length("Hello")) # 5 print(get_length([1, 2, 3])) # 3