Python常見100個經(jīng)典面試問題總結(jié)(從入門到進階)
說明:本文整理了 Python 面試中常見的 100 個經(jīng)典問題,覆蓋基礎(chǔ)語法、數(shù)據(jù)結(jié)構(gòu)、函數(shù)、裝飾器、異常、文件、迭代器、生成器、面向?qū)ο?、工程化、并發(fā)、標準庫、性能優(yōu)化等內(nèi)容。每個問題都盡量配有示例代碼和真實輸出,方便讀者邊看邊練。
前言
Python 面試并不是單純考“會不會寫語法”,而是考你是否真正理解對象、數(shù)據(jù)結(jié)構(gòu)、函數(shù)、異常、面向?qū)ο?、裝飾器、生成器、并發(fā)、性能、工程化和常見坑點。
很多候選人能寫出代碼,但一問:
- 為什么列表不能作為字典 key?
- 裝飾器什么時候執(zhí)行?
is和==有什么區(qū)別?- 線程、進程、協(xié)程怎么選?
- GIL 到底影響什么?
- 淺拷貝和深拷貝有什么區(qū)別?
就容易卡住。
本文整理 100 個 Python 高頻面試問題,每個問題都配一個小例子,方便你邊看邊練。建議閱讀方式是:先看問題,自己想 30 秒,再看答案和代碼。
一、Python 基礎(chǔ)語法與對象模型
1. Python 是解釋型語言嗎?
是。Python 通常由解釋器執(zhí)行源碼或字節(jié)碼,不需要像 C/C++ 那樣提前編譯成機器碼。
但這不代表 Python 沒有編譯過程。.py 文件通常會先被編譯成字節(jié)碼,再由 Python 虛擬機執(zhí)行。
print("hello python")
輸出:
hello python
2. Python 中“一切皆對象”是什么意思?
變量、函數(shù)、類、模塊、數(shù)字、字符串都是對象。對象通常有三個重要特征:
- 身份:可以用
id()查看 - 類型:可以用
type()查看 - 值:對象保存的數(shù)據(jù)
x = 100 print(type(x)) print(id(x))
輸出示例:
<class 'int'> 140735568356104
3.is和==有什么區(qū)別?
== 比較的是兩個對象的值是否相等。
is 比較的是兩個變量是否引用同一個對象。
a = [1, 2] b = [1, 2] print(a == b) print(a is b)
輸出:
True False
解釋:
雖然 a 和 b 的值一樣,但它們是兩個不同的列表對象。
4. Python 中可變對象和不可變對象有什么區(qū)別?
可變對象的值可以原地修改,例如:
listdictset
不可變對象創(chuàng)建后不能直接修改,例如:
intfloatstrtuple
a = [1, 2] a.append(3) print(a) s = "ab" s += "c" print(s)
輸出:
[1, 2, 3] abc
注意:字符串看起來被修改了,其實是創(chuàng)建了一個新的字符串對象。
5. 為什么列表不能作為字典 key?
因為列表是可變對象,哈希值不穩(wěn)定,不能作為字典 key。
字典 key 必須是可哈希對象。常見可哈希對象包括:
- 字符串
- 數(shù)字
- 元組
- 布爾值
d = {}
# d[[1, 2]] = "value" # TypeError: unhashable type: 'list'
d[(1, 2)] = "value"
print(d)
輸出:
{(1, 2): 'value'}
6.None應(yīng)該如何判斷?
推薦使用 is None,不要使用 == None。
value = None
if value is None:
print("value is None")
輸出:
value is None
原因是 None 是一個單例對象,使用 is 更準確。
7. Python 的布爾值判斷規(guī)則是什么?
以下值通常會被判斷為假:
NoneFalse0""[]{}set()tuple()
values = ["", [], {}, 0, None, "python"]
for v in values:
print(bool(v))
輸出:
False False False False False True
8.and和or返回的一定是布爾值嗎?
不一定。它們返回的是參與運算的對象本身。
print(0 or "default")
print("python" and "ok")
輸出:
default ok
這個特性經(jīng)常用于默認值處理。
9. Python 中變量需要聲明類型嗎?
不需要。Python 是動態(tài)類型語言,變量名只是對象的引用。
x = 1 x = "hello" print(x)
輸出:
hello
10. Python 的類型注解會強制校驗類型嗎?
不會。類型注解主要用于:
- 提高代碼可讀性
- 輔助 IDE 提示
- 配合 mypy、pyright 等工具做靜態(tài)檢查
Python 運行時默認不會強制校驗類型。
def add(a: int, b: int) -> int:
return a + b
print(add("1", "2"))
輸出:
12
雖然參數(shù)標注為 int,但運行時傳入字符串也能執(zhí)行。
二、字符串、列表、元組、字典、集合
11. 字符串如何反轉(zhuǎn)?
s = "python" print(s[::-1])
輸出:
nohtyp
12. 字符串拼接為什么推薦join?
循環(huán)中頻繁使用 + 拼接字符串,會產(chǎn)生多個中間字符串對象。
大量字符串拼接時,推薦使用 join()。
words = ["Python", "is", "good"]
print(" ".join(words))
輸出:
Python is good
13.split()和strip()有什么區(qū)別?
split() 用于分割字符串。
strip() 用于去除字符串首尾空白或指定字符。
s = " a,b,c "
print(s.strip())
print(s.strip().split(","))
輸出:
a,b,c ['a', 'b', 'c']
14. 列表推導(dǎo)式是什么?
列表推導(dǎo)式可以用簡潔語法生成列表。
nums = [x * x for x in range(5)] print(nums)
輸出:
[0, 1, 4, 9, 16]
15. 列表推導(dǎo)式中如何加條件?
nums = [x for x in range(10) if x % 2 == 0] print(nums)
輸出:
[0, 2, 4, 6, 8]
16.append()和extend()有什么區(qū)別?
append() 添加一個元素。
extend() 展開可迭代對象后逐個添加。
a = [1, 2] a.append([3, 4]) print(a) b = [1, 2] b.extend([3, 4]) print(b)
輸出:
[1, 2, [3, 4]] [1, 2, 3, 4]
17.list.sort()和sorted()有什么區(qū)別?
list.sort() 是原地排序,返回 None。
sorted() 會返回一個新的列表。
a = [3, 1, 2] b = sorted(a) print(a) print(b) a.sort() print(a)
輸出:
[3, 1, 2] [1, 2, 3] [1, 2, 3]
18. 元組一定不可變嗎?
元組本身不可變,但如果元組中包含可變對象,可變對象內(nèi)部仍然可以修改。
t = ([1, 2], "a") t[0].append(3) print(t)
輸出:
([1, 2, 3], 'a')
19. 字典如何安全獲取不存在的 key?
使用 get()。
user = {"name": "vito"}
print(user.get("age"))
print(user.get("age", 18))
輸出:
None 18
20. 字典如何遍歷 key 和 value?
user = {"name": "vito", "age": 18}
for k, v in user.items():
print(k, v)
輸出:
name vito age 18
21. 字典推導(dǎo)式是什么?
d = {x: x * x for x in range(3)}
print(d)
輸出:
{0: 0, 1: 1, 2: 4}
22. 集合有什么特點?
集合的特點:
- 元素唯一
- 無序
- 適合去重
- 適合成員判斷
nums = [1, 2, 2, 3] print(set(nums))
輸出:
{1, 2, 3}
23. 集合常見運算有哪些?
a = {1, 2, 3}
b = {3, 4}
print(a | b)
print(a & b)
print(a - b)
輸出:
{1, 2, 3, 4}
{3}
{1, 2}
24. 如何統(tǒng)計列表中元素出現(xiàn)次數(shù)?
from collections import Counter items = ["a", "b", "a", "c", "b", "a"] print(Counter(items))
輸出:
Counter({'a': 3, 'b': 2, 'c': 1})
25. 如何取列表中出現(xiàn)最多的元素?
from collections import Counter items = ["a", "b", "a", "c", "b", "a"] print(Counter(items).most_common(1))
輸出:
[('a', 3)]
三、函數(shù)與參數(shù)
26. Python 函數(shù)參數(shù)有哪些類型?
常見參數(shù)類型包括:
- 位置參數(shù)
- 默認參數(shù)
- 關(guān)鍵字參數(shù)
- 可變位置參數(shù)
*args - 可變關(guān)鍵字參數(shù)
**kwargs
def demo(a, b=2, *args, **kwargs):
print(a, b, args, kwargs)
demo(1, 3, 4, 5, name="vito")
輸出:
1 3 (4, 5) {'name': 'vito'}
27. 默認參數(shù)有什么坑?
默認參數(shù)只在函數(shù)定義時創(chuàng)建一次。
如果默認參數(shù)是列表、字典等可變對象,可能導(dǎo)致數(shù)據(jù)被多次調(diào)用共享。
def add_item(item, box=[]):
box.append(item)
return box
print(add_item("a"))
print(add_item("b"))
輸出:
['a'] ['a', 'b']
推薦寫法:
def add_item(item, box=None):
if box is None:
box = []
box.append(item)
return box
print(add_item("a"))
print(add_item("b"))
輸出:
['a'] ['b']
28.*args是什么?
*args 用于接收多余的位置參數(shù),類型是元組。
def total(*args):
return sum(args)
print(total(1, 2, 3))
輸出:
6
29.**kwargs是什么?
**kwargs 用于接收多余的關(guān)鍵字參數(shù),類型是字典。
def show(**kwargs):
print(kwargs)
show(name="vito", age=18)
輸出:
{'name': 'vito', 'age': 18}
30. Python 函數(shù)是對象嗎?
是。函數(shù)可以賦值給變量,也可以作為參數(shù)傳遞。
def hello():
return "hello"
f = hello
print(f())
輸出:
hello
31. 什么是高階函數(shù)?
接收函數(shù)作為參數(shù),或者返回函數(shù)的函數(shù),稱為高階函數(shù)。
def apply(func, value):
return func(value)
print(apply(abs, -10))
輸出:
10
32.lambda表達式是什么?
lambda 是匿名函數(shù),適合簡單邏輯。
add = lambda a, b: a + b print(add(1, 2))
輸出:
3
實際項目中,不建議寫過于復(fù)雜的 lambda。
33.map()怎么用?
map() 會對可迭代對象中的每個元素應(yīng)用函數(shù)。
nums = [1, 2, 3] print(list(map(lambda x: x * 2, nums)))
輸出:
[2, 4, 6]
34.filter()怎么用?
filter() 用于過濾元素。
nums = [1, 2, 3, 4] print(list(filter(lambda x: x % 2 == 0, nums)))
輸出:
[2, 4]
35.zip()怎么用?
zip() 會把多個可迭代對象按位置打包。
names = ["a", "b"] scores = [90, 80] print(list(zip(names, scores)))
輸出:
[('a', 90), ('b', 80)]
四、作用域、閉包、裝飾器
36. Python 作用域查找規(guī)則是什么?
Python 變量查找遵循 LEGB 規(guī)則:
- Local:局部作用域
- Enclosing:外層函數(shù)作用域
- Global:全局作用域
- Built-in:內(nèi)置作用域
x = "global"
def outer():
x = "outer"
def inner():
x = "inner"
print(x)
inner()
outer()
輸出:
inner
37.global有什么作用?
global 用于在函數(shù)內(nèi)部聲明并修改全局變量。
count = 0
def inc():
global count
count += 1
inc()
print(count)
輸出:
1
38.nonlocal有什么作用?
nonlocal 用于修改外層函數(shù)作用域中的變量。
def outer():
count = 0
def inner():
nonlocal count
count += 1
return count
return inner
f = outer()
print(f())
print(f())
輸出:
1 2
39. 什么是閉包?
函數(shù)內(nèi)部定義函數(shù),并且內(nèi)部函數(shù)引用了外部函數(shù)的變量,這種結(jié)構(gòu)就是閉包。
def make_multiplier(n):
def mul(x):
return x * n
return mul
double = make_multiplier(2)
print(double(5))
輸出:
10
40. 什么是裝飾器?
裝飾器本質(zhì)上是一個函數(shù),用于在不修改原函數(shù)代碼的情況下增強功能。
def log(func):
def wrapper():
print("before")
func()
print("after")
return wrapper
@log
def hello():
print("hello")
hello()
輸出:
before hello after
41. 裝飾器如何保留原函數(shù)信息?
使用 functools.wraps。
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@log
def hello():
"""say hello"""
print("hello")
print(hello.__name__)
print(hello.__doc__)
輸出:
hello say hello
42. 帶參數(shù)的裝飾器怎么寫?
from functools import wraps
def repeat(n):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(2)
def say():
print("hi")
say()
輸出:
hi hi
五、異常處理
43. Python 如何捕獲異常?
try:
x = 1 / 0
except ZeroDivisionError as e:
print("error:", e)
輸出:
error: division by zero
44.try...except...else...finally執(zhí)行順序是什么?
else 在沒有異常時執(zhí)行。
finally 無論是否異常都會執(zhí)行。
try:
x = 10 / 2
except ZeroDivisionError:
print("except")
else:
print("else:", x)
finally:
print("finally")
輸出:
else: 5.0 finally
45. 如何主動拋出異常?
使用 raise。
def check_age(age):
if age < 0:
raise ValueError("age cannot be negative")
return age
try:
check_age(-1)
except ValueError as e:
print(e)
輸出:
age cannot be negative
46. 如何自定義異常?
class BusinessError(Exception):
pass
raise BusinessError("業(yè)務(wù)異常")
輸出示例:
BusinessError: 業(yè)務(wù)異常
47. 為什么不要直接except Exception: pass?
因為這樣會吞掉錯誤,導(dǎo)致問題隱藏,排查困難。
try:
int("abc")
except Exception:
print("發(fā)生異常,但這里至少要記錄日志")
輸出:
發(fā)生異常,但這里至少要記錄日志
六、文件、上下文管理器、迭代器、生成器
48. 為什么推薦使用with open()?
with 會自動關(guān)閉文件,避免資源泄漏。
with open("demo.txt", "w", encoding="utf-8") as f:
f.write("hello")
49. 什么是上下文管理器?
實現(xiàn) __enter__ 和 __exit__ 方法的對象,就是上下文管理器。
class Demo:
def __enter__(self):
print("enter")
return self
def __exit__(self, exc_type, exc, tb):
print("exit")
with Demo():
print("running")
輸出:
enter running exit
50. 什么是迭代器?
實現(xiàn) __iter__() 和 __next__() 的對象就是迭代器。
nums = iter([1, 2, 3]) print(next(nums)) print(next(nums))
輸出:
1 2
51. 什么是可迭代對象?
能被 for 循環(huán)遍歷的對象,就是可迭代對象。
常見可迭代對象包括:
- 列表
- 元組
- 字典
- 字符串
- 集合
- 生成器
for ch in "abc":
print(ch)
輸出:
a b c
52. 什么是生成器?
包含 yield 的函數(shù)會返回生成器。生成器會按需產(chǎn)生數(shù)據(jù)。
def gen():
yield 1
yield 2
g = gen()
print(next(g))
print(next(g))
輸出:
1 2
53. 生成器有什么優(yōu)點?
生成器節(jié)省內(nèi)存,適合處理大數(shù)據(jù)流。
def numbers(n):
for i in range(n):
yield i
for x in numbers(3):
print(x)
輸出:
0 1 2
54.yield from有什么作用?
yield from 可以把子生成器的值交給外層生成器。
def gen():
yield from [1, 2, 3]
print(list(gen()))
輸出:
[1, 2, 3]
55. 生成器表達式和列表推導(dǎo)式有什么區(qū)別?
生成器表達式按需計算。
列表推導(dǎo)式會一次性生成完整列表。
g = (x * x for x in range(3)) print(g) print(list(g))
輸出示例:
<generator object <genexpr> at 0x...> [0, 1, 4]
七、面向?qū)ο?/h2>
56. 類和對象有什么區(qū)別?
類是模板,對象是類的實例。
class User:
pass
u = User()
print(type(u))
輸出:
<class '__main__.User'>
57.__init__是構(gòu)造函數(shù)嗎?
嚴格來說,__init__ 是初始化方法,對象創(chuàng)建后會調(diào)用它。
真正創(chuàng)建對象的是 __new__。
class User:
def __init__(self, name):
self.name = name
u = User("vito")
print(u.name)
輸出:
vito
58. 實例屬性和類屬性有什么區(qū)別?
實例屬性屬于對象。
類屬性屬于類。
class User:
role = "tester"
u1 = User()
u2 = User()
u1.name = "vito"
print(u1.role)
print(u2.role)
print(u1.name)
輸出:
tester tester vito
59. 類方法、靜態(tài)方法、實例方法有什么區(qū)別?
實例方法默認接收 self。
類方法默認接收 cls。
靜態(tài)方法不自動接收對象或類。
class Demo:
def ins(self):
print("instance")
@classmethod
def cls_method(cls):
print("class")
@staticmethod
def static_method():
print("static")
d = Demo()
d.ins()
Demo.cls_method()
Demo.static_method()
輸出:
instance class static
60. 什么是繼承?
子類可以復(fù)用父類的屬性和方法。
class Animal:
def speak(self):
print("animal speak")
class Dog(Animal):
pass
Dog().speak()
輸出:
animal speak
61. 什么是方法重寫?
子類重新定義父類方法,就是方法重寫。
class Animal:
def speak(self):
print("animal")
class Dog(Animal):
def speak(self):
print("wang")
Dog().speak()
輸出:
wang
62.super()有什么作用?
super() 用于調(diào)用父類方法。
class Base:
def hello(self):
print("base hello")
class Child(Base):
def hello(self):
super().hello()
print("child hello")
Child().hello()
輸出:
base hello child hello
63. Python 支持多繼承嗎?
支持。方法解析順序由 MRO 決定。
class A:
def hello(self):
print("A")
class B(A):
pass
class C(A):
def hello(self):
print("C")
class D(B, C):
pass
D().hello()
print(D.mro())
輸出示例:
C [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
64. 什么是魔術(shù)方法?
以雙下劃線開頭和結(jié)尾的方法,例如:
__str____repr____len____call____enter____exit__
class User:
def __str__(self):
return "User object"
print(User())
輸出:
User object
65.__repr__和__str__有什么區(qū)別?
__str__ 面向用戶,輸出更友好。
__repr__ 面向開發(fā)者和調(diào)試。
class User:
def __repr__(self):
return "User(name='vito')"
u = User()
print(repr(u))
輸出:
User(name='vito')
66.@property有什么作用?
@property 可以把方法當屬性訪問,同時封裝計算邏輯。
class Circle:
def __init__(self, r):
self.r = r
@property
def area(self):
return 3.14 * self.r * self.r
c = Circle(2)
print(c.area)
輸出:
12.56
67. 什么是dataclass?
dataclass 可以自動生成 __init__、__repr__ 等方法,適合定義數(shù)據(jù)類。
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
u = User("vito", 18)
print(u)
輸出:
User(name='vito', age=18)
68.__slots__有什么作用?
__slots__ 可以限制實例動態(tài)添加屬性,也可以減少內(nèi)存開銷。
class User:
__slots__ = ("name",)
u = User()
u.name = "vito"
print(u.name)
# u.age = 18 # AttributeError
輸出:
vito
八、模塊、包、虛擬環(huán)境、工程化
69. 模塊和包有什么區(qū)別?
一個 .py 文件可以是模塊。
包含多個模塊的目錄可以作為包。
# demo.py
def hello():
return "hello"
使用:
# import demo # print(demo.hello())
70.if __name__ == "__main__"有什么作用?
判斷當前文件是被直接運行,還是被其他模塊導(dǎo)入。
def main():
print("running main")
if __name__ == "__main__":
main()
直接運行輸出:
running main
71. Python 如何管理第三方依賴?
常用 pip 安裝依賴,并推薦使用虛擬環(huán)境。
python -m venv .venv source .venv/bin/activate pip install requests
Windows PowerShell:
python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install requests
72.requirements.txt有什么用?
requirements.txt 用于記錄項目依賴,方便環(huán)境復(fù)現(xiàn)。
requests==2.32.3 pytest==8.3.2
安裝依賴:
pip install -r requirements.txt
73.pyproject.toml是什么?
pyproject.toml 是現(xiàn)代 Python 項目常見配置文件,可配置:
- 項目信息
- 構(gòu)建系統(tǒng)
- pytest 配置
- black 配置
- mypy 配置
- ruff 配置
[project] name = "demo" version = "0.1.0" [tool.pytest.ini_options] testpaths = ["tests"]
74. Python 如何讀取環(huán)境變量?
import os
os.environ["APP_ENV"] = "dev"
print(os.getenv("APP_ENV"))
輸出:
dev
75.__all__有什么作用?
__all__ 用于控制 from module import * 導(dǎo)入的內(nèi)容。
__all__ = ["hello"]
def hello():
print("hello")
def hidden():
print("hidden")
九、并發(fā)、線程、進程、協(xié)程
76. 線程適合什么場景?
線程適合 IO 密集型任務(wù),例如:
- 網(wǎng)絡(luò)請求
- 文件讀寫
- 數(shù)據(jù)庫訪問
- 接口調(diào)用
import threading
import time
def task(name):
time.sleep(1)
print(name, "done")
t1 = threading.Thread(target=task, args=("A",))
t2 = threading.Thread(target=task, args=("B",))
t1.start()
t2.start()
t1.join()
t2.join()
輸出:
A done B done
77. 什么是 GIL?
GIL 是 CPython 中的全局解釋器鎖。
它會限制多個線程同時執(zhí)行 Python 字節(jié)碼,所以 CPU 密集型任務(wù)通常無法通過多線程獲得明顯性能提升。
def cpu_task():
return sum(i * i for i in range(100000))
print(cpu_task())
輸出:
333328333350000
78. 進程適合什么場景?
進程適合 CPU 密集型任務(wù)。
多進程可以利用多核 CPU。
from multiprocessing import Pool
def square(x):
return x * x
if __name__ == "__main__":
with Pool(2) as pool:
print(pool.map(square, [1, 2, 3]))
輸出:
[1, 4, 9]
79. 為什么 Windows 下多進程要寫if __name__ == "__main__"?
因為 Windows 創(chuàng)建子進程時會重新導(dǎo)入主模塊。
如果不加保護,可能導(dǎo)致子進程重復(fù)創(chuàng)建子進程。
from multiprocessing import Process
def hello():
print("hello")
if __name__ == "__main__":
p = Process(target=hello)
p.start()
p.join()
輸出:
hello
80. 協(xié)程適合什么場景?
協(xié)程適合高并發(fā) IO 場景,例如:
- 網(wǎng)絡(luò)請求
- WebSocket
- 異步數(shù)據(jù)庫
- 異步爬蟲
- 高并發(fā)接口調(diào)用
import asyncio
async def main():
print("start")
await asyncio.sleep(1)
print("end")
asyncio.run(main())
輸出:
start end
81.async和await是什么?
async 用于定義協(xié)程函數(shù)。
await 用于等待異步操作完成。
import asyncio
async def fetch():
await asyncio.sleep(1)
return "data"
async def main():
result = await fetch()
print(result)
asyncio.run(main())
輸出:
data
82. 如何并發(fā)運行多個協(xié)程?
使用 asyncio.gather()。
import asyncio
async def task(name):
await asyncio.sleep(1)
return f"{name} done"
async def main():
result = await asyncio.gather(task("A"), task("B"))
print(result)
asyncio.run(main())
輸出:
['A done', 'B done']
83.time.sleep()和asyncio.sleep()有什么區(qū)別?
time.sleep() 會阻塞當前線程。
asyncio.sleep() 會讓出事件循環(huán),不阻塞其他協(xié)程。
import asyncio
async def task():
await asyncio.sleep(1)
print("done")
asyncio.run(task())
輸出:
done
84. 如何避免多個線程同時修改共享數(shù)據(jù)?
可以使用鎖。
import threading
count = 0
lock = threading.Lock()
def inc():
global count
for _ in range(10000):
with lock:
count += 1
threads = [threading.Thread(target=inc) for _ in range(2)]
for t in threads:
t.start()
for t in threads:
t.join()
print(count)
輸出:
20000
十、常用標準庫與實戰(zhàn)能力
85.collections.defaultdict有什么用?
defaultdict 可以給不存在的 key 自動創(chuàng)建默認值。
from collections import defaultdict
d = defaultdict(list)
d["python"].append("good")
print(d)
輸出:
defaultdict(<class 'list'>, {'python': ['good']})
86.deque適合什么場景?
deque 是雙端隊列,適合從兩端快速添加和刪除元素。
from collections import deque q = deque([1, 2]) q.appendleft(0) q.append(3) print(q)
輸出:
deque([0, 1, 2, 3])
87.heapq有什么用?
heapq 可以實現(xiàn)堆,常用于:
- Top K
- 優(yōu)先隊列
- 小頂堆
import heapq nums = [5, 1, 3] heapq.heapify(nums) print(heapq.heappop(nums))
輸出:
1
88.json.dumps()和json.loads()有什么區(qū)別?
json.dumps() 把 Python 對象轉(zhuǎn)成 JSON 字符串。
json.loads() 把 JSON 字符串轉(zhuǎn)成 Python 對象。
import json
s = json.dumps({"name": "vito"}, ensure_ascii=False)
print(s)
obj = json.loads(s)
print(obj["name"])
輸出:
{"name": "vito"}
vito
89. 如何處理Decimal不能直接 JSON 序列化的問題?
可以轉(zhuǎn)換為字符串或浮點數(shù)。
如果是金額、精度敏感場景,建議轉(zhuǎn)換為字符串。
import json
from decimal import Decimal
data = {"price": str(Decimal("10.50"))}
print(json.dumps(data))
輸出:
{"price": "10.50"}
90.pathlib相比os.path有什么好處?
pathlib 是面向?qū)ο蟮穆窂教幚矸绞剑窂狡唇痈庇^。
from pathlib import Path
p = Path("logs") / "app.log"
print(p)
輸出:
logs/app.log
91. 如何讀取 CSV 文件?
import csv
rows = [["name", "score"], ["vito", "90"]]
with open("score.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerows(rows)
with open("score.csv", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row)
輸出:
{'name': 'vito', 'score': '90'}
92. 如何記錄日志?
import logging
logging.basicConfig(level=logging.INFO)
logging.info("service started")
輸出示例:
INFO:root:service started
93. 如何寫單元測試?
def add(a, b):
return a + b
def test_add():
assert add(1, 2) == 3
使用 pytest 運行:
pytest test_demo.py
輸出示例:
1 passed in 0.01s
94.pytest.raises怎么用?
import pytest
def div(a, b):
return a / b
def test_div_zero():
with pytest.raises(ZeroDivisionError):
div(1, 0)
輸出示例:
1 passed in 0.01s
十一、性能、內(nèi)存、編碼規(guī)范
95. 如何查看對象占用內(nèi)存?
import sys a = [1, 2, 3] print(sys.getsizeof(a))
輸出示例:
88
具體數(shù)值和 Python 版本、操作系統(tǒng)有關(guān)。
96. 如何優(yōu)化大列表處理?
能用生成器就不要一次性創(chuàng)建大列表。
total = sum(x * x for x in range(1000000)) print(total)
輸出:
333332833333500000
97. 淺拷貝和深拷貝有什么區(qū)別?
淺拷貝只復(fù)制外層對象。
深拷貝會遞歸復(fù)制內(nèi)部對象。
import copy a = [[1, 2], [3, 4]] b = copy.copy(a) c = copy.deepcopy(a) a[0].append(99) print(b) print(c)
輸出:
[[1, 2, 99], [3, 4]] [[1, 2], [3, 4]]
98.with為什么比手動close()更安全?
因為即使中間發(fā)生異常,with 也會執(zhí)行資源釋放邏輯。
try:
with open("demo.txt", "r", encoding="utf-8") as f:
print(f.read())
except FileNotFoundError:
print("file not found")
輸出示例:
hello
或者:
file not found
99. Python 代碼規(guī)范主要看什么?
常見關(guān)注點包括:
- 命名清晰
- 函數(shù)不要太長
- 異常不要亂吞
- 不要寫重復(fù)代碼
- 復(fù)雜邏輯拆函數(shù)
- 遵循 PEP 8 風(fēng)格
- 加必要的類型注解
- 加必要的單元測試
def calculate_total_price(price: float, count: int) -> float:
return price * count
print(calculate_total_price(9.9, 3))
輸出:
29.700000000000003
如果涉及金額,建議使用 Decimal。
100. 面試中如何回答“你怎么提升 Python 代碼質(zhì)量”?
可以從以下幾個方面回答:
- 使用類型注解提升可讀性
- 使用 pytest 編寫單元測試
- 使用 logging 記錄關(guān)鍵日志
- 使用異常處理保證程序穩(wěn)定
- 使用虛擬環(huán)境隔離依賴
- 使用 requirements.txt 或 pyproject.toml 管理依賴
- 使用 black、ruff、mypy 等工具做代碼檢查
- 使用 CI 流水線自動執(zhí)行測試和代碼掃描
- 復(fù)雜邏輯模塊化
- 性能敏感代碼做 profiling 分析
from typing import Sequence
def average(nums: Sequence[float]) -> float:
if not nums:
raise ValueError("nums cannot be empty")
return sum(nums) / len(nums)
print(average([80, 90, 100]))
輸出:
90.0
十二、總結(jié):Python 面試不是背答案,而是建立知識網(wǎng)絡(luò)
這 100 個問題可以分成 8 條主線:
- 基礎(chǔ)語法:變量、對象、類型、真假判斷
- 數(shù)據(jù)結(jié)構(gòu):字符串、列表、元組、字典、集合
- 函數(shù)能力:參數(shù)、閉包、裝飾器、高階函數(shù)
- 面向?qū)ο螅侯?、繼承、魔術(shù)方法、屬性管理
- 異常與資源:異常捕獲、上下文管理器、文件處理
- 并發(fā)模型:線程、進程、協(xié)程、GIL、鎖
- 標準庫:json、csv、pathlib、logging、collections
- 工程質(zhì)量:虛擬環(huán)境、依賴管理、測試、類型注解、代碼規(guī)范
真正的面試重點不是“你是否見過這個問題”,而是你能否用清晰的語言說明原理,并寫出可靠的小例子。
最好的準備方式是:
- 每個問題都自己敲一遍代碼
- 觀察真實輸出
- 嘗試修改參數(shù)和邊界條件
- 主動制造異常場景
- 把問題串成知識體系
當你能把一個知識點講清楚、寫明白、舉出例子,并能說出常見坑點時,面試基本就穩(wěn)了一半。
附:面試復(fù)習(xí)建議
如果你準備 Python 面試,可以按下面順序復(fù)習(xí):
第一階段:基礎(chǔ)語法
重點掌握:
- 變量
- 類型
- 判斷
- 循環(huán)
- 字符串
- 列表
- 字典
- 集合
第二階段:函數(shù)和對象
重點掌握:
- 參數(shù)傳遞
- 默認參數(shù)坑點
- 閉包
- 裝飾器
- 類
- 繼承
- 魔術(shù)方法
第三階段:工程能力
重點掌握:
- 虛擬環(huán)境
- pip
- requirements.txt
- pyproject.toml
- 日志
- 異常
- 單元測試
第四階段:進階能力
重點掌握:
- 迭代器
- 生成器
- 上下文管理器
- 多線程
- 多進程
- 協(xié)程
- GIL
- 性能優(yōu)化
第五階段:項目表達
面試時不要只說“我會 Python”,而要結(jié)合項目講:
- 我用 Python 做過什么
- 解決了什么問題
- 遇到過什么坑
- 如何排查問題
- 如何提升效率
- 如何保證代碼質(zhì)量
例如:
我在自動化測試平臺中使用 Python 編寫接口測試腳本,通過 pytest 管理測試用例,結(jié)合 logging 輸出關(guān)鍵日志,并使用 requests 封裝接口調(diào)用。對于復(fù)雜業(yè)務(wù)場景,我會把公共邏輯抽成工具函數(shù)或類,同時通過 fixture 管理測試數(shù)據(jù),提升了用例復(fù)用性和維護性。
這樣的回答,比單純背語法更有說服力。
參考方向
本文內(nèi)容主要圍繞 Python 常見面試點整理,建議進一步閱讀:
- Python 官方文檔
- Python Tutorial
- Python Data Model
- Python Standard Library
- pytest 官方文檔
- Python Packaging 官方文檔
- asyncio 官方文檔
- threading 官方文檔
- multiprocessing 官方文檔
到此這篇關(guān)于Python常見100個經(jīng)典面試問題總結(jié)的文章就介紹到這了,更多相關(guān)Python經(jīng)典面試問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Django實現(xiàn)學(xué)員管理系統(tǒng)
這篇文章主要為大家詳細介紹了Django實現(xiàn)學(xué)員管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-02-02
python服務(wù)器與android客戶端socket通信實例
這篇文章主要介紹了python服務(wù)器與android客戶端socket通信的實現(xiàn)方法,實例形式詳細講述了Python的服務(wù)器端實現(xiàn)原理與方法,以及對應(yīng)的Android客戶端實現(xiàn)方法,需要的朋友可以參考下2014-11-11
將本地Python項目打包成docker鏡像上傳到服務(wù)器并在docker中運行
Docker是一個開源項目,為開發(fā)人員和系統(tǒng)管理員提供了一個開放平臺,可以將應(yīng)用程序構(gòu)建、打包為一個輕量級容器,并在任何地方運行,這篇文章主要給大家介紹了關(guān)于將本地Python項目打包成docker鏡像上傳到服務(wù)器并在docker中運行的相關(guān)資料,需要的朋友可以參考下2023-12-12
Python自動化復(fù)制Excel sheet表的兩種實用方案
日常辦公或數(shù)據(jù)處理中,我們經(jīng)常會遇到需要復(fù)制Excel工作表(sheet)的場景,今天就給大家分享兩種Python自動化復(fù)制Excel sheet表的實用方案,分別基于openpyxl和win32com實現(xiàn),需要的朋友可以參考下2026-05-05
Django的數(shù)據(jù)模型訪問多對多鍵值的方法
這篇文章主要介紹了Django的數(shù)據(jù)模型訪問多對多鍵值的方法,Django是Python豐富多彩的web框架中最具人氣的一個,需要的朋友可以參考下2015-07-07
Python3 把一個列表按指定數(shù)目分成多個列表的方式
今天小編就為大家分享一篇Python3 把一個列表按指定數(shù)目分成多個列表的方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
python調(diào)用Matplotlib繪制分布點并且添加標簽
這篇文章主要為大家詳細介紹了python調(diào)用Matplotlib繪制分布點并且添加標簽的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05

