Python
100 questions
How to create a virtual environment?
•python -m venv venv.
•Activation on Windows: venv\Scripts\activate.
•Linux/Mac: source venv/bin/activate.
•Deactivation: deactivate.
•pip install package.
What are the differences between lists, tuples, sets?
•List — mutable: [1,2,3].
•Tuple — immutable: (1,2,3).
•Set — no duplicates: {1,2,3}.
•Dictionary — key-value pairs.
•Tuples are hashable.
What are decorators?
•A function that modifies another function.
•@decorator above a definition.
•def log(f): def wrapper(*a): return f(*a); return wrapper.
•functools.wraps preserves name/docstring.
•Examples: @property, @staticmethod.
How to work with files?
•with open('file.txt', 'r', encoding='utf-8') as f:.
•f.read() or for line in f:.
•Modes: r, w, a, rb.
•with automatically closes the file.
•pathlib.Path — modern approach.
What are generators?
•Function with yield.
•Returns an iterator.
•Lazy evaluation (saves memory).
•next(gen) — get next element.
•Generator expression: (x*2 for x in range(10)).
How to install Python and verify it works?
•Download from python.org or install via package manager.
•Check: python --version (or python3 --version).
•Check pip: python -m pip --version.
•Update pip: python -m pip install -U pip.
•Run REPL: python.
What is the difference between python and python3 in Linux?
•In some distributions, python = Python 2 (historically) or absent.
•python3 always points to Python
3.
•For scripts, better to use shebang: #!/usr/bin/env python3.
•pip/pip3 similarly.
•Virtual environments resolve version conflicts.
How to properly set dependencies in a project?
•Create venv.
•Install packages via python -m pip install ....
•Freeze dependencies: pip freeze > requirements.txt.
•On another PC: pip install -r requirements.txt.
•For larger projects, consider Poetry/uv.
What is PEP 8 and why is it needed?
•PEP 8 — Python code style.
•Makes code readable and consistent in a team.
•Indents: 4 spaces.
•Names: snake_case for functions/variables, PascalCase for classes.
•Autoformatter: black, linter: ruff.
How does module import (import) work in Python?
•import searches for a module in sys.path.
•The local project folder is usually at the beginning of sys.path.
•__init__.py file makes a folder a package (mandatory in older versions).
•Relative imports: from .sub import x.
•Avoid cyclic imports.
What is the difference between shallow copy and deep copy?
•Shallow copy copies only the top level of the container.
•Nested objects remain shared.
•Deep copy recursively copies everything.
•Shallow: list.copy(), copy.copy().
•Deep: copy.deepcopy() (can be expensive).
When to use list and when to use tuple?
•list — if you need to modify contents.
•tuple — if data should be immutable.
•tuple can be used as a dict key (if elements are hashable).
•tuple is usually slightly more compact.
•For returning “packets” of values, tuple is convenient.
How are dicts structured and which operations are fast?
•dict — hash table.
•Access/insertion/deletion by key is usually O(1).
•Key must be hashable (immutable).
•Insertion order is preserved (Python 3.7+ guaranteed).
•Use collections.Counter for counting.
How to nicely format strings (f-string)?
•f'Hello, {name}'.
•Format: f'{value:.2f}' for float.
•Dates: f'{dt:%Y-%m-%d}'.
•Width: f'{n:>10}'.
•For debugging: f'{var=}' (3.8+).
How does unpacking *args and **kwargs work?
•*args — positional arguments as a tuple.
•**kwargs — named arguments as a dict.
•You can proxy a call: f(*args, **kwargs).
•Collection unpacking: [*a, *b].
•Dict unpacking: {**d1, **d2}.
What is list comprehension and when to use it?
•Short syntax for creating a list.
•Example: [x*x for x in range(
•if x % 2 == 0].
•Readable compared to manual loop (if expression is simple).
•Use (...) for generator.
•Be careful with nested loops, don't overcomplicate.
How does generator expression differ from list comprehension?
•List comprehension creates a list immediately.
•Generator expression creates items lazily.
•Generator saves memory on large data.
•Example: sum(x*x for x in data).
•Generator can be “exhausted” once.
How does enumerate work and why is it convenient?
•enumerate(iterable) gives (index, value).
•Example: for i, item in enumerate(items, start=1): ...
•Eliminates manual counter.
•Works with any iterator.
•Improves readability.
How to properly sort lists (sorted vs sort)?
•list.sort() sorts in place and returns None.
•sorted(iterable) returns a new list.
•key= — key function: sorted(users, key=lambda u: u.age).
•reverse=True — reverse order.
•Stable sorting (important for multi-level).
How to combine and filter collections (map/filter) and when is comprehension better?
•map/filter return iterators.
•Example: map(str, nums).
•filter(fn, items) keeps elements where fn=True.
•Comprehension is often easier to read.
•For complex logic, a regular loop is better.
How is exception handling structured with try/except/else/finally?
•try — code that might fail.
•except catches specific exceptions (don't catch bare except).
•else runs if no exception occurred.
•finally always runs (cleanup).
•raise to propagate/create an error.
How to create a custom exception?
•Inherit from Exception: class MyError(Exception): pass.
•Use a meaningful name.
•Pass a message: raise MyError('...').
•For parameters — store them in attributes.
•Do not inherit from BaseException.
What is a context manager and with?
•with guarantees resource release.
•Files, locks, connections.
•Custom manager: implement __enter__ and __exit__.
•Or use contextlib.contextmanager.
•Simplifies safe code.
How to work with date and time (datetime)?
•datetime.datetime.now() — current local time.
•Better to store UTC: datetime.datetime.now(datetime.timezone.utc).
•Parsing: datetime.datetime.fromisoformat(...).
•Formatting: dt.strftime('%Y-%m-%d').
•Difference: timedelta.
How to safely work with paths (pathlib)?
•from pathlib import Path.
•p = Path('data') / 'file.txt'.
•p.exists(), p.is_file(), p.read_text(encoding='utf-8').
•Create folder: p.parent.mkdir(parents=True, exist_ok=True).
•Cross-platform and readable.
How to read/write JSON?
•import json.
•json.loads(text) → dict/list.
•json.dumps(obj, ensure_ascii=False) → string.
•For files: json.load(fp), json.dump(obj, fp).
•For datetime, convert (e.g., ISO string).
What is a dataclass and why is it needed?
•dataclass reduces boilerplate for data classes.
•@dataclass automatically creates __init__/__repr__/__eq__.
•You can set frozen=True (immutability).
•default_factory for lists/dicts.
•Useful for DTOs/models.
How to create an immutable object in Python?
•Use dataclass(frozen=True).
•Or NamedTuple / typing.NamedTuple.
•For collections: tuple instead of list, frozenset instead of set.
•Do not mutate internal structures.
•For configs, it reduces bugs.
What is @property and when to use it?
•Makes the method look like a field.
•Allows computed properties.
•You can add validation in setter.
•Helps hide internal representation.
•Don't abuse — complexity also increases.
How do inheritance and super() work?
•class Child(Parent): ...
•super() calls methods of the base class according to MRO.
•In multiple inheritance, MRO is critical.
•Always use super() in cooperative classes.
•Check MRO: Class.mro().
What is MRO and why is it important?
•MRO — the method search order in inheritance.
•Uses the C3 linearization algorithm.
•Affects super() in multiple inheritance.
•MRO errors → TypeError when creating a class.
•See Class.__mro__ / Class.mro().
What are dunder methods (__str__, __repr__, __iter__)?
•These are object behavior protocols.
•__repr__ — for developers, __str__ — for users.
•__len__ makes the object compatible with len().
•__iter__/__next__ — iterator.
•__enter__/__exit__ — context manager.
How to correctly implement __repr__?
•Make an unambiguous representation.
•Ideally: so that the object can be reconstructed (if really possible).
•Use f'ClassName(x={self.x!r})'.
•Do not perform heavy computations.
•For dataclass, __repr__ is generated automatically.
What is an iterator and an iterable object?
•Iterable — something you can loop over with for.
•Iterator — object with __iter__ and __next__.
•iter(obj) returns an iterator.
•next(it) gives the next element or raises StopIteration.
•Generators are iterators.
How to use itertools for efficient loops?
•itertools.chain combines sequences.
•itertools.islice creates a “slice” of an iterator.
•itertools.groupby groups data (on sorted data).
•itertools.product for Cartesian product.
•Good for large data streams.
What is the difference between * and / in function signatures (keyword-only and positional-only)?
•f(a, /, b) — a is positional-only.
•f(*, x, y) — x and y are keyword-only.
•Reduces errors in calls.
•Helps maintain API.
•Often used in library code.
What is typing and why are type hints needed?
•Type hints — type annotations (not mandatory for the interpreter).
•Improve IDE autocomplete.
•Help static analyzers (mypy/pyright).
•Document API.
•Reduce bugs in large projects.
How to use Optional, Union, and | (PEP 604)?
•Optional[str] = Union[str, None].
•In 3.10+: str | None.
•Union[int, str] = int | str.
•Prefer | in modern code.
•Don't forget about handling None.
What is Protocol and when is it useful?
•Protocol describes a "duck type" by methods.
•Allows typing interfaces without inheritance.
•Example: an object with a .read() method.
•Useful for mocks and abstractions.
•Requires typing.Protocol (3.8+) or typing_extensions.
How to properly log (logging) instead of print?
•import logging; log = logging.getLogger(__name__).
•Use levels: debug/info/warning/error.
•Configure format and handler.
•Do not log secrets (tokens/passwords).
•Do not configure root-logger in the library.
How to read large files without loading into memory?
•Iterate over lines: for line in f:.
•For binary — read in chunks: f.read(8192).
•Use generators for pipelines.
•Do not do f.read() on gigabytes.
•For CSV — csv.reader line by line.
How to work with CSV?
•import csv.
•reader = csv.DictReader(f).
•Use: csv.DictWriter(...).writeheader(); writer.writerow(...).
•Specify newline='' when opening.
•For encodings use encoding='utf-8'.
How to quickly find minimum/maximum by key?
•min(items, key=...).
•max(items, key=...).
•key can be lambda or attrgetter.
•For dict: max(d, key=d.get).
•More readable than manual loops.
How to use collections.Counter and defaultdict?
•Counter counts frequencies: Counter(words).
•most_common(n) — top-N.
•defaultdict(list) is convenient for grouping.
•defaultdict(int) — counter without if.
•Improves readability and speed of code.
How to group list elements by key?
•For small data: defaultdict(list).
•group[key].append(item).
•For groupby, sort first by key.
•key function should be stable.
•Result usually dict[key] -> list[items].
How to make HTTP requests in Python?
•Popular: requests (if available).
•In standard library: urllib.request (less convenient).
•For async: httpx or aiohttp.
•Always set a timeout.
•Check status and handle errors.
How to safely parse user input?
•Explicitly convert types: int(x), float(x) with try/except.
•Check ranges and format.
•Do not use eval/exec on input data.
•For JSON use json.loads.
•For paths — pathlib and whitelisting.
What is an f-string and why is it better than format?
•f-string is faster and more readable.
•Supports expressions inside {}.
•Convenient for formatting numbers/dates.
•Easier to maintain than concatenation.
•format is useful when template is stored separately.
How to create a CLI script in Python?
•Entry point: if __name__ == '__main__': main().
•Parsing arguments: argparse.
•Return code: sys.exit(code).
•Logs instead of print in complex utilities.
•Specify shebang for Linux.
How to use argparse for command-line arguments?
•parser = argparse.ArgumentParser().
•parser.add_argument('--path', required=True).
•args = parser.parse_args().
•Support subcommands: add_subparsers().
•Auto-generate help.
What is asyncio and when is it needed?
•asyncio — concurrency for I/O (network/files) without threads.
•Use async def and await.
•Does not speed up CPU-heavy tasks.
•Suitable for web services/bots/parsers.
•For CPU — multiprocessing.
What is the difference between threading and multiprocessing?
•threading — threads in one process, shared GIL.
•Good for I/O tasks.
•multiprocessing — separate processes, parallelize CPU.
•IPC and serialization are more expensive.
•Choice depends on workload profile.
What is GIL and how does it affect performance?
•GIL limits Python bytecode execution to one thread.
•CPU-bound tasks do not scale with threads.
•I/O tasks usually work fine with threads.
•For CPU — multiprocessing or NumPy (C code).
•Alternatives: PyPy, Cython, Rust/Go extensions.
How to run multiple async tasks in parallel?
•Create tasks: asyncio.create_task(coro()).
•Gather: await asyncio.gather(*tasks).
•Use Semaphore to limit concurrency.
•Handle exceptions (return_exceptions).
•Remember about timeouts.
How to properly implement timeouts in asyncio?
•asyncio.wait_for(coro, timeout=...).
•In Python 3.11+: asyncio.timeout().
•Set timeouts at library level for network clients.
•Catch asyncio.TimeoutError.
•Retry with backoff if needed.
How to write tests: unittest or pytest?
•unittest — standard library, more “Java-style”.
•pytest — simpler syntax, powerful fixtures.
•Convenient to run in CI.
•Structure tests by modules/features.
•Isolate external dependencies with mocks.
How to mock dependencies in tests?
•Use unittest.mock (patch, MagicMock).
•Mock at the point of use, not definition.
•Prefer dependency injection where possible.
•Check calls: assert_called_once_with.
•Do not turn tests into copies of implementation.
How to work with fixtures in pytest?
•@pytest.fixture for setup data.
•scope=function/module/session.
•Fixture can return an object or yield for teardown.
•Fixtures can be parameterized.
•Reduces test duplication.
How to measure test coverage?
•coverage.py or pytest-cov.
•Run: pytest --cov=package.
•View the HTML report.
•High coverage does not guarantee quality, but helps.
•Goal: cover critical business logic.
How to profile Python code?
•cProfile for general profiling.
•timeit for micro-benchmarks.
•line_profiler for line-by-line analysis.
•py-spy for production without injection.
•Measure first, then optimize.
What are context managers (contextlib.contextmanager)?
•Allows writing with statements via generator.
•@contextmanager decorator on a function.
•yield separates enter/exit.
•Do cleanup in finally.
•Useful for temporary settings/resources.
How to cache computations (functools.lru_cache)?
•@lru_cache(maxsize=...).
•Works for pure functions.
•Arguments must be hashable.
•cache_clear() clears cache.
•For complex cases — external cache (Redis).
How to use @dataclass with default_factory?
•Mutable default values cannot be default=[].
•Use field(default_factory=list).
•Similarly for dict/set.
•Prevents shared list across instances.
•Common beginner mistake.
Why is it dangerous to write def f(x, arr=[])?
•Default value is computed once at function definition.
•List will be shared across calls.
•Correct: def f(x, arr=None): arr = arr or [].
•Same for dict/set.
•Classic Python trap.
How to handle project configuration?
•Separate config and code.
•Use environment variables for secrets.
•For .env, use python-dotenv.
•Validate config (pydantic/settings).
•Do not commit secrets to git.
How to work with SQLite (sqlite3)?
•import sqlite3; conn = sqlite3.connect('db.sqlite').
•cursor.execute('SELECT ...', params).
•Use parameterization, not concatenation.
•conn.commit() to save.
•conn.close() or use context manager.
What is SQLAlchemy and why is it needed?
•ORM and SQL toolkit.
•Write queries via Python expressions.
•Easy migrations via Alembic.
•Suitable for complex projects.
•For simple scripts, sqlite3 may suffice.
How to correctly work with files in binary mode?
•open(path, 'rb') for reading bytes.
•For writing: 'wb'.
•Do not specify encoding in binary mode.
•For large files — use chunks.
•For hashes — hashlib.
How to compute file hash (sha256)?
•import hashlib.
•h = hashlib.sha256().
•Read the file in chunks and h.update(chunk).
•At the end, h.hexdigest().
•Do not read a huge file entirely.
How to work with regular expressions (re)?
•re.search/findall/sub.
•Compile the pattern: re.compile(pattern).
•Use raw strings: r'\d+'.
•Flags: re.I, re.M, re.S.
•Don't complicate regex if it can be simpler.
How to write readable code: small functions, clear names?
•One function — one responsibility.
•Clear names are more important than comments.
•Avoid “magic” numbers — put them in constants.
•Write docstring for public API.
•Refactor if it becomes hard to read.
How to use linters and formatters (ruff/black)?
•Black formats code automatically.
•Ruff combines linter and rules.
•Configure in pyproject.toml.
•Run in CI to avoid fixing style manually.
•Don't argue with style — automate it.
How are packages and __init__.py files structured?
•A package is a folder with modules.
•__init__.py can export public API.
•Avoid heavy imports in __init__.py.
•Avoid cyclic dependencies.
•Keep the structure simple.
How to work with virtual environments in IDE?
•Create venv in the project root.
•Select the venv interpreter in IDE settings.
•Install dependencies into this venv.
•Check that IDE terminal also uses venv.
•Don't mix global and project packages.
How to package a project (pyproject.toml) and install it?
•Modern standard — pyproject.toml.
•Specify dependencies and metadata.
•Use Poetry/uv/pip-tools as preferred.
•Version and release consciously.
•Publishing to PyPI is a separate step (twine).
How to organize project structure for an application?
•Separate domain/logic and infrastructure (IO).
•Don't mix API layer and business logic.
•Keep dependencies explicit.
•Add tests/ next to code or separately.
•Extract configs into a separate module.
How to work with dependencies: requirements.txt vs poetry.lock?
•requirements.txt — simple list of dependencies (pip).
•Lock file fixes exact versions.
•Poetry creates lock automatically.
•Reproducibility is important for production.
•Don't update dependencies without tests.
How to read environment variables in Python?
•import os.
•os.environ['KEY'] (will crash if missing).
•os.getenv('KEY', default) is safer.
•Convert types explicitly (int/bool).
•For .env, use python-dotenv (in dev).
How to safely work with secrets (API keys)?
•Never store keys in the repository.
•Use env vars/secret manager.
•Limit key permissions (minimum).
•Rotate keys in case of leaks.
•Mask in logs and errors.
How to handle HTTP errors and retries?
•Check response status and response.raise_for_status() (requests).
•Set timeouts.
•Retry only for idempotent requests.
•Use exponential backoff.
•Log failure reasons.
What are runtime type contracts (pydantic)?
•Type hints alone do not validate data.
•Pydantic validates incoming data in models.
•Convenient for API/configs.
•Generates understandable errors.
•Do not use for “hot” paths where every nanosecond counts.
How to serialize dataclass to dict/JSON?
•dataclasses.asdict(obj) → dict.
•Then json.dumps(dict).
•Convert datetime to string.
•asdict works recursively for nested objects.
•Use pydantic or explicit code for format control.
How to compare strings correctly considering case/locale?
•For simple: s.lower() or s.casefold().
•casefold is better for Unicode.
•Locale-specific processing requires separate handling (locale).
•Don’t forget strip() for input.
•Use in/startswith/endswith for searching.
How to work with encodings and Unicode?
•Always specify encoding when working with text files.
•Terminal/Windows may need configuration.
•Inside Python, strings are Unicode.
•Bytes ↔ string: encode/decode.
•Solve issues at IO boundary.
How to handle input/output errors (IOError/OSError)?
•Catch specific exceptions: FileNotFoundError, PermissionError.
•Check file existence if needed.
•Do atomic write (via temp file).
•Log context (path, operation).
•Do not silently hide errors.
How to perform atomic file write?
•Write to a temporary file nearby.
•fsync if needed.
•Then replace/rename to target path (atomic on most FS).
•Use pathlib and os.replace.
•Protects against corrupted files on crash.
How are exception generators and raise from chains structured?
•raise NewError() from e preserves the cause.
•Improves diagnostics.
•Without from, cause is lost or unclear.
•Use for wrapping low-level errors.
•Can suppress context: raise ... from None.
How to write a proper docstring?
•Briefly: what the function does.
•Describe arguments and return value.
•Mention exceptions if important.
•Usage examples help.
•Follow a style (Google/Numpy) consistently in the project.
How to work with dates in ISO format?
•Save dates as an ISO 8601 string or UTC timestamp.
•Parsing: datetime.fromisoformat (for standard ISO).
•Formatting: dt.isoformat().
•For timezone, use timezone-aware datetime.
•Do not mix naive and aware datetime.
What is the uv dependency manager and why is it popular?
•uv is a fast package/virtual environment manager (written in Rust).
•Quickly creates venv and installs packages.
•Convenient in CI.
•An alternative to pip/poetry for many commands.
•The choice of tool depends on the team's processes.
How to write REST API in Python (FastAPI briefly)?
•FastAPI uses type hints and pydantic.
•Describe endpoints with @app.get/post.
•Data models via BaseModel.
•Run: uvicorn app:app --reload.
•Documentation is generated automatically (Swagger).
How does Flask differ from FastAPI?
•Flask is minimalist, synchronous by default.
•FastAPI is modern, async-friendly.
•FastAPI generates OpenAPI from types.
•Flask requires more manual validation.
•The choice depends on team requirements and habits.
How to handle file uploads in web (general approach)?
•Limit upload size.
•Check MIME/type and extension (don't trust only extension).
•Generate a new filename.
•Save outside the public directory if needed.
•Log events and errors.
How to avoid memory leaks in Python applications?
•Don't keep global collections without control.
•Monitor caches and list growth.
•Close files/connections.
•Use tracemalloc/memory_profiler for profiling.
•Look for reference cycles and large objects.
What is weakref and when is it useful?
•weakref holds a weak reference, not preventing object deletion.
•Useful for caches and observers.
•When the object is deleted, weakref becomes empty.
•There are WeakKeyDictionary/WeakValueDictionary.
•Use carefully to avoid unexpected None.
How to speed up “slow” Python code without rewriting everything?
•Profile first to find hot spots.
•Replace algorithms/data structures.
•Use built-in functions (they are in C and faster).
•Consider NumPy/C packages.
•Only then think about Cython/extensions.
How to work with data pipelines via generators?
•Create generator functions that yield elements.
•Chain them together.
•Filtering/mapping is lazy.
•Saves memory.
•Good for processing large files/logs.
How to properly close resources on errors?
•Use with/context managers.
•For multiple resources: with a() as x, b() as y:.
•In try/finally, close what doesn't support with.
•Log exceptions and context.
•Don't leave connections/files open.
How to safely read and update a dictionary in multithreading?
•In CPython, individual dict operations are atomic, but multi-step logic is not.
•Use threading.Lock around critical sections.
•For queues, use queue.Queue.
•Avoid shared mutable state.
•For multiprocessing — Manager or process queues.
What are the “must know” tools for a Python developer?
•venv/pip (or uv/poetry) for environment management.
•ruff/black for style and linting.
•pytest for testing.
•mypy/pyright for type checking (optional).
•Git + CI for automated checks.