10 câu hỏi có thể gặp khi phỏng vấn
Chọn theo kỹ năng và cấp của tin (Python, AI / Machine Learning, C/C++ & Embedded). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.
01Shallow copy và deep copy khác nhau thế nào? Phép gán
b = acó tạo bản sao không?Python · JuniorGợi ý trả lời
Ôn thêm câu hỏi Python →b = akhông sao chép gì: hai tên cùng trỏ đến một object. Sửa quabthìacũng đổi.- Shallow copy (
a.copy(),list(a),a[:],copy.copy(a)): tạo container mới nhưng các phần tử bên trong vẫn là object cũ. - Deep copy (
copy.deepcopy(a)): sao chép đệ quy toàn bộ cấu trúc.
a = [[1, 2], [3]] b = a.copy() b[0].append(99) # a cũng thành [[1, 2, 99], [3]]Hay sai: tạo ma trận bằng
[[0] * 3] * 3. Ba hàng là cùng một list, sửa một ô thì cả cột đổi theo. Viết đúng:[[0] * 3 for _ in range(3)].- Shallow copy (
02Generator và
yieldlà gì? Khác gì với list comprehension?Python · JuniorGợi ý trả lời
Ôn thêm câu hỏi Python →Generator sinh giá trị lười (lazy): mỗi lần được hỏi mới tính phần tử tiếp theo, rồi tạm dừng tại
yield. Nhờ vậy nó không phải giữ toàn bộ dữ liệu trong bộ nhớ.def read_lines(path): with open(path) as f: for line in f: yield line.rstrip() total = sum(len(l) for l in read_lines("big.log"))- List comprehension
[x * 2 for x in data]tạo cả list ngay. Generator expression(x * 2 for x in data)thì không. - Hợp với file lớn, dữ liệu stream, phân trang API, pipeline xử lý nhiều bước.
Hay sai: duyệt một generator hai lần. Lần thứ hai không có gì vì nó đã cạn; cần duyệt lại thì tạo generator mới hoặc chuyển thành list.
- List comprehension
03Decorator hoạt động thế nào? Hãy viết một decorator đo thời gian chạy của hàm.Python
Gợi ý trả lời
Ôn thêm câu hỏi Python →Decorator là hàm nhận một hàm và trả về hàm mới bọc quanh nó.
@timerchỉ là cú pháp ngắn củafunc = timer(func).import functools, time def timer(func): @functools.wraps(func) def wrapper(*args, **kwargs): start = time.perf_counter() try: return func(*args, **kwargs) finally: print(func.__name__, time.perf_counter() - start) return wrapperfunctools.wrapsgiữ lại__name__, docstring của hàm gốc, quan trọng cho log và debug.- Decorator có tham số (ví dụ
@retry(times=3)) cần thêm một lớp hàm bên ngoài. - Ví dụ thực tế:
@app.getcủa FastAPI,@login_requiredcủa Django,@functools.lru_cache.
Hay sai: decorator viết kiểu đồng bộ bọc hàm
async def. Kết quả là đo thời gian tạo coroutine chứ không phải thời gian chạy.04Giải thích ngắn gọn cơ chế attention và vì sao Transformer thay thế RNN trong NLP.AI / Machine Learning · Junior
Gợi ý trả lời
Ôn thêm câu hỏi AI / Machine Learning →Attention cho mỗi token "nhìn" tất cả token khác và tính trọng số mức liên quan, nhờ đó nắm được phụ thuộc xa trong câu. Mỗi token tạo ra query, key, value; trọng số là softmax của tích query với key (chia cho căn bậc hai số chiều), rồi lấy tổng có trọng số của value.
Transformer thắng RNN vì:
- Xử lý song song cả chuỗi khi train, tận dụng GPU tốt; RNN phải đi tuần tự.
- Ít gặp vấn đề mất thông tin ở chuỗi dài.
- Mở rộng quy mô tốt, là nền của các LLM hiện nay.
Đánh đổi: chi phí attention tăng theo bình phương độ dài chuỗi, nên ngữ cảnh dài tốn bộ nhớ và tính toán.
05RAG là gì? Mô tả các bước xây dựng một hệ thống hỏi đáp trên tài liệu nội bộ.AI / Machine Learning
Gợi ý trả lời
Ôn thêm câu hỏi AI / Machine Learning →RAG (Retrieval-Augmented Generation) tìm các đoạn tài liệu liên quan rồi đưa vào prompt để LLM trả lời dựa trên đó, giúp dùng dữ liệu riêng, cập nhật mà không cần train lại.
Các bước:
- Nạp và làm sạch tài liệu (PDF, wiki), giữ metadata và quyền truy cập.
- Chunking theo cấu trúc (tiêu đề, đoạn), có chồng lấp hợp lý.
- Embedding và lưu vào vector DB.
- Truy xuất: kết hợp tìm vector và từ khoá (hybrid), rồi rerank.
- Sinh câu trả lời với prompt yêu cầu bám nguồn và trích dẫn, trả lời "không biết" khi thiếu thông tin.
Hay sai: bỏ qua phân quyền, để người dùng nhận được nội dung từ tài liệu họ không được xem.
06RAII là gì? So sánh unique_ptr, shared_ptr và weak_ptr.C/C++ & Embedded
Gợi ý trả lời
Ôn thêm câu hỏi C/C++ & Embedded →RAII (Resource Acquisition Is Initialization): gắn tài nguyên vào vòng đời một object; constructor lấy tài nguyên, destructor tự giải phóng. Nhờ vậy không rò rỉ kể cả khi có exception hoặc return sớm.
unique_ptr: sở hữu duy nhất, chỉ move được, không tốn thêm chi phí so với con trỏ thường. Nên là lựa chọn mặc định.shared_ptr: sở hữu chung bằng bộ đếm tham chiếu (cập nhật atomic), giải phóng khi bộ đếm về 0.weak_ptr: quan sát mộtshared_ptrmà không tăng bộ đếm, dùng phá vòng tham chiếu (vd. con trỏ ngược từ con về cha).
auto dev = std::make_unique<Device>("/dev/i2c-1");Hay sai: dùng
shared_ptrkhắp nơi "cho an toàn", làm mờ quyền sở hữu và tốn chi phí atomic.07GIL là gì? Vậy khi nào dùng threading, multiprocessing hay asyncio?Python
Gợi ý trả lời
Ôn thêm câu hỏi Python →GIL (Global Interpreter Lock) trong CPython chỉ cho một thread chạy bytecode Python tại một thời điểm. Vì vậy threading không tăng tốc tác vụ nặng CPU, nhưng vẫn hữu ích cho I/O vì GIL được nhả ra khi chờ mạng, đĩa.
- I/O, số lượng vừa phải, thư viện blocking:
threadinghoặcThreadPoolExecutor. - I/O rất nhiều kết nối đồng thời:
asynciovới thư viện async (httpx,asyncpg). - Nặng CPU:
multiprocessinghoặcProcessPoolExecutor, hoặc dùng thư viện viết bằng C như NumPy (nhả GIL khi tính toán).
Từ Python 3.13 có bản build free-threaded (không GIL) tuỳ chọn, nhưng chưa phải mặc định và còn phụ thuộc thư viện hỗ trợ.
Người phỏng vấn muốn nghe: bạn phân biệt được bài toán I/O-bound và CPU-bound trước khi chọn công cụ.
- I/O, số lượng vừa phải, thư viện blocking:
08Trong Django ORM, lỗi N+1 query là gì? Phân biệt
select_relatedvàprefetch_related.PythonGợi ý trả lời
Ôn thêm câu hỏi Python →N+1 là khi lấy danh sách bằng 1 query, rồi mỗi phần tử truy cập quan hệ lại sinh thêm 1 query. Ví dụ duyệt 50 bài viết và in
post.author.namesẽ thành 51 query.select_related: dùng SQLJOIN, cho quan hệ trỏ tới một object (ForeignKey,OneToOne).prefetch_related: chạy query riêng rồi ghép trong Python, cho quan hệ nhiều (ManyToMany, reverseForeignKey).
posts = (Post.objects .select_related("author") .prefetch_related("tags"))Phát hiện bằng Django Debug Toolbar, hoặc
assertNumQueriestrong test.Hay sai: gọi
.filter()trên quan hệ đã prefetch bên trong vòng lặp. Lệnh đó tạo query mới và bỏ qua dữ liệu prefetch; dùngPrefetch(..., queryset=...)để lọc ngay từ đầu.09Context manager (
with) là gì? Làm sao tự viết một context manager?PythonGợi ý trả lời
Ôn thêm câu hỏi Python →Context manager đảm bảo việc "mở" và "dọn dẹp" luôn đi cùng nhau, kể cả khi có exception: đóng file, trả connection, nhả lock, rollback transaction.
Cách nhanh nhất là dùng
contextlib.contextmanager:from contextlib import contextmanager @contextmanager def db_transaction(conn): try: yield conn conn.commit() except Exception: conn.rollback() raise- Cách đầy đủ: viết class có
__enter__và__exit__(self, exc_type, exc, tb). Nếu__exit__trả vềTruethì exception bị nuốt. - Bản async:
async with,__aenter__/__aexit__hoặcasynccontextmanager.
Hay sai: quên
raiselại exception trong khốiexcept, khiến lỗi bị che mất và code phía sau tưởng mọi thứ đã thành công.- Cách đầy đủ: viết class có
10Kể về một thất bại hoặc sai lầm của bạn và bài học rút ra.Câu hỏi hành vi & văn hoá
Gợi ý trả lời
Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →Chọn sai lầm thật, có hậu quả vừa phải, nhận trách nhiệm rõ ràng, và nhấn mạnh việc bạn đã thay đổi sau đó.
Cấu trúc: chuyện gì xảy ra, phần lỗi của bạn, bạn khắc phục ngay thế nào, bài học và thay đổi lâu dài.
Câu mẫu: "Có lần em deploy một thay đổi cấu hình lên production vào chiều thứ Sáu mà không kiểm tra kỹ trên staging, làm một tính năng lỗi khoảng một giờ. Em báo ngay cho lead, rollback và viết báo cáo sự cố. Sau đó em đề xuất checklist trước deploy và quy ước hạn chế deploy cuối tuần; team áp dụng tới giờ."
Hay sai: kể một "thất bại" thực ra là khoe, đổ lỗi cho người khác, hoặc nói mình chưa từng thất bại.
Bạn đã phỏng vấn ở MB Bank?
Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.
Chia sẻ kinh nghiệm phỏng vấn