python 52 Q&As

Python FAQ & Answers

52 expert Python answers researched from official documentation. Every answer cites authoritative sources you can verify.

unknown

52 questions
A

PEP 8 is Python's official style guide defining code formatting standards. Key rules: 4-space indentation, 79-character line limit (88 for Black), snake_case for functions/variables, PascalCase for classes, 2 blank lines between top-level definitions, imports order (standard library, third-party, local). Philosophy: 'code is read much more often than written'. Modern enforcement: Ruff (fastest linter, replaces Flake8/isort/pydocstyle), Black (opinionated formatter, 88-char default), mypy (type checking). Use pre-commit hooks for automatic enforcement. Not dogmatic - E501 (line length) often relaxed to 100-120 chars in 2025 projects. Essential for team collaboration and code maintainability.

99% confidence
A

Type hints specify expected types for static analysis (runtime unaffected). Python 3.12+ syntax: def func(name: str, age: int) -> str. Modern features: use | for unions (int | str), built-in generics (list[int], dict[str, Any]), new generic syntax class Stack[T] (PEP 695, no TypeVar needed), type aliases with type Point = tuple[float, float]. Type checkers: mypy (standard), pyright (fast, used by VS Code), Pydantic (runtime validation). Benefits: IDE autocomplete, early bug detection, self-documentation, safe refactoring. Python 3.13: TypeIs for type narrowing, default type parameters. Essential for production code - use strict mode (mypy --strict) for maximum safety.

99% confidence
A

Decorators modify functions/classes using @decorator syntax above definition. Implementation: decorator takes callable, returns wrapped callable. Pattern: def decorator(func): @wraps(func); def wrapper(*args, *kwargs): / setup */ result = func(*args, *kwargs); / teardown */ return result; return wrapper. Always use @functools.wraps(func) to preserve name, doc. Built-in: @property, @staticmethod, @classmethod, @dataclass, @lru_cache, @override (Python 3.12+). Parametrized decorators: def with_arg(param): def decorator(func): ... return decorator. Common patterns: @lru_cache(maxsize=128) for memoization, @retry for error handling, @validate for input checking. Type hints: from typing import Callable; def decorator(func: Callable[..., T]) -> Callable[..., T]. Essential for clean, reusable code patterns.

99% confidence
A

List comprehensions [x2 for x in range(10)] build entire list in memory immediately (eager evaluation). Generator expressions (x2 for x in range(10)) create iterator yielding values on-demand (lazy evaluation). Memory: list comp uses O(n) memory, generators use O(1) constant memory. Performance: generators ~2-3x faster for large datasets (no upfront allocation), list comp ~10-20% faster for small datasets (<1000 items). Use list comp when: need len(), indexing, multiple iterations, or small data (<10k items). Use generator when: single pass iteration, large/infinite sequences, memory constrained, pipeline processing (gen1 | gen2 style). Walrus operator pattern: if (n := sum(x for x in data if x > 0)) > threshold. Generators composable for data pipelines.

99% confidence
A

Context managers manage resources via with statement, ensuring cleanup even on exceptions. Protocol: enter(self) returns resource, exit(self, exc_type, exc_val, exc_tb) handles cleanup. Common uses: with open('file') as f (auto-close), with lock (auto-release), with db.transaction() (auto-commit/rollback). Create with @contextmanager: from contextlib import contextmanager; @contextmanager def my_context(): /* setup / yield resource; / cleanup */. Async version: async with for async resources, requires aenter/aexit. Python 3.10+: parenthesized context managers with (open('a') as a, open('b') as b). Use contextlib.suppress(Exception) to ignore specific errors, contextlib.chdir() for temporary directory changes. ExitStack for dynamic number of context managers. Essential pattern for RAII (Resource Acquisition Is Initialization) in Python.

99% confidence
A

GIL is mutex preventing multiple threads from executing Python bytecode simultaneously in CPython. Impact: CPU-bound multi-threaded code runs on single core (no parallel speedup). I/O-bound code unaffected (GIL released during I/O operations). Python 3.13+: experimental free-threaded mode (build with --disable-gil, run python3.13t) allows true parallelism but ~40% slower single-threaded. Python 3.14: free-threading promoted from experimental to supported (PEP 779). Check GIL status: sys._is_gil_enabled(). Workarounds: multiprocessing for CPU tasks (separate processes), asyncio for I/O concurrency, C extensions with Py_BEGIN_ALLOW_THREADS. Use free-threaded Python 3.13+ for CPU parallelism with threads. Future: GIL likely optional by Python 3.15, eventual default removal planned.

99% confidence
A

*args captures positional arguments as tuple, **kwargs captures keyword arguments as dict. Signature: def func(*args, **kwargs). Unpacking: func(*my_list, **my_dict). Parameter order: positional, *args, keyword-only, **kwargs. Example: def f(a, b, *args, c, d=5, **kwargs). Type hints: def f(*args: int, **kwargs: str) or from typing import Unpack; def f(**kwargs: Unpack[MyTypedDict]). Python 3.8+: positional-only with /: def f(a, b, /, *args, **kwargs). Use for: decorators, wrappers, flexible APIs, forwarding arguments. Introspection: inspect.signature(func) to examine parameters. Modern pattern: prefer explicit parameters over **kwargs for better IDE support and type safety. Use TypedDict with Unpack for typed **kwargs in Python 3.12+.

99% confidence
A

@dataclass decorator (PEP 557, Python 3.7+) auto-generates init, repr, eq, hash. Syntax: @dataclass class Point: x: float; y: float; z: float = 0.0. Python 3.10+ features: slots=True (memory optimization, ~40% less memory, faster attribute access), kw_only=True (keyword-only init), match_args=False (disable pattern matching). Frozen dataclasses: @dataclass(frozen=True) for immutability (hashable, thread-safe). Post-init: post_init(self) for validation. Field options: field(default_factory=list) for mutable defaults, field(repr=False) to hide from repr. Use for: DTOs, config objects, domain models, replacing namedtuples. Alternatives: Pydantic (runtime validation, serialization), attrs (more features). Modern Python standard for data containers - use slots=True for production.

99% confidence
A

asyncio provides single-threaded concurrent I/O via async/await syntax. async def creates coroutine, await suspends until awaitable completes, event loop schedules execution. Entry point: asyncio.run(main()). Create tasks: asyncio.create_task(coro) for concurrent execution, asyncio.gather(*coros) to wait for multiple. Use for: I/O-bound operations (HTTP requests, database queries, file I/O), WebSocket servers, concurrent API calls. NOT for CPU-bound tasks (use ProcessPoolExecutor). Common pitfall: never use blocking calls (time.sleep, requests.get) - use await asyncio.sleep(), aiohttp instead. Control concurrency: asyncio.Semaphore(10) limits concurrent operations. Libraries: aiohttp (HTTP), asyncpg (PostgreSQL), motor (MongoDB), aiofiles (file I/O). 2025 standard: FastAPI for async web APIs. Always await coroutines or warnings raised. Essential for modern Python I/O performance.

99% confidence
A

Immutable types cannot change after creation: int, float, str, tuple, frozenset, bytes, bool, None. Mutable types can change: list, dict, set, bytearray, user classes (default unless frozen). Implications: only immutable types as dict keys (hashable), immutable types are thread-safe, function default arguments must be immutable (use def f(x=None): x = x or [] pattern). Gotcha: tuple of mutable objects - tuple itself immutable but contents mutable: t = ([1], [2]); t[0].append(3) works. String operations create new strings: s = 'hello'; s.upper() doesn't modify s. Performance: ''.join(list) 10x faster than repeated + for strings. Frozen dataclasses: @dataclass(frozen=True) creates immutable objects. Type hints: from typing import Final; x: Final = 5 for immutable bindings. Choose immutable for hashability, thread-safety, or semantic immutability.

99% confidence
A

== compares values (equality, calls eq method), is compares identity (same object in memory, id(a) == id(b)). Examples: [1,2,3] == [1,2,3] is True, [1,2,3] is [1,2,3] is False. Singletons: None, True, False are cached - always use is None, not == None. Integer caching: small ints (-5 to 256) cached, so (a := 5) is (b := 5) is True, but (a := 1000) is (b := 1000) is False. String interning: literals may be cached. Best practices: use == for value comparison, is only for None/True/False/singletons. Performance: is is O(1) pointer comparison, == depends on eq implementation. Type narrowing: if x is not None reveals x is non-optional to type checkers. Pattern matching: match x: case None: uses identity check. Understanding prevents bugs like if x == None (wrong) vs if x is None (correct).

99% confidence
A

Structure: try (code that may fail), except (handle specific exceptions), else (runs only if no exception), finally (always runs for cleanup). Catch specific exceptions: except ValueError as e, never bare except (hides bugs). Multiple: except (TypeError, ValueError) as e. Python 3.11+: exception groups with except* for multiple errors: try: ... except* ValueError as e (handles all ValueErrors in group). Raise: raise ValueError('msg'), raise from other_exc for chaining, raise for re-raising. Custom: class MyError(Exception): pass. Best practices: catch specific exceptions, use contextlib.suppress(Exception) for ignored errors, log before re-raising, add exception context with from. Exception hierarchy: catch Exception catches most, catch BaseException catches all (including KeyboardInterrupt - usually wrong). Modern: use try/except for control flow is Pythonic (EAFP: easier to ask forgiveness than permission). Pattern: try/except/else/finally order must be preserved.

99% confidence
A

Virtual environments isolate project dependencies, preventing version conflicts. Tools: venv (built-in, python -m venv .venv), uv (fastest, Rust-based, 10-100x faster than pip, 2025 standard), Poetry (dependency + venv manager), conda (scientific computing). Usage: uv venv && source .venv/bin/activate (Unix) or .venv\Scripts\activate (Windows). Benefits: isolated dependencies, reproducible builds via lockfiles, multiple Python versions per machine, safe experimentation. Modern workflow: uv pip install package (faster), uv pip compile pyproject.toml (generate lockfile), uv pip sync (install from lockfile). Poetry: poetry install handles venv + dependencies automatically. Requirements files: pip freeze > requirements.txt (basic) or use pyproject.toml with [project.dependencies]. deactivate to exit venv. Always use virtual environments - never install packages globally with pip. Production: use Docker with specific Python version + lockfile for total reproducibility.

99% confidence
A

Slicing syntax: seq[start:end:step] where start is inclusive, end is exclusive. Common patterns: seq[:3] (first 3), seq[-3:] (last 3), seq[::2] (every 2nd, evens), seq[1::2] (odd indices), seq[::-1] (reverse), seq[:] (shallow copy), seq[2:8:2] (items 2,4,6). Negative indices: -1 is last, -2 is second-to-last. Omitted values: start defaults to 0, end to len(seq), step to 1. Slice objects: slice(1, 5, 2) equivalent to [1:5:2], useful for reusable slices. Works on: lists, tuples, strings, bytes, bytearray, any getitem implementation. Slice assignment: nums[2:5] = [10, 20] replaces elements (lists only, immutable types error). Performance: slicing creates new object (O(k) for k elements), use itertools.islice() for lazy slicing. Memory: seq[::-1] copies entire sequence, reversed(seq) is iterator (better for large data).

99% confidence
A

Magic methods (dunder = double underscore) enable operator overloading and protocol implementation: init, str, repr, eq, len, getitem, etc. Lifecycle: new (creation), init (initialization), del (destruction). String representation: str (user-friendly, str(x)), repr (developer-friendly, repr(x), should be eval-able). Operators: add (+), sub (-), mul (*), truediv (/), eq (==), lt (<), contains (in). Protocols: len/getitem (sequence), iter/next (iterator), enter/exit (context manager), call (callable), hash (hashable). Attribute access: getattr, setattr, delattr. Pattern matching: match_args (Python 3.10+). Best practices: never call directly (use len(x) not x.len()), always implement repr for debugging, implement eq and hash together. Use @dataclass or typing.Protocol for protocol definitions in modern Python.

99% confidence
A

@staticmethod has no implicit first argument, cannot access instance or class, essentially a namespaced function. @classmethod receives class as first argument (cls), can access/modify class state, useful for alternative constructors. Instance methods receive instance (self). Example: class Date: @classmethod def from_string(cls, s): y,m,d = s.split('-'); return cls(int(y), int(m), int(d)) - factory method. @staticmethod def is_valid(d, m, y): return 1 <= m <= 12 - validation utility. Type hints: from typing import Self; @classmethod def create(cls) -> Self (Python 3.11+). Use classmethod for: alternative constructors, accessing class variables, factory patterns. Use staticmethod for: utilities that don't need instance/class data, pure functions logically grouped with class. Modern pattern: prefer module-level functions over staticmethod unless strong class association. Classmethod more Pythonic than staticmethod in most cases.

99% confidence
A

Lambda creates anonymous single-expression function: lambda args: expression. Returns expression result implicitly, no return keyword. Common use: sorted(items, key=lambda x: x[1]) for sort key, max(data, key=lambda x: x.score) for custom comparisons, map(lambda x: x2, nums) for transformations. Limitations: single expression only (no statements), no type hints (use Callable type for variables), harder to debug (shows as in tracebacks), less readable when complex. PEP 8: never assign lambda to variable (bad: f = lambda x: x2; good: def f(x): return x2). Prefer named functions for: reuse, complexity beyond one line, type hints needed, better error messages. Modern Python: use list comprehensions over map/filter with lambda ([x2 for x in nums] vs map(lambda x: x*2, nums)). Good lambda: simple, one-time use, makes code more concise. Bad lambda: assigned to variable, multiple uses, complex logic.

99% confidence
A

Assignment (=) creates reference (same object), shallow copy creates new container with references to original elements, deep copy recursively copies everything. Shallow: import copy; new = copy.copy(original) or new = original[:] (lists), new = original.copy() (dicts/sets). Deep: new = copy.deepcopy(original). Gotcha: matrix = [[0]3] * 3 creates 3 references to same row (use [list(row) for row in matrix]). Shallow copy of nested structure: outer copied, inner shared - x = [1, [2, 3]]; y = x[:]; y[1].append(4) affects both. Performance: shallow O(n), deep O(nd) where d is nesting depth. Dataclasses: from dataclasses import replace; new = replace(obj, field=value) for shallow copy with changes. Frozen dataclasses: immutable so no need to copy for safety. Use shallow when: top-level modification only, immutable elements. Use deep when: fully independent copy needed, nested mutable structures. Most code needs shallow copy only.

99% confidence
A

Generators are lazy iterators created via yield keyword or generator expressions. Function with yield: def count(n): i = 0; while i < n: yield i; i += 1. yield returns value and suspends execution, next call resumes from yield. Generator expression: (x**2 for x in range(1000000)) creates iterator (vs list comp). Methods: send(value) sends value to generator, throw(exc) raises exception inside, close() terminates. yield from delegates to subgenerator: yield from range(10). Memory: O(1) constant regardless of sequence size. Use for: large/infinite sequences, data pipelines (gen1 -> gen2 -> gen3), reading large files line-by-line. StopIteration raised when exhausted. Async version: async def and async for with async generators. Return in generator: raise StopIteration with return value (access via except StopIteration as e: e.value). Generators one-time use - exhaust and recreate. Understanding generators essential for memory-efficient Python.

99% confidence
A

None is singleton representing absence/null, True/False are boolean singletons. Check None: always use is None or is not None (identity check, faster, type-safe), never == None. Type narrowing: if x is not None reveals x is non-optional to type checkers. Truthiness: falsy values are None, False, 0, 0.0, '', [], {}, set(), empty objects with bool returning False. Truthy: everything else including -1, '0', [0], {0: None}. Pitfall: if x checks truthiness (wrong for 0/''), if x is not None checks existence (correct). Pattern: def f(x=None): x = x or [] (wrong if x=0 intended), x = [] if x is None else x (correct). all([]) returns True (vacuous truth), any([]) returns False. Type hints: Optional[T] = T | None for nullable types. Boolean operators: and/or return operands (x or default pattern), not returns bool. Understanding truthiness essential for idiomatic Python conditionals.

99% confidence
A

Methods: (1) Module-level instance (most Pythonic): # config.py: _instance = Config(); def get_config(): return _instance. (2) new override: def new(cls): if not hasattr(cls, '_instance'): cls._instance = super().new(cls); return cls._instance. (3) Metaclass: class Singleton(type): _instances = {}; def call(cls, *args): if cls not in cls._instances: cls._instances[cls] = super().call(*args); return cls._instances[cls]. (4) Decorator: @functools.lru_cache(maxsize=1) on class factory. Thread-safe new: use threading.Lock. Modern approach: dependency injection with container (avoids global state). Use for: config objects, logging, database connections, caches. Anti-pattern warning: singletons create hidden dependencies, make testing hard - prefer explicit passing or DI. Python 3.13+: use @dataclass(frozen=True) with module-level instance for immutable config. Most Pythonic: module-level instance, simplest and explicit.

99% confidence
A

Essential built-ins: len(seq) (length), range(start, stop, step) (integer sequence), enumerate(iterable, start=0) ((index, value) pairs), zip(*iterables) (parallel iteration, stops at shortest), sorted(iterable, key=None, reverse=False) (returns sorted list), sum(iterable, start=0) (numeric sum), any(iterable) (True if any truthy), all(iterable) (True if all truthy), isinstance(obj, type) (type check), type(obj) (get type), dir(obj) (list attributes), help(obj) (documentation). Modern patterns: enumerate(items, 1) for 1-based indexing, zip(*matrix) to transpose, max(items, key=lambda x: x.score) with key function, any(x > 10 for x in data) with generator. Python 3.10+: zip(a, b, strict=True) raises if lengths differ. Avoid: map/filter (use comprehensions instead), reduce (explicit loop clearer). Power functions: getattr(obj, 'attr', default), setattr(obj, 'attr', val), hasattr(obj, 'attr') for dynamic attribute access. Know these for concise, idiomatic Python.

99% confidence
A

F-strings (f'text {expr} text', Python 3.6+) embed expressions in string literals. Features: any expression f'{x + y}', format specs f'{value:.2f}' (2 decimals), f'{value:>10}' (right-align in 10 chars), f'{value:,}' (thousands separator), debugging f'{x=}' (prints 'x=5'). Python 3.12+: multiline expressions allowed, comments inside f-strings. Conversion: f'{obj!r}' (repr), f'{obj!s}' (str), f'{obj!a}' (ascii). Date formatting: f'{now:%Y-%m-%d}'. Alternatives: %-formatting (old, use only for logging), str.format() (verbose, legacy). Performance: f-strings ~2x faster than %-formatting, most readable. Nested f-strings: f'{f"{x:.{precision}f"}' (avoid, use variables). Multi-line: msg = (f'Line 1 {x}' f'Line 2 {y}'). F-strings are 2025 standard - use exclusively for new code. Template strings (string.Template) only for user-provided templates (security).

99% confidence
A

Modern Python project structure (2025 standard): project_root/ containing pyproject.toml (metadata + dependencies, replaces setup.py), src/package/init.py (source code in src/ layout prevents import confusion), tests/ (pytest tests), README.md, LICENSE, .gitignore. pyproject.toml: [project] table with name/version/dependencies (PEP 621), [build-system] with build-backend, [tool.ruff] for linting, [tool.mypy] for type checking. Tools: uv (fast package manager), Poetry 2.0 (dependency + build manager, supports [project] table), Ruff (all-in-one linter/formatter, replaces Black/Flake8/isort). Entry point: package/main.py or console_scripts in pyproject.toml. Imports: absolute (from package.module import func) preferred over relative. Testing: pytest with tests/ mirroring src/ structure. Pre-commit: .pre-commit-config.yaml with ruff, mypy. Distribution: python -m build creates wheel. No setup.py needed unless complex build (C extensions). Src layout prevents accidental imports of local code during testing.

99% confidence
A

Walrus operator (:=) enables assignment expressions - assign and use variable in single expression (PEP 572, Python 3.8). Syntax: if (n := len(items)) > 10: where n gets value and is used in condition. Use cases: while loops (while (line := file.readline()) != ''), list comprehensions with filtering, avoiding repeated function calls, conditional expressions. Benefits: cleaner code, avoids temporary variables, improves performance by reducing function calls. Avoid overuse - can reduce readability when complex. Perfect for simplifying code that would otherwise require separate assignment before conditional check.

99% confidence
A

Pattern matching (match/case, Python 3.10+) enables structural pattern matching for complex conditionals (PEP 634). Syntax: match value: case pattern:. Pattern types: literals (123, 'hello'), sequences ([x, y]), mappings ({'key': value}), class patterns (Point(x, y)), wildcard (_). Features: guards (case x if x > 5:), capture patterns (case x:), OR patterns (case 0 | 1:). Use cases: parsing data, state machines, complex conditional logic, AST processing. Replaces complex if/elif chains with more readable, maintainable code. Essential for modern Python when dealing with structured data.

99% confidence
A

PEP 8 is Python's official style guide defining code formatting standards. Key rules: 4-space indentation, 79-character line limit (88 for Black), snake_case for functions/variables, PascalCase for classes, 2 blank lines between top-level definitions, imports order (standard library, third-party, local). Philosophy: 'code is read much more often than written'. Modern enforcement: Ruff (fastest linter, replaces Flake8/isort/pydocstyle), Black (opinionated formatter, 88-char default), mypy (type checking). Use pre-commit hooks for automatic enforcement. Not dogmatic - E501 (line length) often relaxed to 100-120 chars in 2025 projects. Essential for team collaboration and code maintainability.

99% confidence
A

Type hints specify expected types for static analysis (runtime unaffected). Python 3.12+ syntax: def func(name: str, age: int) -> str. Modern features: use | for unions (int | str), built-in generics (list[int], dict[str, Any]), new generic syntax class Stack[T] (PEP 695, no TypeVar needed), type aliases with type Point = tuple[float, float]. Type checkers: mypy (standard), pyright (fast, used by VS Code), Pydantic (runtime validation). Benefits: IDE autocomplete, early bug detection, self-documentation, safe refactoring. Python 3.13: TypeIs for type narrowing, default type parameters. Essential for production code - use strict mode (mypy --strict) for maximum safety.

99% confidence
A

Decorators modify functions/classes using @decorator syntax above definition. Implementation: decorator takes callable, returns wrapped callable. Pattern: def decorator(func): @wraps(func); def wrapper(*args, *kwargs): / setup */ result = func(*args, *kwargs); / teardown */ return result; return wrapper. Always use @functools.wraps(func) to preserve name, doc. Built-in: @property, @staticmethod, @classmethod, @dataclass, @lru_cache, @override (Python 3.12+). Parametrized decorators: def with_arg(param): def decorator(func): ... return decorator. Common patterns: @lru_cache(maxsize=128) for memoization, @retry for error handling, @validate for input checking. Type hints: from typing import Callable; def decorator(func: Callable[..., T]) -> Callable[..., T]. Essential for clean, reusable code patterns.

99% confidence
A

List comprehensions [x2 for x in range(10)] build entire list in memory immediately (eager evaluation). Generator expressions (x2 for x in range(10)) create iterator yielding values on-demand (lazy evaluation). Memory: list comp uses O(n) memory, generators use O(1) constant memory. Performance: generators ~2-3x faster for large datasets (no upfront allocation), list comp ~10-20% faster for small datasets (<1000 items). Use list comp when: need len(), indexing, multiple iterations, or small data (<10k items). Use generator when: single pass iteration, large/infinite sequences, memory constrained, pipeline processing (gen1 | gen2 style). Walrus operator pattern: if (n := sum(x for x in data if x > 0)) > threshold. Generators composable for data pipelines.

99% confidence
A

Context managers manage resources via with statement, ensuring cleanup even on exceptions. Protocol: enter(self) returns resource, exit(self, exc_type, exc_val, exc_tb) handles cleanup. Common uses: with open('file') as f (auto-close), with lock (auto-release), with db.transaction() (auto-commit/rollback). Create with @contextmanager: from contextlib import contextmanager; @contextmanager def my_context(): /* setup / yield resource; / cleanup */. Async version: async with for async resources, requires aenter/aexit. Python 3.10+: parenthesized context managers with (open('a') as a, open('b') as b). Use contextlib.suppress(Exception) to ignore specific errors, contextlib.chdir() for temporary directory changes. ExitStack for dynamic number of context managers. Essential pattern for RAII (Resource Acquisition Is Initialization) in Python.

99% confidence
A

GIL is mutex preventing multiple threads from executing Python bytecode simultaneously in CPython. Impact: CPU-bound multi-threaded code runs on single core (no parallel speedup). I/O-bound code unaffected (GIL released during I/O operations). Python 3.13+: experimental free-threaded mode (build with --disable-gil, run python3.13t) allows true parallelism but ~40% slower single-threaded. Python 3.14: free-threading promoted from experimental to supported (PEP 779). Check GIL status: sys._is_gil_enabled(). Workarounds: multiprocessing for CPU tasks (separate processes), asyncio for I/O concurrency, C extensions with Py_BEGIN_ALLOW_THREADS. Use free-threaded Python 3.13+ for CPU parallelism with threads. Future: GIL likely optional by Python 3.15, eventual default removal planned.

99% confidence
A

*args captures positional arguments as tuple, **kwargs captures keyword arguments as dict. Signature: def func(*args, **kwargs). Unpacking: func(*my_list, **my_dict). Parameter order: positional, *args, keyword-only, **kwargs. Example: def f(a, b, *args, c, d=5, **kwargs). Type hints: def f(*args: int, **kwargs: str) or from typing import Unpack; def f(**kwargs: Unpack[MyTypedDict]). Python 3.8+: positional-only with /: def f(a, b, /, *args, **kwargs). Use for: decorators, wrappers, flexible APIs, forwarding arguments. Introspection: inspect.signature(func) to examine parameters. Modern pattern: prefer explicit parameters over **kwargs for better IDE support and type safety. Use TypedDict with Unpack for typed **kwargs in Python 3.12+.

99% confidence
A

@dataclass decorator (PEP 557, Python 3.7+) auto-generates init, repr, eq, hash. Syntax: @dataclass class Point: x: float; y: float; z: float = 0.0. Python 3.10+ features: slots=True (memory optimization, ~40% less memory, faster attribute access), kw_only=True (keyword-only init), match_args=False (disable pattern matching). Frozen dataclasses: @dataclass(frozen=True) for immutability (hashable, thread-safe). Post-init: post_init(self) for validation. Field options: field(default_factory=list) for mutable defaults, field(repr=False) to hide from repr. Use for: DTOs, config objects, domain models, replacing namedtuples. Alternatives: Pydantic (runtime validation, serialization), attrs (more features). Modern Python standard for data containers - use slots=True for production.

99% confidence
A

asyncio provides single-threaded concurrent I/O via async/await syntax. async def creates coroutine, await suspends until awaitable completes, event loop schedules execution. Entry point: asyncio.run(main()). Create tasks: asyncio.create_task(coro) for concurrent execution, asyncio.gather(*coros) to wait for multiple. Use for: I/O-bound operations (HTTP requests, database queries, file I/O), WebSocket servers, concurrent API calls. NOT for CPU-bound tasks (use ProcessPoolExecutor). Common pitfall: never use blocking calls (time.sleep, requests.get) - use await asyncio.sleep(), aiohttp instead. Control concurrency: asyncio.Semaphore(10) limits concurrent operations. Libraries: aiohttp (HTTP), asyncpg (PostgreSQL), motor (MongoDB), aiofiles (file I/O). 2025 standard: FastAPI for async web APIs. Always await coroutines or warnings raised. Essential for modern Python I/O performance.

99% confidence
A

Immutable types cannot change after creation: int, float, str, tuple, frozenset, bytes, bool, None. Mutable types can change: list, dict, set, bytearray, user classes (default unless frozen). Implications: only immutable types as dict keys (hashable), immutable types are thread-safe, function default arguments must be immutable (use def f(x=None): x = x or [] pattern). Gotcha: tuple of mutable objects - tuple itself immutable but contents mutable: t = ([1], [2]); t[0].append(3) works. String operations create new strings: s = 'hello'; s.upper() doesn't modify s. Performance: ''.join(list) 10x faster than repeated + for strings. Frozen dataclasses: @dataclass(frozen=True) creates immutable objects. Type hints: from typing import Final; x: Final = 5 for immutable bindings. Choose immutable for hashability, thread-safety, or semantic immutability.

99% confidence
A

== compares values (equality, calls eq method), is compares identity (same object in memory, id(a) == id(b)). Examples: [1,2,3] == [1,2,3] is True, [1,2,3] is [1,2,3] is False. Singletons: None, True, False are cached - always use is None, not == None. Integer caching: small ints (-5 to 256) cached, so (a := 5) is (b := 5) is True, but (a := 1000) is (b := 1000) is False. String interning: literals may be cached. Best practices: use == for value comparison, is only for None/True/False/singletons. Performance: is is O(1) pointer comparison, == depends on eq implementation. Type narrowing: if x is not None reveals x is non-optional to type checkers. Pattern matching: match x: case None: uses identity check. Understanding prevents bugs like if x == None (wrong) vs if x is None (correct).

99% confidence
A

Structure: try (code that may fail), except (handle specific exceptions), else (runs only if no exception), finally (always runs for cleanup). Catch specific exceptions: except ValueError as e, never bare except (hides bugs). Multiple: except (TypeError, ValueError) as e. Python 3.11+: exception groups with except* for multiple errors: try: ... except* ValueError as e (handles all ValueErrors in group). Raise: raise ValueError('msg'), raise from other_exc for chaining, raise for re-raising. Custom: class MyError(Exception): pass. Best practices: catch specific exceptions, use contextlib.suppress(Exception) for ignored errors, log before re-raising, add exception context with from. Exception hierarchy: catch Exception catches most, catch BaseException catches all (including KeyboardInterrupt - usually wrong). Modern: use try/except for control flow is Pythonic (EAFP: easier to ask forgiveness than permission). Pattern: try/except/else/finally order must be preserved.

99% confidence
A

Virtual environments isolate project dependencies, preventing version conflicts. Tools: venv (built-in, python -m venv .venv), uv (fastest, Rust-based, 10-100x faster than pip, 2025 standard), Poetry (dependency + venv manager), conda (scientific computing). Usage: uv venv && source .venv/bin/activate (Unix) or .venv\Scripts\activate (Windows). Benefits: isolated dependencies, reproducible builds via lockfiles, multiple Python versions per machine, safe experimentation. Modern workflow: uv pip install package (faster), uv pip compile pyproject.toml (generate lockfile), uv pip sync (install from lockfile). Poetry: poetry install handles venv + dependencies automatically. Requirements files: pip freeze > requirements.txt (basic) or use pyproject.toml with [project.dependencies]. deactivate to exit venv. Always use virtual environments - never install packages globally with pip. Production: use Docker with specific Python version + lockfile for total reproducibility.

99% confidence
A

Slicing syntax: seq[start:end:step] where start is inclusive, end is exclusive. Common patterns: seq[:3] (first 3), seq[-3:] (last 3), seq[::2] (every 2nd, evens), seq[1::2] (odd indices), seq[::-1] (reverse), seq[:] (shallow copy), seq[2:8:2] (items 2,4,6). Negative indices: -1 is last, -2 is second-to-last. Omitted values: start defaults to 0, end to len(seq), step to 1. Slice objects: slice(1, 5, 2) equivalent to [1:5:2], useful for reusable slices. Works on: lists, tuples, strings, bytes, bytearray, any getitem implementation. Slice assignment: nums[2:5] = [10, 20] replaces elements (lists only, immutable types error). Performance: slicing creates new object (O(k) for k elements), use itertools.islice() for lazy slicing. Memory: seq[::-1] copies entire sequence, reversed(seq) is iterator (better for large data).

99% confidence
A

Magic methods (dunder = double underscore) enable operator overloading and protocol implementation: init, str, repr, eq, len, getitem, etc. Lifecycle: new (creation), init (initialization), del (destruction). String representation: str (user-friendly, str(x)), repr (developer-friendly, repr(x), should be eval-able). Operators: add (+), sub (-), mul (*), truediv (/), eq (==), lt (<), contains (in). Protocols: len/getitem (sequence), iter/next (iterator), enter/exit (context manager), call (callable), hash (hashable). Attribute access: getattr, setattr, delattr. Pattern matching: match_args (Python 3.10+). Best practices: never call directly (use len(x) not x.len()), always implement repr for debugging, implement eq and hash together. Use @dataclass or typing.Protocol for protocol definitions in modern Python.

99% confidence
A

@staticmethod has no implicit first argument, cannot access instance or class, essentially a namespaced function. @classmethod receives class as first argument (cls), can access/modify class state, useful for alternative constructors. Instance methods receive instance (self). Example: class Date: @classmethod def from_string(cls, s): y,m,d = s.split('-'); return cls(int(y), int(m), int(d)) - factory method. @staticmethod def is_valid(d, m, y): return 1 <= m <= 12 - validation utility. Type hints: from typing import Self; @classmethod def create(cls) -> Self (Python 3.11+). Use classmethod for: alternative constructors, accessing class variables, factory patterns. Use staticmethod for: utilities that don't need instance/class data, pure functions logically grouped with class. Modern pattern: prefer module-level functions over staticmethod unless strong class association. Classmethod more Pythonic than staticmethod in most cases.

99% confidence
A

Lambda creates anonymous single-expression function: lambda args: expression. Returns expression result implicitly, no return keyword. Common use: sorted(items, key=lambda x: x[1]) for sort key, max(data, key=lambda x: x.score) for custom comparisons, map(lambda x: x2, nums) for transformations. Limitations: single expression only (no statements), no type hints (use Callable type for variables), harder to debug (shows as in tracebacks), less readable when complex. PEP 8: never assign lambda to variable (bad: f = lambda x: x2; good: def f(x): return x2). Prefer named functions for: reuse, complexity beyond one line, type hints needed, better error messages. Modern Python: use list comprehensions over map/filter with lambda ([x2 for x in nums] vs map(lambda x: x*2, nums)). Good lambda: simple, one-time use, makes code more concise. Bad lambda: assigned to variable, multiple uses, complex logic.

99% confidence
A

Assignment (=) creates reference (same object), shallow copy creates new container with references to original elements, deep copy recursively copies everything. Shallow: import copy; new = copy.copy(original) or new = original[:] (lists), new = original.copy() (dicts/sets). Deep: new = copy.deepcopy(original). Gotcha: matrix = [[0]3] * 3 creates 3 references to same row (use [list(row) for row in matrix]). Shallow copy of nested structure: outer copied, inner shared - x = [1, [2, 3]]; y = x[:]; y[1].append(4) affects both. Performance: shallow O(n), deep O(nd) where d is nesting depth. Dataclasses: from dataclasses import replace; new = replace(obj, field=value) for shallow copy with changes. Frozen dataclasses: immutable so no need to copy for safety. Use shallow when: top-level modification only, immutable elements. Use deep when: fully independent copy needed, nested mutable structures. Most code needs shallow copy only.

99% confidence
A

Generators are lazy iterators created via yield keyword or generator expressions. Function with yield: def count(n): i = 0; while i < n: yield i; i += 1. yield returns value and suspends execution, next call resumes from yield. Generator expression: (x**2 for x in range(1000000)) creates iterator (vs list comp). Methods: send(value) sends value to generator, throw(exc) raises exception inside, close() terminates. yield from delegates to subgenerator: yield from range(10). Memory: O(1) constant regardless of sequence size. Use for: large/infinite sequences, data pipelines (gen1 -> gen2 -> gen3), reading large files line-by-line. StopIteration raised when exhausted. Async version: async def and async for with async generators. Return in generator: raise StopIteration with return value (access via except StopIteration as e: e.value). Generators one-time use - exhaust and recreate. Understanding generators essential for memory-efficient Python.

99% confidence
A

None is singleton representing absence/null, True/False are boolean singletons. Check None: always use is None or is not None (identity check, faster, type-safe), never == None. Type narrowing: if x is not None reveals x is non-optional to type checkers. Truthiness: falsy values are None, False, 0, 0.0, '', [], {}, set(), empty objects with bool returning False. Truthy: everything else including -1, '0', [0], {0: None}. Pitfall: if x checks truthiness (wrong for 0/''), if x is not None checks existence (correct). Pattern: def f(x=None): x = x or [] (wrong if x=0 intended), x = [] if x is None else x (correct). all([]) returns True (vacuous truth), any([]) returns False. Type hints: Optional[T] = T | None for nullable types. Boolean operators: and/or return operands (x or default pattern), not returns bool. Understanding truthiness essential for idiomatic Python conditionals.

99% confidence
A

Methods: (1) Module-level instance (most Pythonic): # config.py: _instance = Config(); def get_config(): return _instance. (2) new override: def new(cls): if not hasattr(cls, '_instance'): cls._instance = super().new(cls); return cls._instance. (3) Metaclass: class Singleton(type): _instances = {}; def call(cls, *args): if cls not in cls._instances: cls._instances[cls] = super().call(*args); return cls._instances[cls]. (4) Decorator: @functools.lru_cache(maxsize=1) on class factory. Thread-safe new: use threading.Lock. Modern approach: dependency injection with container (avoids global state). Use for: config objects, logging, database connections, caches. Anti-pattern warning: singletons create hidden dependencies, make testing hard - prefer explicit passing or DI. Python 3.13+: use @dataclass(frozen=True) with module-level instance for immutable config. Most Pythonic: module-level instance, simplest and explicit.

99% confidence
A

Essential built-ins: len(seq) (length), range(start, stop, step) (integer sequence), enumerate(iterable, start=0) ((index, value) pairs), zip(*iterables) (parallel iteration, stops at shortest), sorted(iterable, key=None, reverse=False) (returns sorted list), sum(iterable, start=0) (numeric sum), any(iterable) (True if any truthy), all(iterable) (True if all truthy), isinstance(obj, type) (type check), type(obj) (get type), dir(obj) (list attributes), help(obj) (documentation). Modern patterns: enumerate(items, 1) for 1-based indexing, zip(*matrix) to transpose, max(items, key=lambda x: x.score) with key function, any(x > 10 for x in data) with generator. Python 3.10+: zip(a, b, strict=True) raises if lengths differ. Avoid: map/filter (use comprehensions instead), reduce (explicit loop clearer). Power functions: getattr(obj, 'attr', default), setattr(obj, 'attr', val), hasattr(obj, 'attr') for dynamic attribute access. Know these for concise, idiomatic Python.

99% confidence
A

F-strings (f'text {expr} text', Python 3.6+) embed expressions in string literals. Features: any expression f'{x + y}', format specs f'{value:.2f}' (2 decimals), f'{value:>10}' (right-align in 10 chars), f'{value:,}' (thousands separator), debugging f'{x=}' (prints 'x=5'). Python 3.12+: multiline expressions allowed, comments inside f-strings. Conversion: f'{obj!r}' (repr), f'{obj!s}' (str), f'{obj!a}' (ascii). Date formatting: f'{now:%Y-%m-%d}'. Alternatives: %-formatting (old, use only for logging), str.format() (verbose, legacy). Performance: f-strings ~2x faster than %-formatting, most readable. Nested f-strings: f'{f"{x:.{precision}f"}' (avoid, use variables). Multi-line: msg = (f'Line 1 {x}' f'Line 2 {y}'). F-strings are 2025 standard - use exclusively for new code. Template strings (string.Template) only for user-provided templates (security).

99% confidence
A

Modern Python project structure (2025 standard): project_root/ containing pyproject.toml (metadata + dependencies, replaces setup.py), src/package/init.py (source code in src/ layout prevents import confusion), tests/ (pytest tests), README.md, LICENSE, .gitignore. pyproject.toml: [project] table with name/version/dependencies (PEP 621), [build-system] with build-backend, [tool.ruff] for linting, [tool.mypy] for type checking. Tools: uv (fast package manager), Poetry 2.0 (dependency + build manager, supports [project] table), Ruff (all-in-one linter/formatter, replaces Black/Flake8/isort). Entry point: package/main.py or console_scripts in pyproject.toml. Imports: absolute (from package.module import func) preferred over relative. Testing: pytest with tests/ mirroring src/ structure. Pre-commit: .pre-commit-config.yaml with ruff, mypy. Distribution: python -m build creates wheel. No setup.py needed unless complex build (C extensions). Src layout prevents accidental imports of local code during testing.

99% confidence
A

Walrus operator (:=) enables assignment expressions - assign and use variable in single expression (PEP 572, Python 3.8). Syntax: if (n := len(items)) > 10: where n gets value and is used in condition. Use cases: while loops (while (line := file.readline()) != ''), list comprehensions with filtering, avoiding repeated function calls, conditional expressions. Benefits: cleaner code, avoids temporary variables, improves performance by reducing function calls. Avoid overuse - can reduce readability when complex. Perfect for simplifying code that would otherwise require separate assignment before conditional check.

99% confidence
A

Pattern matching (match/case, Python 3.10+) enables structural pattern matching for complex conditionals (PEP 634). Syntax: match value: case pattern:. Pattern types: literals (123, 'hello'), sequences ([x, y]), mappings ({'key': value}), class patterns (Point(x, y)), wildcard (_). Features: guards (case x if x > 5:), capture patterns (case x:), OR patterns (case 0 | 1:). Use cases: parsing data, state machines, complex conditional logic, AST processing. Replaces complex if/elif chains with more readable, maintainable code. Essential for modern Python when dealing with structured data.

99% confidence