テーマ: python
-
Pythonのコマンドラインツールを設計する: argparse、main()、終了コード
インターフェースはコンソールスクリプトとして登録した`main(argv) -> int`関数にまとめ、argparseの`type`と`choices`で検証し、終了コードの慣習(0は成功、2は使用法エラー、1はその他の失敗、sysexitsのコードは文書化されている場合にのみ)に従い、結果はstdoutに、診断情報はstderrに出力し、SIGINTとbroken pipeを処理する。
-
中央値・パーセンタイル・比率のブートストラップ信頼区間
生の観測値を復元抽出で何度もリサンプリングし、各リサンプルについて統計量を計算し、得られた分布から区間を読み取る。これにより、教科書の公式が通用しない中央値・パーセンタイル・比率・差分についての不確実性を求められる。手法名、リサンプリング回数、サンプルサイズを報告し、小さなサンプルの極端なパーセンタイルについては信用しないこと。
-
Property-based testing with generated inputs
Instead of hand-picked examples, a property-based test states an invariant and lets a library generate many inputs, shrinking failures to minimal counterexamples; Hypothesis is the reference implementation for Python.
-
Context managers in Python: guaranteeing clean-up
The with statement runs __enter__ and __exit__ around a block so that files, locks and connections are released even when an exception occurs; contextlib.contextmanager turns a generator into one.
-
Docstrings that tools and readers can use
PEP 257 defines where docstrings go and how they are formatted; a consistent style (Google or NumPy) with a one-line summary, argument and return descriptions and raised exceptions makes them usable by readers, editors and documentation generators.
-
Floating-point numbers: why 0.1 + 0.2 is not 0.3
Binary floating point represents most decimal fractions approximately, so arithmetic accumulates rounding error; compare with tolerances, sum carefully, use integers or decimal types for money and counts, and print with enough digits to round-trip.
-
Loading YAML safely
Full YAML loaders can instantiate arbitrary objects from tagged nodes; always use a safe loader, pin the YAML version semantics, and validate the result against a schema before use.
-
When asyncio helps and when it does not
asyncio runs many I/O-bound tasks on one thread by suspending at await points; it does not speed up CPU-bound code, and blocking calls inside coroutines stall the whole loop.
-
Automated formatting and linting as a team contract
Delegating layout to a formatter and mechanical checks to a linter removes style debates from review; EditorConfig, PEP 8 and tools such as Ruff show how the contract can be encoded in the repository.
-
Protocol classes: structural typing for duck-typed Python
A typing.Protocol declares the methods and attributes a consumer needs; any object that has them satisfies the type without inheriting from it. Define protocols next to the code that depends on them, keep them minimal, and use runtime_checkable only where isinstance is really needed.
-
Finding a memory leak with tracemalloc snapshots
Start tracing early with PYTHONTRACEMALLOC or tracemalloc.start(nframe), take a snapshot after warm-up and another after N iterations, filter import noise, and read compare_to(..., 'lineno') for lines whose size grows proportionally to N; switch to 'traceback' grouping to see the callers.
-
Money and other exact quantities: use Decimal, not float
Binary floating point cannot represent most decimal fractions exactly, so sums of prices drift; the decimal module provides exact decimal arithmetic with explicit rounding, and integers in minor units are an alternative.
-
Choosing between threads, processes and asyncio for a Python workload
Classify the hot path first: waiting on I/O suits asyncio (many connections, async libraries) or a thread pool (few blocking calls); pure-Python CPU work needs processes or a free-threaded build; native code that releases the GIL can use threads. Bound every pool, choose the process start method explicitly and write the shutdown path.
-
Dataclasses for plain records
dataclasses generate __init__, __repr__ and equality from annotated fields; frozen dataclasses give immutable value objects, slots reduce memory, and field(default_factory=...) avoids shared mutable defaults.
-
At what workload does the free-threaded CPython build beat a process pool for a mixed I/O and CPU service?
Open question: the free-threaded build removes the GIL but adds single-threaded overhead and may fall back to the GIL when an unprepared extension is imported, while process pools pay for pickling and memory duplication; for which CPU-to-wait ratios, working sets and core counts does a thread pool on the free-threaded build deliver more throughput per core?
-
Attempting an exercise before reading its worked solution yields better one-month recall of a language feature than reading the solution first
Hypothesis: for an engineer learning a specific language feature, such as Python's match statement, working an exercise before seeing the worked solution leads to better delayed recall and transfer than studying the solution first and then working a similar exercise; a proposed within-person test with two features, two orders and a one-month delayed test, with no result claimed.
-
Iterables versus iterators: the protocol behind for loops
An iterable returns a fresh iterator from __iter__; an iterator returns items from __next__, raises StopIteration when done and must keep raising it. A for loop calls iter once and next repeatedly, so an exhausted iterator passed to a second loop looks empty. Annotate Iterable for one pass, Sequence or Collection when several are needed.
-
Testing code that depends on time and randomness
Inject a clock and a random source instead of calling time.time() or random directly; tests then pass fixed values, and the code stays deterministic and reproducible.
-
Deserialisation of untrusted data: pickle and Java serialization
Native object serialisation formats instruct the receiver to construct arbitrary objects, and constructing objects runs code; Python's pickle documentation says outright that the module is not secure. Never deserialise these formats from untrusted input; where a legacy interface forces it, restrict the classes the stream may name and sign the payload.
-
Running external commands safely from Python
Use subprocess.run with an argument list and shell=False, set timeouts, capture output explicitly, check return codes and never build a command line from untrusted strings.
機械可読: JSON