Tổng hợp 83 câu hỏi phỏng vấn Python kèm đáp án chi tiết, song ngữ Việt–Anh — sắp xếp từ cơ bản đến nâng cao. Ôn luyện miễn phí, tự động lưu tiến độ.
Python dùng hai cơ chế: (1) Reference counting — mỗi object đếm số tham chiếu, về 0 thì giải phóng ngay (2) Garbage Collector (module gc) — phát hiện và thu hồi circular references mà reference counting không xử lý được (3) Memory Pool (PyMalloc)…
Mutable types là kiểu dữ liệu có thể thay đổi giá trị tại chỗ sau khi tạo; immutable types là kiểu không thể thay đổi sau khi tạo, mọi thao tác "sửa" thực chất tạo ra object mới. Ví dụ: list, dict, set, bytearray là…
Dùng list khi cần ordered collection có thể thay đổi. Dùng tuple cho dữ liệu bất biến, làm dict key, trả về nhiều giá trị từ function. Dùng set để loại bỏ duplicate và kiểm tra membership O(1). Dùng dict cho key-value lookup O(1). Lưu…
Generator là function dùng yield trả về iterator — tính giá trị lazily, từng phần tử khi được yêu cầu. Tiết kiệm bộ nhớ so với list vì không nạp toàn bộ dữ liệu vào RAM. Dùng khi: xử lý file lớn, streaming data, infinite…
Decorator là higher-order function nhận một function và trả về function mới với hành vi bổ sung — cú pháp @decorator là syntactic sugar. Dùng @functools.wraps để giữ metadata của function gốc. Lưu ý: Không dùng @functools.wraps → mất name, doc của function gốc.
Context manager quản lý tài nguyên tự động qua enter và exit. with đảm bảo cleanup chạy dù có exception hay không.
Closure là nested function "ghi nhớ" biến từ enclosing scope dù outer function đã kết thúc. Lambda là anonymous function một dòng — thường dùng cho logic đơn giản tức thời. Lưu ý: Closure trong vòng lặp — mọi closure đều tham chiếu cùng biến…
Shallow copy tạo object mới nhưng elements bên trong vẫn tham chiếu cùng objects gốc — thay đổi mutable elements sẽ ảnh hưởng cả hai bản. Deep copy tạo hoàn toàn độc lập, copy đệ quy toàn bộ. Dùng copy.copy() cho shallow và copy.deepcopy() cho…
(1) try — khối code có thể raise exception (2) except — xử lý exception (3) else — chạy nếu KHÔNG có exception trong try (4) finally — LUÔN chạy, dù có exception hay không — dùng để cleanup.
== so sánh giá trị (gọi eq). is so sánh identity — hai biến có trỏ đến cùng object trong memory không. Lưu ý: CPython cache integers nhỏ (-5 đến 256) và string interning — x = 256; y = 256; x is y có…
lrucache (Least Recently Used cache) là decorator memoize kết quả của function — lần sau gọi cùng args sẽ trả về cache thay vì tính lại. Function phải có hashable arguments. Dùng cho: pure functions với expensive computation, recursive algorithms.
Dùng f-string (Python 3.6+) — nhanh nhất, dễ đọc nhất, hỗ trợ expression trực tiếp. f"Name: {name!r}, Score: {score:.2f}". .format() khi cần template string tái sử dụng. % formatting là cũ, không nên dùng trong code mới. Ví dụ: f"2+2={2+2}" in ra "2+2=4" — expression…
(1) Encapsulation — đóng gói data + methods, dùng (protected) và (name mangling) (2) Inheritance — class Child(Parent), hỗ trợ multiple inheritance, dùng super() (3) Polymorphism — cùng method tên, hành vi khác nhau tuỳ class; duck typing (4) Abstraction — ẩn implementation qua ABC…
Instance method nhận self — có access vào instance và class. @classmethod nhận cls — access class, thường dùng làm factory. @staticmethod không nhận self hay cls — utility function liên quan đến class.
@property cho phép define getter/setter/deleter cho attribute, truy cập như attribute thường nhưng có validation logic.
Dùng ABC + @abstractmethod để tạo abstract class. Class con bắt buộc implement tất cả abstract methods, nếu không sẽ không instantiate được.
@dataclass tự động generate init, repr, eq — giảm boilerplate đáng kể. Ưu điểm so với namedtuple: có default values, methods, mutable (nếu không frozen).
(1) repr — developer repr (eval-safe), str — user-friendly string (2) len, getitem, setitem — sequence protocol (3) enter/exit — context manager (4) eq, lt, hash — comparison và hashability (5) call — cho phép gọi instance như function (6) iter/next — iterator protocol. Lưu…
GIL (Global Interpreter Lock) là mutex trong CPython đảm bảo chỉ một thread thực thi Python bytecode tại một thời điểm. Ảnh hưởng: (1) I/O-bound tasks — threading vẫn hiệu quả vì GIL được release khi chờ I/O (network, file, DB) (2) CPU-bound tasks —…
Dùng asyncio cho I/O-bound với nhiều concurrent operations (web APIs, DB queries) — single thread, cooperative concurrency, overhead thấp nhất. Dùng threading cho I/O-bound với thư viện blocking không hỗ trợ async. Dùng multiprocessing cho CPU-bound (ML training, image processing, data transformation) — bypass GIL,…
Event loop quản lý coroutines. Khi coroutine gặp await, nó tạm dừng và nhường control để event loop chạy coroutine khác. Đây là cooperative concurrency — không phải parallelism thực sự.
FastAPI là modern Python web framework dựa trên Starlette (ASGI) + Pydantic. Ưu điểm: (1) Async native — ~20K RPS, Flask/Django ~4-5K RPS (2) Auto OpenAPI docs — Swagger UI + ReDoc tự động từ type hints (3) Type-based validation — Pydantic validate request/response (4)…
FastAPI dùng Pydantic model để tự động validate request body, query params, path params. Trả về 422 Unprocessable Entity nếu invalid.
Middleware chạy trước và sau mỗi request. Dùng @app.middleware("http") cho custom middleware. CORS, GZip, TrustedHost — dùng built-in middlewares. Lưu ý: Middleware exception handler không bắt HTTP exceptions từ path operations — dùng exceptionhandler thay.
JWT auth gồm bốn bước: (1) Hash password với bcrypt (2) Tạo JWT token khi login (3) Verify token trong dependency (4) Protect routes với Depends(getcurrentuser). Dùng PyJWT (không phải python-jose — đã có CVEs và ít được maintain).
Background Tasks: zero config, in-process, chạy sau khi response trả về client. Dùng cho: email xác nhận đơn giản, logging, non-critical async work. Celery: cần Redis/RabbitMQ broker, distributed workers, retry logic, monitoring với Flower. Dùng cho: payment processing, report generation, critical tasks cần retry. Lưu…
N+1 problem: 1 query lấy N records, rồi N queries nữa để lấy related data. Giải quyết bằng eager loading.
SQLAlchemy 2.0 async dùng createasyncengine, asyncsessionmaker, và ORM style mới với Mapped/mappedcolumn — fully type-safe.
Dùng TestClient cho synchronous-style test của async endpoints. Override dependencies để isolate tests.
Fixture scope xác định fixture được tạo và destroy khi nào: function (default) — mỗi test; class — mỗi test class; module — mỗi module; session — toàn bộ test session.
Dùng mocker fixture từ pytest-mock để mock functions và verify calls.
pydantic-settings tự động đọc env vars và validate types. Hỗ trợ .env file.
Type hints (PEP 484, Python 3.5+) không enforce lúc runtime nhưng mang lại: (1) IDE autocompletion và refactoring tốt hơn (2) Static analysis với mypy/pyright bắt lỗi trước runtime (3) Documentation tự động — code tự giải thích (4) Pydantic/FastAPI dùng type hints để validation…
args cho phép nhận bất kỳ số positional arguments — nhóm thành tuple. kwargs nhận bất kỳ số keyword arguments — nhóm thành dict. Thứ tự params: def fn(pos, /, normal, args, kwonly, kwargs). Lưu ý: args và kwargs không giữ type information — dùng…
Các built-ins quan trọng để xử lý collections hiệu quả: Lưu ý: map và filter trả về lazy iterators — cần list() để materialize. Modern Python ưu tiên list comprehension hơn map/filter vì dễ đọc hơn.
Walrus operator (PEP 572, Python 3.8+) cho phép assign và return giá trị trong cùng một expression — giảm lặp code. Lưu ý: không lạm dụng — walrus trong nested expression phức tạp làm code khó đọc hơn. Dùng khi thực sự tránh được duplicate…
Python type hints làm được nhiều hơn chỉ int, str cơ bản: Python 3.10+: dùng X Y thay vì Union[X, Y], X None thay vì Optional[X].
Iterator: bất kỳ object nào implement iter() và next(). Generator: function dùng yield — tự động implement iterator protocol, lazy, stateful. Generator với send() — coroutine-lite, nhận value từ caller:
FastAPI 0.100+ dùng Pydantic v2 mặc định — nhanh hơn 5-50x nhờ Rust core. Thay đổi chính:
FastAPI chạy trên Starlette (ASGI), hỗ trợ cả sync và async endpoints: async def: dùng khi endpoint thực hiện I/O async (database queries async, HTTP calls async): def (sync): khi dùng blocking operations không thể async. FastAPI tự động chạy sync endpoint trong ThreadPoolExecutor để…
@pytest.mark.parametrize cho phép chạy cùng test với nhiều input/output khác nhau:
Mock là base class; MagicMock mở rộng với magic method support (len, iter, enter...); AsyncMock (Python 3.8+) bắt buộc cho coroutine — dùng sai type thì assertawaitedonce sẽ silently pass dù không được await.
Kết hợp slots với @dataclass để có cả type safety và memory efficiency: Dùng @dataclass(slots=True) khi có hàng triệu instances — tiết kiệm ~30-60% memory.
Python dùng cơ chế thường gọi là pass-by-object-reference (hay "call by assignment"): mỗi tham số được gán vào đúng object mà caller truyền vào — không copy object, cũng không phải pass-by-reference kiểu C++. Hệ quả tuỳ object là mutable hay không: - Mutable (list,…
LEGB là thứ tự Python tra một tên: Local (trong hàm hiện tại) → Enclosing (hàm bao ngoài) → Global (module) → Built-in. Tìm thấy ở tầng nào thì dừng ở đó. Mặc định, gán một tên bên trong hàm sẽ tạo biến Local —…
Cú pháp gọn để dựng collection mới bằng transform + filter trong một biểu thức: Dùng khi map/filter một iterable — ngắn và thường nhanh hơn vòng for + append. Không nên dùng khi logic nhiều nhánh, lồng sâu, hay có side-effect → vòng for…
Mỗi module có biến name. Khi bạn chạy file trực tiếp (python foo.py), name của file đó bằng "main". Khi file bị import từ nơi khác, name bằng tên module ("foo"). Đặt code chạy-thử / entry-point CLI trong khối này để nó chỉ chạy khi…
- list.sort(): sắp xếp tại chỗ, trả về None, chỉ dùng cho list. - sorted(iterable): trả về list mới, nhận mọi iterable (kể cả tuple, dict keys...). Cả hai đều nhận key= (hàm rút khoá so sánh) và reverse=. Cả hai dùng Timsort và ổn…
pickle serialize một object Python thành byte stream và deserialize ngược lại (dựng lại object). Khác JSON: giữ được cấu trúc Python phức tạp (object tuỳ biến, tham chiếu vòng) nhưng chỉ Python đọc được và không cross-language. Nguy hiểm: quá trình unpickle có thể…
Không phải switch so-sánh-giá-trị đơn thuần. match so khớp cấu trúc: nó có thể destructure sequence/mapping/object, bắt biến từ bên trong, và thêm điều kiện if (guard). Trúng nhánh nào thì gán luôn các phần con vào biến. Khác biệt cần nhớ: - Không fall-through…
Python không có access modifier thật (private/protected). Thay vào đó là quy ước và một cơ chế đổi tên: - name (1 gạch đầu): quy ước "nội bộ, đừng đụng từ ngoài" — thuần convention, không ràng buộc, vẫn truy cập được. - name (2…
Giá trị mặc định chỉ được tính đúng một lần, tại thời điểm câu lệnh def chạy — không phải mỗi lần gọi hàm. List đó được gắn vào chính object hàm (add.defaults), nên mọi lần gọi không truyền bucket đều dùng chung một list.…
Kết quả là [[1, 0, 0], [1, 0, 0]] — cả hai hàng cùng đổi. Toán tử trên list không sao chép phần tử, nó chỉ nhân bản tham chiếu: hai "hàng" thực chất là một object. Riêng [0] 3 vẫn đúng như mong đợi…
List comprehension dựng sẵn toàn bộ list trong RAM; generator expression trả về một lazy iterator, chỉ tính từng phần tử khi được duyệt. Khác biệt thực tế: - Bộ nhớ: genexp giữ một phần tử tại một thời điểm, hợp với file lớn, cursor…
Vì CPython cấp phát sẵn và dùng chung các object số nguyên nhỏ trong khoảng -5 đến 256. Với giá trị nằm ngoài khoảng đó, mỗi lần tạo là một object mới nên is (so sánh identity) trả về False, dù == (so sánh giá…
Decorator có tham số cần ba tầng hàm: hàm ngoài nhận tham số cấu hình và trả về decorator, decorator nhận function và trả về wrapper. @retry(times=3) được đọc là: gọi retry(times=3) trước, lấy kết quả rồi mới áp lên hàm. functools.wraps để làm gì:…
Về giá trị sinh ra thì giống nhau, nhưng yield from uỷ quyền hẳn cho sub-generator chứ không chỉ chuyển tiếp giá trị. Ba điểm khác biệt: 1. Chuyển tiếp hai chiều: send(), throw(), close() từ caller đi thẳng xuống sub-generator. Vòng for thủ công…
Hai cách: viết class có enter/exit, hoặc dùng @contextlib.contextmanager với một generator yield đúng một lần. Phần dọn dẹp phải nằm trong finally, nếu không thì block có exception sẽ không dọn. exit trả về True: exception bị nuốt hoàn toàn — chương trình chạy…
Ném TypeError: unhashable type. Python 3 tự đặt hash = None cho class nào override eq mà không khai báo hash. Lý do là ràng buộc giữa hash và equality: - a == b thì bắt buộc hash(a) == hash(b). - Hash phải không đổi…
Ba thứ giải quyết ba nhu cầu khác nhau, nhìn theo ranh giới dữ liệu: NamedTuple — bản ghi bất biến, nhẹ, có thể unpack và dùng làm key của dict. Hợp cho giá trị trả về nhiều thành phần, cấu hình chỉ đọc, toạ…
Không. Runtime của Python bỏ qua annotation: def f(n: int) vẫn nhận "abc" và chạy bình thường, không có lỗi nào được ném ra. Type hint phục vụ công cụ phân tích tĩnh (mypy, pyright, IDE) và thư viện đọc metadata (pydantic, FastAPI, dataclasses, SQLAlchemy…
Vì closure trong Python giữ tham chiếu tới biến, không giữ giá trị tại thời điểm tạo (late binding). Cả ba lambda cùng trỏ tới một biến i; đến lúc gọi thì vòng lặp đã kết thúc và i đang là 2. Ba cách sửa:…
asyncio.gather khởi chạy tất cả coroutine cùng lúc. Với 200 lời gọi, phía bên kia dễ trả 429, kết nối bị nghẽn, và nếu vài request đồng thời cùng làm vậy thì tiến trình mở hàng nghìn socket. Cách chuẩn là giới hạn bằng asyncio.Semaphore…