大厂面试python复习基础100题
- [一、先建立 0 基础 Python 思维](#一、先建立 0 基础 Python 思维)
- [二、100 题按知识点讲解与答案](#二、100 题按知识点讲解与答案)
-
- [A. Python 基础概念:](#A. Python 基础概念:)
-
- [1. Python 有什么特点?](#1. Python 有什么特点?)
- [3. Python 是通用编程语言吗?](#3. Python 是通用编程语言吗?)
- [4. Python 为什么叫解释型语言?](#4. Python 为什么叫解释型语言?)
- [5. 什么是 PEP?](#5. 什么是 PEP?)
- [6. Python 如何管理内存?](#6. Python 如何管理内存?)
- [7. 什么是命名空间?](#7. 什么是命名空间?)
- [8. 什么是 PYTHONPATH?](#8. 什么是 PYTHONPATH?)
- [9. 什么是 Python 模块?](#9. 什么是 Python 模块?)
- [10. 局部变量和全局变量](#10. 局部变量和全局变量)
- [11. Python 区分大小写吗?](#11. Python 区分大小写吗?)
- [12. 类型转换](#12. 类型转换)
- [13. Windows 安装 Python 和设置路径](#13. Windows 安装 Python 和设置路径)
- [14. Python 是否需要缩进?](#14. Python 是否需要缩进?)
- [26 / 31. Python 注释](#26 / 31. Python 注释)
- [32. Docstring 是什么?](#32. Docstring 是什么?)
- [33. is、not、in](#33. is、not、in)
- [34. help() 和 dir()](#34. help() 和 dir())
- [35. Python 退出时为什么不一定清理所有内存?](#35. Python 退出时为什么不一定清理所有内存?)
- [44. Python 内置类型](#44. Python 内置类型)
- [93. 标识符最大长度是多少?](#93. 标识符最大长度是多少?)
- [94. 为什么不鼓励下划线开头变量?](#94. 为什么不鼓励下划线开头变量?)
- [95. 哪个声明无效?](#95. 哪个声明无效?)
- [B. 列表、元组、字典、字符串、索引:1、15、21、29、30、36、39~41、46、47、53、91、97](#B. 列表、元组、字典、字符串、索引:1、15、21、29、30、36、39~41、46、47、53、91、97)
-
- [1. 列表和元组区别](#1. 列表和元组区别)
- [15. 数组和列表区别](#15. 数组和列表区别)
- [21. `::-1` 是什么?](#21.
[::-1]是什么?) - [29. 字符串首字母大写](#29. 字符串首字母大写)
- [30. 字符串转小写](#30. 字符串转小写)
- [36. 字典是什么?](#36. 字典是什么?)
- [39. len() 函数有什么作用?](#39. len() 函数有什么作用?)
- [40. split、sub、subn](#40. split、sub、subn)
- [41. 负索引](#41. 负索引)
- [46. 添加元素](#46. 添加元素)
- [47. 删除元素](#47. 删除元素)
- [53. split 函数](#53. split 函数)
- [91. 哪些语句创建字典?](#91. 哪些语句创建字典?)
- [97. `list1-1`](#97.
list1[-1])
- [C. 函数、参数、迭代器、生成器、随机数:16、18、20、22~25、27、28、37、38、54、85](#C. 函数、参数、迭代器、生成器、随机数:16、18、20、22~25、27、28、37、38、54、85)
-
- [16. 函数是什么?](#16. 函数是什么?)
- [18. lambda 函数](#18. lambda 函数)
- [20. break、continue、pass](#20. break、continue、pass)
- [22. 随机打乱列表](#22. 随机打乱列表)
- [23. 迭代器是什么?](#23. 迭代器是什么?)
- [24. 生成随机数](#24. 生成随机数)
- [25. range 和 xrange 区别](#25. range 和 xrange 区别)
- [27. pickling 和 unpickling](#27. pickling 和 unpickling)
- [28. 生成器是什么?](#28. 生成器是什么?)
- [37. 三元运算符](#37. 三元运算符)
- [38. `*args` 和 `**kwargs`](#38.
*args和**kwargs) - [54. 如何在 Python 中导入模块?](#54. 如何在 Python 中导入模块?)
- [85. map 函数](#85. map 函数)
- [D. 面向对象:17、19、48、55~64](#D. 面向对象:17、19、48、55~64)
-
- [17. `init` 是什么?](#17.
__init__是什么?) - [19. self 是什么?](#19. self 是什么?)
- [48. Python 有 OOP 概念吗?](#48. Python 有 OOP 概念吗?)
- [55. 继承是什么?](#55. 继承是什么?)
- [56. 创建类](#56. 创建类)
- [57. Python 补丁 / 猴子补丁](#57. Python 补丁 / 猴子补丁)
- [58. Python 支持多重继承吗?](#58. Python 支持多重继承吗?)
- [59. 多态是什么?](#59. 多态是什么?)
- [60. 封装是什么?](#60. 封装是什么?)
- [61. 数据抽象是什么?](#61. 数据抽象是什么?)
- [62. Python 有访问修饰符吗?](#62. Python 有访问修饰符吗?)
- [63. 空类](#63. 空类)
- [64. object() 函数](#64. object() 函数)
- [17. `init` 是什么?](#17.
- [E. 文件、异常、复制、多线程:43、49~52、70、96、98~100](#E. 文件、异常、复制、多线程:43、49~52、70、96、98~100)
-
- [43. 删除文件](#43. 删除文件)
- [49. 浅拷贝和深拷贝](#49. 浅拷贝和深拷贝)
- [50. Python 多线程和 GIL](#50. Python 多线程和 GIL)
- [51. Python 编译和链接](#51. Python 编译和链接)
- [52. Python 库](#52. Python 库)
- [70. 统计文件中大写字母数量](#70. 统计文件中大写字母数量)
- [96. 异常题](#96. 异常题)
- [98. 打开文件写入](#98. 打开文件写入)
- [99. with 打开文件后是否关闭?](#99. with 打开文件后是否关闭?)
- [100. try-except-else 中 else 什么时候执行?](#100. try-except-else 中 else 什么时候执行?)
- [F. 算法题:65~72](#F. 算法题:65~72)
-
- [65. 冒泡排序](#65. 冒泡排序)
- [66. 星号三角形](#66. 星号三角形)
- [67. Fibonacci 数列](#67. Fibonacci 数列)
- [68. 判断素数](#68. 判断素数)
- [69. 判断回文](#69. 判断回文)
- [71. 列表排序](#71. 列表排序)
- [72. 阅读代码求值](#72. 阅读代码求值)
- [G. Web 框架与爬虫:73~84](#G. Web 框架与爬虫:73~84)
-
- [73. Flask 是什么?](#73. Flask 是什么?)
- [74. Django 和 Flask 比较](#74. Django 和 Flask 比较)
- [75. Django、Pyramid、Flask 差异](#75. Django、Pyramid、Flask 差异)
- [76. Django 架构](#76. Django 架构)
- [77. Django 设置数据库](#77. Django 设置数据库)
- [78. Django View 示例](#78. Django View 示例)
- [79. Django 模板组成](#79. Django 模板组成)
- [80. Django Session](#80. Django Session)
- [81. Django 继承样式](#81. Django 继承样式)
- [82. 根据 URL 保存图片](#82. 根据 URL 保存图片)
- [83. 获取 Google 缓存页面](#83. 获取 Google 缓存页面)
- [84. 爬取 IMDb 前 250 电影](#84. 爬取 IMDb 前 250 电影)
- [H. NumPy、SciPy、数据分析:45、86~90](#H. NumPy、SciPy、数据分析:45、86~90)
-
- [45. NumPy 相比 Python 列表的优势](#45. NumPy 相比 Python 列表的优势)
- [86. NumPy 比列表好吗?](#86. NumPy 比列表好吗?)
- [87. NumPy 数组中 N 个最大值的索引](#87. NumPy 数组中 N 个最大值的索引)
- [88. NumPy 计算百分位数](#88. NumPy 计算百分位数)
- [89. NumPy 和 SciPy 区别](#89. NumPy 和 SciPy 区别)
- [90. NumPy/SciPy 做 3D 可视化](#90. NumPy/SciPy 做 3D 可视化)
- 三、python中的装饰器:
- [四、面试中最重点的 20 几个高频考题](#四、面试中最重点的 20 几个高频考题)
一、先建立 0 基础 Python 思维
你先记住这 6 句话:
- 变量 就是给数据起名字:
name = "Tom"。 - 类型就是数据的种类:整数、字符串、列表、字典等。
- 函数 就是一段可重复使用的代码:
def add(a, b): return a + b。 - 类和对象就是用代码模拟现实事物,比如"员工 Employee"。
- 模块 就是一个
.py文件,里面可以放函数、变量、类。 - 缩进在 Python 里非常重要,它决定代码属于哪一块。
二、100 题按知识点讲解与答案
A. Python 基础概念:
1. Python 有什么特点?
Python 是解释型、动态类型、面向对象、语法简单、开发快的语言。
解释:
C/C++ 通常是:
- 源代码 → 编译器 → 机器码程序 → CPU 直接执行
Python 常见运行过程是:
- py 源代码 → 字节码 → Python 虚拟机执行
Python 这样设计,是为了提高开发效率、增强代码灵活性、方便跨平台运行。
面试可以这样说:
Python 不需要像 C/C++ 那样先手动编译再运行,它由解释器执行。Python 是动态类型语言,变量不用提前声明类型。Python 支持面向对象,也常用于 Web、自动化、数据分析、人工智能等领域。
3. Python 是通用编程语言吗?
是。Python 不只是脚本语言,它可以做 Web、爬虫、数据分析、AI、自动化、后端服务等。
补充解释:
脚本语言强调"快速完成自动化任务",比如批量处理文件、爬虫、自动化测试。 通用编程语言强调"能做很多领域的软件",比如
- Web、AI、数据分析、自动化、后端服务。
结论:- Python 既可以写小脚本,也可以做大型项目。
4. Python 为什么叫解释型语言?
因为 Python 程序通常由解释器执行,不需要开发者手动编译成机器码。
更准确地说,Python 会先生成字节码,再由虚拟机执行。但面试初级岗位说"Python 是解释型语言"就够了。
注意:
- 解释型语言不等于一定有虚拟机。 编译型语言也不等于一定没有虚拟机。 C/C++ 通常编译成机器码直接执行。 Java 是编译成字节码后由
- JVM 执行。 Python 常见实现也是源码到字节码,再由虚拟机执行。
5. 什么是 PEP?
PEP 是 Python Enhancement Proposal,意思是 Python 增强提案。
最常见的是 PEP 8,它规定 Python 代码风格,比如缩进 4 个空格、变量名小写加下划线等。
补充解释:
- PEP 是 Python 社区记录语言设计、改进和规范的正式文档。 PEP 8 是其中最常见的代码风格指南。
要特别说明:
- Python 强制要求缩进,但不强制必须 4 个空格(都是2个空格的python代码也能运行,只要缩进对齐没问题就行)。 4 个空格是 PEP 8 推荐风格。 变量名小写加下划线也是 PEP 8 推荐风格,不是语法强制。
6. Python 如何管理内存?
Python 自动管理内存。对象放在私有堆空间里,程序员不用手动释放。Python 有垃圾回收机制,会清理不再使用的对象。
你可以这样答:
- Python 的内存由解释器管理,主要包括引用计数和垃圾回收机制。开发者通常不需要手动分配和释放内存。
面试回答核心:- Python 的内存管理主要包括对象分配、引用计数和垃圾回收。
7. 什么是命名空间?
命名空间就是"名字存放的地方"。
比如:
python
x = 10
这里 x 这个名字就存在某个命名空间里。函数内部有局部命名空间,整个文件有全局命名空间。
比如变量名、函数名、类名都会存在某个命名空间里。
常见命名空间:
局部命名空间。
全局命名空间。
内置命名空间。
作用:
避免命名冲突。
8. 什么是 PYTHONPATH?
PYTHONPATH 是环境变量,用来告诉 Python 去哪些目录查找模块。
例如你写:
python
import my_module
Python 会在当前目录、标准库目录、PYTHONPATH 指定的目录里查找这个模块。
9. 什么是 Python 模块?
模块是 Python 组织代码的单位,最常见形式是一个 .py 文件。
补充解释:
一个模块可以包含变量、函数、类。
例如:
python
# my_tools.py
PI = 3.14
def add(a, b):
return a + b
class Dog:
pass
这个 my_tools.py 就是一个模块。
导入:
python
import my_tools
print(my_tools.PI)
print(my_tools.add(1, 2))
可以把模块理解成"工具箱"。
附加内容:
math 不是 C/C++ 的数学头文件,而是 Python 官方提供的数学模块。
python
import math
print(math.sqrt(16))
print(math.pi)
print(math.ceil(3.2))
常用模块:
python
sys
os
math
random
datetime
json
re
10. 局部变量和全局变量
函数外定义的是全局变量,函数内定义的是局部变量。
python
x = 10 # 全局变量
def test():
y = 20 # 局部变量
print(y)
print(x)
x 是全局变量。
y 是局部变量。
x 在整个文件里都能访问,y 只能在函数内部使用。
11. Python 区分大小写吗?
区分。
python
Name = "Tom"
name = "Jerry"
Name 和 name 是两个不同变量。
12. 类型转换
类型转换就是把一种类型变成另一种类型。
常见例子:
python
int("123") # 字符串转整数
float("3.14") # 字符串转小数
str(100) # 数字转字符串
list("abc") # ['a', 'b', 'c']
tuple([1, 2]) # (1, 2)
set([1, 1, 2]) # {1, 2}
13. Windows 安装 Python 和设置路径
面试一般不会深问。核心回答:
- 从 Python 官网下载安装。
- 安装时勾选
Add Python to PATH。 - 命令行输入
python --version验证安装。
14. Python 是否需要缩进?
需要。Python 用缩进表示代码块。
python
if True:
print("hello")
缩进错误会报错。
补充:
Python 强制要求缩进,但 4 个空格是 PEP 8 推荐风格。
26 / 31. Python 注释
单行注释用 #:
python
# 这是注释
print("hello")
多行说明常用三引号:
python
"""
这是多行说明
也可以作为文档字符串
"""
补充:
如果三引号写在模块、函数、类的开头,通常叫 Docstring。用于说明其用途、参数、返回值等,可通过 doc 属性访问,并被 IDE 和文档工具识别。
32. Docstring 是什么?
Docstring 是文档字符串,用于说明其用途、参数、返回值等,可通过 doc 属性访问,并被 IDE 和文档工具识别。
- docstring必须紧跟在函数定义后,且只有第一段字符串会被识别为文档字符串。
python
def add(a, b):
"""返回两个数的和"""
return a + b
补充:
Docstring 和普通注释的区别:
普通注释运行时不会被保存。
Docstring 会被 Python 保存,可以通过 doc 或 help() 查看。
python
print(add.__doc__)
help(add)
33. is、not、in
python
a is b
判断两个变量是不是同一个对象。
python
a == b
判断两个值是否相等。
python
not True
取反。
python
3 in [1, 2, 3]
判断元素是否存在。
面试重点:is 比较对象身份,== 比较值是否相等。
34. help() 和 dir()
help() 用来看帮助文档:
python
help(str)
dir() 用来看对象有哪些属性和方法:
python
dir(list)
35. Python 退出时为什么不一定清理所有内存?
Python 退出时会尝试清理大部分对象。
但有些循环引用、全局对象、C 扩展占用的内存可能不会逐个释放。最终操作系统会回收进程资源。
44. Python 内置类型
常见内置类型:
python
int # 整数
float # 小数
complex # 复数
str # 字符串
bool # 布尔
list # 列表
tuple # 元组
dict # 字典
set # 集合
93. 标识符最大长度是多少?
Python 标识符理论上可以很长,没有固定最大长度限制。
标识符就是变量名、函数名、类名等。
94. 为什么不鼓励下划线开头变量?
因为约定俗成:单下划线开头表示"内部使用,不建议外部访问"。
比如
python
_name
表示内部使用,不建议外部访问。
不是强制私有,只是一种约定。
95. 哪个声明无效?
python
abc = 1000 2000 3000
无效,因为数字之间没有运算符,也没有逗号。
补充:
注意:
python
abc = 1,000,000
这是有效的,但它表示一个元组:
python
(1, 0, 0)
B. 列表、元组、字典、字符串、索引:1、15、21、29、30、36、39~41、46、47、53、91、97
1. 列表和元组区别
列表 list 用 [],可以修改。
元组 tuple 用 (),一般不能修改。
列表 list:
python
a = [1, 2, 3]
a[0] = 100
元组 tuple:
python
b = (1, 2, 3)
面试答法:
列表是可变对象,适合存放需要修改的数据;元组是不可变对象,适合存放固定数据。列表用
[],元组用()。
15. 数组和列表区别
Python 列表可以放不同类型:
python
a = [1, "hello", 3.14]
数组通常要求元素类型一致。
比如:
python
from array import array
a = array("i", [1, 2, 3])
NumPy 数组也通常是同一种类型,适合计算。
21. [::-1] 是什么?
[::-1]表示反转序列。
python
s = "abc"
print(s[::-1]) # cba
输出:
python
cba
可以用来判断回文。
29. 字符串首字母大写
使用 capitalize()。
python
"hello".capitalize()
结果:
python
"Hello"
30. 字符串转小写
python
"HELLO".lower()
结果:
python
"hello"
36. 字典是什么?
字典dict是键值对结构。
python
person = {
"name": "Tom",
"age": 18
}
通过 key 找 value:
python
person["name"]
结果是:
python
"Tom"
39. len() 函数有什么作用?
len()用来获取长度。
python
len("abc") # 3
len([1, 2, 3]) # 3
len({"a": 1, "b": 2})
40. split、sub、subn
普通字符串的 split()用来切分字符串。
python
"a,b,c".split(",")
结果:
python
["a", "b", "c"]
正则模块 re 中:
python
re.split() # 按正则切分。
re.sub() # 按正则替换。
re.subn() # 替换并返回替换次数。
sub() 是替换,subn() 替换并返回替换次数。
41. 负索引
负索引是从后往前取元素。
python
a = [10, 20, 30]
print(a[-1])
print(a[-2])
输出:
python
30
20
-1表示最后一个元素。
46. 添加元素
重点融合内容:
python
a = [1, 2]
a.append(3) # 末尾加一个
a.extend([4, 5]) # 末尾加多个
a.insert(0, 100) # 指定位置插入
append() 添加一个元素。
extend() 添加多个元素。
insert() 在指定位置插入。
47. 删除元素
python
a.pop()
删除并返回最后一个元素。
python
a = [1, 2, 3]
a.remove(2)
remove() 按值删除,不返回删除值。
53. split 函数
python
a = "edureka python"
print(a.split())
结果:
python
["edureka", "python"]
91. 哪些语句创建字典?
正确:
python
d = {}
d = {"john": 40, "peter": 45}
d = {40: "john", 45: "peter"}
错误:
python
d = (40: "john", 45: "50")
字典外层必须用 {},并且是 key-value 结构。
97. list1[-1]
python
list1 = [2, 33, 222, 14, 25]
list1[-1]
结果:
python
25
-1 表示最后一个元素。
C. 函数、参数、迭代器、生成器、随机数:16、18、20、22~25、27、28、37、38、54、85
16. 函数是什么?
函数是一段可以重复使用的代码。
python
def add(a, b):
return a + b
print(add(1, 2))
函数的作用是减少重复代码。
18. lambda 函数
lambda 是匿名函数,适合写简单函数。
python
f = lambda x: x + 1
print(f(2)) # 3
等价于:
python
def f(x):
return x + 1
20. break、continue、pass
break:结束整个循环。
continue:跳过当前循环,进入下一轮。
pass:什么都不做,只是占位。
python
break
直接结束循环。
python
continue
跳过本轮循环,进入下一轮。
python
pass
什么都不做,只是占位。
例子:
python
for i in range(5):
if i == 2:
continue
print(i)
输出不会有 2。
22. 随机打乱列表
使用 random.shuffle()。
python
from random import shuffle
x = ["Keep", "The", "Blue"]
shuffle(x)
print(x)
shuffle() 会原地打乱列表。
23. 迭代器是什么?
迭代器是可以被 next() 一个一个取值的对象。
python
a = iter([1, 2, 3])
print(next(a)) # 1
print(next(a)) # 2
24. 生成随机数
使用 random 模块。
python
import random
random.random()
生成 0 到 1 之间的小数。
常见方法:
python
random.randint(1, 10)
random.randrange(1, 10)
random.uniform(1, 10)
25. range 和 xrange 区别
这是 Python 2 的问题。
Python 2:
python
range()
直接生成列表。
python
xrange()
按需生成,更省内存。
Python 3 里:
- 没有
xrange() range()本身就是按需生成的。
面试按 Python 3 答:
Python 3 中只有
range(),它返回一个 range 对象,不会一次性生成完整列表,节省内存。
27. pickling 和 unpickling
Pickling 序列化:把 Python 对象保存成二进制数据。
Unpickling 反序列化:把保存的数据还原成 Python 对象。
python
import pickle
data = {"name": "Tom"}
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
with open("data.pkl", "rb") as f:
obj = pickle.load(f)
28. 生成器是什么?
生成器是一种特殊迭代器,用 yield 返回数据。
python
def gen():
yield 1
yield 2
yield 3
g = gen()
print(next(g))
print(next(g))
优点:
- 不会一次性把所有数据放进内存。
- 用到一个生成一个。
- 适合处理大量数据。
37. 三元运算符
格式:
值1 if 条件 else 值2
python
big = x if x > y else y
意思是:
如果
x > y,big 等于 x,否则等于 y。
38. *args 和 **kwargs
*args 接收多个位置参数,结果是元组。
python
def test(*args):
print(args)
test(1, 2, 3)
结果:
python
(1, 2, 3)
**kwargs 接收多个关键字参数,结果是字典:
python
def test(**kwargs):
print(kwargs)
test(name="Tom", age=18)
结果:
python
{"name": "Tom", "age": 18}
54. 如何在 Python 中导入模块?
重点融合内容:
python
import math
使用:
python
math.sqrt(16)
起别名:
python
import math as m
print(m.sqrt(16))
只导入某个函数:
python
from math import sqrt
print(sqrt(16))
不推荐滥用:
python
from math import *
因为容易命名冲突。
面试建议说:
推荐使用
import module或from module import name,不推荐大量使用import *,因为容易命名冲突。
85. map 函数
map() 会把一个函数应用到序列的每个元素上。
python
nums = [1, 2, 3]
result = map(lambda x: x * 2, nums)
print(list(result))
结果:
python
[2, 4, 6]
map() 返回的是一个迭代器,所以通常需要用 list() 转换后查看结果。
D. 面向对象:17、19、48、55~64
17. __init__ 是什么?
__init__ 是初始化方法,创建对象时自动执行。
python
class Person:
def __init__(self, name):
self.name = name
p = Person("Tom")
创建 p 时,会自动调用 __init__。
19. self 是什么?
self 代表当前对象自己。
python
class Person:
def __init__(self, name):
self.name = name
self.name 是对象自己的名字。
48. Python 有 OOP 概念吗?
有。Python 支持面向对象编程,包括类、对象、继承、多态、封装等。
55. 继承是什么?
继承就是子类可以使用父类的属性和方法。
python
class Animal:
def eat(self):
print("eat")
class Dog(Animal):
pass
d = Dog()
d.eat()
56. 创建类
python
class Employee:
def __init__(self, name):
self.name = name
e1 = Employee("abc")
print(e1.name)
57. Python 补丁 / 猴子补丁
运行时动态修改类或模块的行为。
python
class A:
def hello(self):
print("hello")
def new_hello(self):
print("new hello")
A.hello = new_hello
这叫 monkey patch,灵活但容易让代码难维护。
58. Python 支持多重继承吗?
支持。
python
class A:
pass
class B:
pass
class C(A, B):
pass
59. 多态是什么?
同一个方法名,不同对象有不同表现。
python
class Dog:
def speak(self):
print("wang")
class Cat:
def speak(self):
print("miao")
调用 speak(),不同对象结果不同。
60. 封装是什么?
封装就是把数据和操作数据的方法放在类里。
python
class Person:
def __init__(self, name):
self.name = name
def say_hi(self):
print("Hi", self.name)
61. 数据抽象是什么?
抽象就是只暴露必要功能,隐藏内部细节。
比如你调用:
python
list.sort()
你不用关心它内部怎么排序。
62. Python 有访问修饰符吗?
Python 没有 Java 那种严格的 private/public。
但有约定:
python
_name # 受保护风格,提示内部使用
__name # 名称改写,较难从外部直接访问
63. 空类
python
class Empty:
pass
pass 是占位语句。
64. object() 函数
object() 返回一个最基础的对象。所有类最终都继承自 object。
E. 文件、异常、复制、多线程:43、49~52、70、96、98~100
43. 删除文件
python
import os
os.remove("test.txt")
49. 浅拷贝和深拷贝
浅拷贝只复制外层对象,里面的子对象还是共用。
深拷贝会递归复制里面的对象。
python
import copy
b = copy.copy(a) # 浅拷贝
c = copy.deepcopy(a) # 深拷贝
面试口诀:
浅拷贝拷贝外壳,深拷贝连里面一起拷贝。
50. Python 多线程和 GIL
Python 有多线程,但 CPython 有 GIL,全局解释器锁。
面试可以说:
GIL 使得同一时刻只有一个线程执行 Python 字节码,所以 CPU 密集型任务多线程不一定更快;I/O 密集型任务可以使用多线程提高效率。
51. Python 编译和链接
这题偏 C 扩展。简单答:
Python 可以通过 C/C++ 扩展提升性能。扩展模块需要编译成动态库,再由 Python 解释器加载。
52. Python 库
库就是一组模块或包。
常见库:
python
NumPy
Pandas
Matplotlib
Scikit-learn
Requests
Flask
Django
70. 统计文件中大写字母数量
推荐写法:
python
count = 0
with open("data.txt", "r", encoding="utf-8") as f:
for line in f:
for char in line:
if char.isupper():
count += 1
print(count)
一行写法:
python
count = sum(1 for line in f for char in line if char.isupper())
PDF 里少了一个 =,正确是 count = sum(...)。
96. 异常题
代码:
python
raise "someError"
在 Python 3 中是无效的,因为异常必须继承自 BaseException。
正确答案:无效代码。
正确写法:
python
raise Exception("someError")
98. 打开文件写入
正确:
python
outfile = open("c:\\scores.txt", "w")
或者:
python
outfile = open(r"c:\scores.txt", "w")
答案选 w,因为 w 表示写入。
99. with 打开文件后是否关闭?
python
with open("data.txt", "w") as f:
pass
print(f.closed)
结果:
python
True
因为 with 代码块结束后会自动关闭文件。
注意:PDF 里的 print f.closed 是 Python 2 写法,Python 3 应该写:
python
print(f.closed)
100. try-except-else 中 else 什么时候执行?
没有异常时执行。
python
try:
print("ok")
except:
print("error")
else:
print("no error")
F. 算法题:65~72
65. 冒泡排序
冒泡排序思想:
相邻两个数比较,大的往后放。每一轮都会把当前最大的数"冒泡"到最后。
python
def bubble_sort(a):
n = len(a)
for i in range(n - 1):
for j in range(n - 1 - i):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
return a
print(bubble_sort([32, 5, 3, 6, 7, 54, 87]))
输出:
python
[3, 5, 6, 7, 32, 54, 87]
66. 星号三角形
python
def star_triangle(r):
for x in range(r):
print(" " * (r - x - 1) + "*" * (2 * x + 1))
star_triangle(5)
输出大概是:
text
*
***
*****
*******
*********
67. Fibonacci 数列
规律:
text
0, 1, 1, 2, 3, 5, 8...
后一个数 = 前两个数之和。
python
n = int(input("Enter the terms: "))
a = 0
b = 1
for i in range(n):
print(a, end=" ")
a, b = b, a + b
68. 判断素数
素数:只能被 1 和自己整除的数。
python
num = int(input("enter number: "))
if num <= 1:
print("not prime")
else:
for i in range(2, num):
if num % i == 0:
print("not prime")
break
else:
print("prime")
69. 判断回文
回文就是正着读和反着读一样。
python
a = input("enter sequence: ")
if a == a[::-1]:
print("palindrome")
else:
print("not palindrome")
71. 列表排序
python
lst = ["1", "4", "0", "6", "9"]
lst = [int(i) for i in lst]
lst.sort()
print(lst)
结果:
python
[0, 1, 4, 6, 9]
72. 阅读代码求值
重点知识:
python
zip()
dict()
range()
sorted()
列表推导式
字典推导式
结果:
python
A0 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
A1 = range(0, 10)
A2 = []
A3 = [1, 2, 3, 4, 5]
A4 = [1, 2, 3, 4, 5]
A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
其中 A2 = [],因为 A1 里是数字,A0 的 key 是 'a' 'b' 'c',所以没有匹配项。
G. Web 框架与爬虫:73~84
73. Flask 是什么?
Flask 是 Python 的轻量级 Web 框架。
面试答法:
Flask 是一个微框架,简单灵活,适合小型项目或接口服务。它依赖较少,常配合 Werkzeug、Jinja2 使用。
74. Django 和 Flask 比较
Flask:
轻量、自由、灵活,很多功能需要自己选扩展。
Django:
大而全,自带 ORM、后台管理、认证、模板系统,适合中大型项目。
75. Django、Pyramid、Flask 差异
Flask:小型项目,轻量灵活。
Pyramid:中大型项目,配置灵活。
Django:大而全,自带 ORM、Admin、认证等功能。
76. Django 架构
Django 常说 MVT:
text
Model 数据模型
View 业务逻辑
Template 页面模板
URL 把请求映射到 View。
77. Django 设置数据库
在 settings.py 中配置 DATABASES。
常见数据库:
python
SQLite
MySQL
PostgreSQL
Oracle
78. Django View 示例
python
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = f"<html><body>It is now {now}</body></html>"
return HttpResponse(html)
PDF 里的字符串格式有点旧,建议用 f-string。
79. Django 模板组成
模板是文本文件,里面包含:
text
变量
标签
过滤器
HTML 内容
例如:
html
Hello, {{ name }}
80. Django Session
Session 用来在多次请求之间保存用户状态。
比如登录后,服务器需要记住"这个用户已经登录"。
Django 通常通过 cookie 保存 session id,真正的数据保存在服务器端。
81. Django 继承样式
三种:
text
抽象基类
多表继承
代理模型
82. 根据 URL 保存图片
python
import urllib.request
urllib.request.urlretrieve("图片URL", "local-filename.jpg")
83. 获取 Google 缓存页面
PDF 给的是 Google cache URL 格式。这题现在实战意义不强,面试简单说:
可以通过 Google cache 的特殊 URL 查询网页缓存,但实际可用性取决于 Google 是否缓存该页面。
84. 爬取 IMDb 前 250 电影
核心流程:
text
requests 请求网页
BeautifulSoup 解析 HTML
find / find_all 提取数据
循环输出电影名、年份、评分
面试不一定要求背代码,重点是知道爬虫流程:
python
import requests
from bs4 import BeautifulSoup
url = "https://www.imdb.com/chart/top"
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
H. NumPy、SciPy、数据分析:45、86~90
45. NumPy 相比 Python 列表的优势
Python 列表灵活,但数值计算慢。
NumPy 数组:
text
类型统一
内存更省
计算更快
支持向量化运算
86. NumPy 比列表好吗?
做数值计算时,NumPy 更好。
比如:
python
import numpy as np
a = np.array([1, 2, 3])
print(a * 2)
结果:
python
[2 4 6]
列表不能直接这样做数值向量运算。
87. NumPy 数组中 N 个最大值的索引
python
import numpy as np
arr = np.array([1, 3, 2, 4, 5])
print(arr.argsort()[-3:][::-1])
结果是最大 3 个值的索引。
88. NumPy 计算百分位数
python
import numpy as np
a = np.array([1, 2, 3, 4, 5])
p = np.percentile(a, 50)
print(p)
50 分位数就是中位数,结果:
python
3.0
89. NumPy 和 SciPy 区别
NumPy:核心是数组和基础数值计算。
SciPy:建立在 NumPy 上,提供更多科学计算功能,比如优化、积分、信号处理、线性代数等。
90. NumPy/SciPy 做 3D 可视化
NumPy 和 SciPy 本身主要负责计算,不负责高级绘图。
常用:
text
Matplotlib 的 mplot3d
Mayavi
Plotly
三、python中的装饰器:
Python 装饰器本质上是一个函数,它接收另一个函数作为参数,并返回一个新的函数。它的作用是在不修改原函数代码的情况下,给原函数增加额外功能,比如日志记录、权限校验、计时、缓存等。
@decorator这种写法只是语法糖,本质上等价于func = decorator(func)。
下面的代码例子:
把 say_hello 这个函数交给 my_decorator 包装一下,然后用包装后的新函数替换原来的 say_hello。
python
def my_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
这段代码等价于下面这样写:
python
def my_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
def say_hello():
print("Hello!")
say_hello = my_decorator(say_hello)
say_hello()
重点在这一句:
python
say_hello = my_decorator(say_hello)
原来的 say_hello 函数被传进了 my_decorator:
python
my_decorator(say_hello)
所以在 my_decorator 里面:
python
func
其实就是原来的 say_hello。
问:
为什么func()等于调用原来的等于调用原来的say_hello()。
答:
在 Python 里,函数也可以像普通变量一样被传来传去。
因为函数名本质上是一个变量名,类似于:
python
def say_hello():
print("Hello!")
可以理解成 Python 创建了一个函数对象,然后让名字 say_hello 指向它。
类似于x = 10,这里 x 指向数字 10。
再更简单解释一下装饰器,面试说:
一句话:
- 装饰器本质是一个高阶函数,用来在不修改原函数代码的情况下增强功能,比如日志、计时、权限校验。
下面例子:
@timer 等价于 run = timer(run)
python
import time
from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} cost {time.time() - start:.4f}s")
return result
return wrapper
@timer
def run():
time.sleep(1)
return "done"
四、面试中最重点的 20 几个高频考题
- Python 是解释型、动态类型、面向对象语言。
- list 可变,tuple 不可变。
- dict 是 key-value 结构。
is比较对象身份,==比较值。[::-1]可以反转序列。- Python 用缩进表示代码块。
*args接收多个位置参数,**kwargs接收多个关键字参数。- lambda 是匿名函数。
- 迭代器可以用
next()逐个取值。 - 生成器用
yield,节省内存。 __init__创建对象时自动执行。self代表当前对象。- Python 支持继承、多态、封装。
- 浅拷贝只拷贝外层,深拷贝递归拷贝。
- GIL 让同一时刻只有一个线程执行 Python 字节码。
with open()会自动关闭文件。try-except-else的 else 在没有异常时执行。- Flask 轻量,Django 大而全。
- NumPy 适合数值计算,比列表快。
/是普通除法,//是整除。- 装饰器
- GIL
GIL
GIL 是 CPython 的全局解释器锁,导致同一时刻只有一个线程执行 Python 字节码。所以 CPU 密集型任务用多线程提升有限,更适合多进程;I/O 密集型任务比如网络请求、文件读写,多线程仍然有效,因为等待 I/O 时可以释放执行权。
深拷贝浅拷贝
浅拷贝只复制最外层容器,内部可变对象仍然共享;深拷贝会递归复制内部对象。比如 list 里嵌套 list 时,浅拷贝修改内部 list 会影响原对象。
生成器 / yield
生成器是惰性计算的迭代器,使用 yield 返回值并保存函数执行状态,适合处理大文件、流式数据、训练数据逐批加载等场景。
__new__ 和 __init__
__new__负责创建对象,返回实例;__init__负责初始化对象属性。单例模式会用到__new__控制只创建一个实例。
1. 装饰器
一句话:
装饰器本质是一个高阶函数,用来在不修改原函数代码的情况下增强功能,比如日志、计时、权限校验。
代码模板:
python
import time
from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} cost {time.time() - start:.4f}s")
return result
return wrapper
@timer
def run():
time.sleep(1)
return "done"
面试重点不是代码多复杂,而是你要说出:
@timer等价于run = timer(run)。
2. GIL
一句话:
GIL 是 CPython 的全局解释器锁,保证同一时刻只有一个线程执行 Python 字节码。
怎么答应用场景:
| 场景 | 用什么 |
|---|---|
| CPU 密集型,比如大规模计算、图像处理 | 多进程 |
| I/O 密集型,比如网络请求、文件读写 | 多线程/异步 |
| 深度学习训练 | 主要靠 GPU 并行,不是 Python 多线程 |
你可以结合自己项目说:
我在训练和推理项目里更多遇到的是 GPU、CUDA、dtype、数据加载和进程管理问题,真正计算密集部分一般由 PyTorch 底层 C++/CUDA 执行。
3. 深拷贝和浅拷贝
一句话:
浅拷贝只复制最外层对象,内部嵌套的可变对象仍然共享;深拷贝会递归复制所有层级。
例子:
python
import copy
a = [[1, 2], [3, 4]]
b = copy.copy(a)
c = copy.deepcopy(a)
a[0].append(99)
print(b) # [[1, 2, 99], [3, 4]]
print(c) # [[1, 2], [3, 4]]
4. 生成器和 yield
一句话:
生成器是一种惰性迭代器,用
yield返回数据,并保存函数执行状态。
适用场景:
| 场景 | 为什么适合生成器 |
|---|---|
| 读取大文件 | 不一次性加载到内存 |
| 训练数据加载 | 按 batch 逐步产生 |
| 流式处理 | 边生成边消费 |
简单代码:
python
def my_range(n):
for i in range(n):
yield i
for x in my_range(3):
print(x)
5. __new__ 和 __init__
一句话:
__new__负责创建对象,__init__负责初始化对象。
python
class A:
def __new__(cls, *args, **kwargs):
print("create object")
return super().__new__(cls)
def __init__(self):
print("init object")
常见追问是单例模式:
python
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
6. 异常处理顺序
记住这个顺序:
python
try:
print("可能出错的代码")
except Exception:
print("出错时执行")
else:
print("没出错时执行")
finally:
print("无论是否出错都执行")
一句话:
else只有没有异常时执行,finally无论是否异常都会执行,常用于释放资源。
7. 垃圾回收
一句话:
Python 主要使用引用计数,辅以标记清除和分代回收,解决循环引用等问题。
你能答到这个程度就够了:
| 机制 | 作用 |
|---|---|
| 引用计数 | 对象引用数为 0 时回收 |
| 标记清除 | 处理循环引用 |
| 分代回收 | 新对象频繁检查,老对象降低检查频率 |