Python牛客总结面试题

5 阅读21分钟

二、Python高频考点目录

  1. Python基本数据结构有哪四种?区别是什么
  2. Python数据类型
  3. Break和Continue区别
  4. Python return和yield的区别,以及return的作用
  5. Python深拷贝和浅拷贝区别
  6. range和xrange的区别
  7. is==的区别
  8. 什么是lambda函数
  9. 字符串拆分方法有哪些
  10. 单引号、双引号、三引号区别
  11. Python传参时需要注意什么
  12. 装饰器
  13. 函数或变量的作用域
  14. 解释型和编译型语言的区别
  15. __init____new__的区别
  16. 常用的模块
  17. Python的list和numpy.array(数组)的区别
  18. 类中self的概念及其三种应用
  19. Python的几种变量,按照作用域划分
  20. Python的面向对象特征

三、Python高频考点解答

3.1 Python基本数据结构及其区别,应用场景分别是什么,代码展现

3.1.1 Python基本数据结构有哪四种?区别是什么
  • list

    • 有序可修改。
    • 通过索引进行查找、切片。使用方括号 [ ] 表示;
  • tuple

    • 有序不可修改。
    • 可查询、切片操作。
    • 元组将多样的对象集合到一起,通过索引进行查找。用小括号 ( ) 表示;
  • set

    • 集合,无序可修改,无重复,无索引,不能跟列表一样切片。
    • 自动去重。
    • 使用 set([ ]) 表示;
  • dict

    • 字典是一组 key-value,通过 key 查找,无顺序(Python 3.7+ 保持插入顺序),用 { } 表示。
3.1.2 应用场景分别是什么
  • list:简单的数据集合,可用索引;
  • tuple:把一些数据当作整体去用,不能修改;
  • dict:使用 key,value 进行关联的数据;
  • set:数据无重复,只关心数据是否出现,不关心位置。
3.1.3 代码展现
mylist = [1, 2, 3, 4, 'oh']
mytuple = (1, 2, 'Hello', (4, 5))
mydict = {'wang': 1, 'Hu': 2, 'Liu': 3}
myset = set(['wang', 'Hu', 'Liu', 4, 'wa'])

3.2 Python数据类型

  1. String(字符串)

  2. Number(数字型)

    • int(整型)
    • float(浮点型)
    • complex(复数)
    • long(长整数,Python 3 中已合并到 int)
  3. List(列表)

  4. Tuple(元组)

  5. Dictionary(字典)

  6. Set(集合)


3.3 Break和Continue区别

  • break:用于结束整个循环。
  • continue:不执行当前循环的 statement,运行下一个循环。

3.4 Python return和yield的区别,以及print和return的作用

3.4.1 Python return和yield的区别
  • 相同点:都是返回函数执行的结果。

  • 不同点

    • return 在返回结果后结束函数的运行,返回到调用处继续执行。
    • yield 则是让函数变成一个生成器,生成器每次产生一个值(yield 语句),函数被冻结,被唤醒后再产生一个值。
3.4.2 yield生成器相比return一次返回所有结果的优势
  • 反应更迅速
  • 更节省空间
  • 使用更灵活
3.4.3 print和return作用
  • print:作用是输出数据到控制端,就是打印在你能看到的界面上。
  • return:作用之一是返回计算的值。

3.5 Python深拷贝和浅拷贝区别

  • 浅拷贝:是在另一块地址中创建一个新的变量或容器,但是容器内的元素的地址均是源对象的元素的地址的拷贝。也就是说新的容器中指向了旧的元素(新瓶装旧酒)。
  • 深拷贝:完全拷贝了一个副本,容器内部元素地址都不一样。

3.6 range和xrange的区别,Range函数用法

3.6.1 range和xrange的区别
  • Python 2

    • range():生成一个 list,是一个列表生成式。
    • xrange():是一个生成器。
  • Python 3

    • 取消了 xrange(),内置的 range() 实际就是 Python 2 里的 xrange(),返回生成器。
3.6.2 Range函数用法
  • 返回一系列连续增加的整数
  • 工作方式类似于分片
  • 可生成一个列表对象(Python 3 中返回的是 range 对象,可迭代)
3.6.3 range代码
alist = range(0, 101)  # range生成 0-100 列表
print(alist)   # 输出结果 [0, 1, 2,.... 100] (Python 2) 或 range(0, 101) (Python 3)

blist = range(2, 101, 2)  # 设置步长为 2
print(blist)  # 输出结果 [2, 4, 6,..... 100] (Python 2) 或 range(2, 101, 2) (Python 3)

3.7 is==的区别

  • is:判断两个对象的内存地址是否相同。
  • ==:判断两个对象的值是否相同。

3.8 什么是lambda函数

  • 匿名函数形式:f = lambda x : x表达式
  • 调用时可采用 f(x) 的形式 或者直接使用(可以用于 return 语句)
  • 优点:没有名字,无需担心函数冲突
  • 缺点:只能有一个表达式,没有 return,返回值就是该表达式的结果

3.9 字符串拆分方法有哪些

  • 方法一:String 对象的 split 方法,不允许有多个分隔符
  • 方法二:函数 re.split(),允许为分隔符指定多个正则模式
line = "I am super man!"
# String的split方法
print(line.split(" "))  # 以空格拆分 输出 ['I', 'am', 'super', 'man!']

# re.split方法
import re
print(re.split("[m]", line))  # 输出 ['I', 'a', '', 'super', '', 'an!']

3.10 单引号、双引号、三引号区别

  • 单引号双引号没有区别,都可以用来表示字符串;
  • 三引号,字符串内可直接换行,且可包含注释。
# 若要表示 Let's go 这个字符串
# 单引号:s1 = 'Let' s go'  # 会报错
# 双引号:s2 = "Let's go"
# 三引号:s3 = '''I realy like "Python"!'''

3.11 Python传参时需要注意什么

3.11.1 传入参数是否可以被修改
  • 如果没有将外部变量传递到函数来(参数定义中包含该外部变量),则函数内部虽然可以使用,但是不能对该变量进行修改(会报错)——未传参的变量可使用但不可修改。

  • 将外部变量作为实参传递到函数中来的话:

    • 如果外部变量是不可变对象的话不可以修改该变量的原始值——相当于"传值"的方式来传递变量,可以通过改变引用指向的方式,在函数内部获取新的不可变对象,但是对函数外部没有影响(除非加了 global)。
    • Python 函数传入的是原变量引用的一个副本,这两个引用(副本及原引用)在内外均指向同一个内存区。
    • 如果在函数内部改变了引用指向的话,只是副本引用指向了一个新的内存区,函数外面的引用仍然指向原内存堆区,不会改变原变量的值(不可变对象的操作、可变对象的赋值操作)。
    • 而如果在内部通过 appendremove 函数改变了堆区的值的话,外部的引用仍然会改变。
3.11.2 传入参数的顺序和类型
  • 参数顺序:必选参数,默认参数,可变参数,命名关键字参数,关键字参数
  • 可变参数必须在关键字参数之前
  • 默认参数:必须指向不可变对象
  • 可变参数:形式 def func(*可变参数),传入参数的个数可以是 0 个或者多个,其实是传入一个 list 或者 tuple,函数接收的是个 tuple。如果有个 list 或者 tuple 想直接传入 func 的话,可以直接用 func(*list) 实现。
  • 关键字参数:形式 def func(**关键字参数),允许传入 0 个或多个含参数名的参数,在函数内部组装成字典。传入的时候用 参数名=参数值 的形式。如果传入 dict 的话可以直接 func(**dict)
  • 命名关键字参数:形式 def func(*, city, job),限制某几种参数名的输入,传入的时候必须只有 , 后面的这几种参数名可以选择,传入用 fun(city=xxx, job=xxx) 的形式。
3.11.3 补充:可变对象与不可变对象总结
  • 可变对象:list、dict、set。

    • 可变对象是指对象的内存值可以改变。
  • 不可变对象:int、tuple、str、bool。

    • 不可变对象是指对象的内存值不可以被改变。
    • 改变变量时,其实质是变量指向新的地址,即变量引用新的对象。

3.12 装饰器

  • 装饰器可以在不改变函数代码和调用方式的情况下给函数添加新的功能。
  • 本质上是一个嵌套函数,接收被装饰的函数 (func) 作为参数,并返回一个包装过的函数,以实现不影响函数的情况下添加新的功能。
  • 抽离出大量与函数主体功能无关的代码,增加一个函数的重用性。
  • 应用场景:性能测试(统计程序运行时间)、插入日志、权限校验。

3.13 函数或变量的作用域

  • 正常的函数/变量是 public 的,可以被直接引用,如 x123PI 等。
  • __xxx__ 变量/函数是特殊变量,虽可以被直接引用,但是有特殊的用途,比如说 __init__, __new__ 等。
  • _xxx 表示半私有的变量,只能在类或者子类内使用。
  • __xxx 表示私有的变量,只能在类内使用。
  • 这两种私有变量都是应当私有,而不是一定不能访问的。

3.14 解释型和编译型语言的区别

3.14.1 编译型语言
  • 在程序执行前,需要把源代码编译成机器语言的文件,再执行时可以直接使用该编译结果,以后不需要再次编译。
  • 优点:运行效率高
  • 缺点:难以移植
3.14.2 解释型语言
  • 代码执行时才一行行动态翻译执行。
  • 优点:无需编译器,方便程序移植;可以交互式运行。
  • 缺点:运行效率较低。

3.15 __init____new__的区别

  • 相同点:两者都是类中的特殊方法。

  • 不同点

    • __new__

      • 是在实例创建之前被调用的。
      • 任务是创建实例然后返回该实例对象。
      • 是个静态方法,至少要有一个参数 cls(代表当前类)。
      • 必须有返回值(即该实例对象)。
    • __init__

      • 是在实例创建完成后被调用的。
      • 设置对象属性的一些初始值,通常用在初始化一个类实例的时候。
      • 是一个实例方法,至少有一个参数 self (代表当前的实例)。
      • 无需返回值。
  • __init____new__ 之后被调用,__new__ 的返回值(实例)传递给 __init__ 的第一个参数,然后由 __init__ 设置一些实例的参数。

  • 此外,继承自 object 的类才有 __new__,如果定义子类的时候没有定义 __new__,则会追溯到父类的 __new__ 方法来构造该类实例,如果父类也未定义,则一直可以向上追溯到 object 的 __new__ 方法。


3.16 常用的模块

  • os:与操作系统交互

  • sys:系统相关

  • random:生成伪随机数

  • time:可以读取时间戳或程序暂停

  • collections:提供常见的数据结构如

    • 双向队列 deque、计数器 Counter、默认字典 defaultdict

3.17 Python的list和numpy.array(数组)的区别

  • list

    • 可以存放不同类型的数据,比如 int, str, bool, float, list, set 等。
    • 每个元素的大小可以相同,也可以不同,因此不支持一次性读取一列。
    • 数据类型保存的是数据存放的地址,即指针而非数据。比如一个有四个数据的列表 a=[1,2,3,4] 需要 4 个指针和 4 个数据,增加了存储空间,消耗 CPU。
    • 每个元素是一个地址的引用,这个地址又指向了另一个元素,这些元素在内存里不一定是连续的,因此每当加入新元素,其实只是把这个元素的地址添加到 list 中。
  • numpy.array

    • 存放的数据类型必须全部相同,必须全为 int 或全为 float。
    • 每个元素大小相同,支持一次性读取一列。对二维数组的操作更为便捷。
    • 只需要存放数据本身,节省内存,方便读取和计算。
    • 是内存中的一个连续块,array 中的元素都是同一类型的,所以一旦确定了一个 array,它的内存就确定了,每个元素的内存大小都确定了。

3.18 类中self的概念及其三种应用

  • self 代表实例本身,具体来说是该实例的内存地址。
3.18.1 self的三种应用
  1. self 为类中函数的第一个参数

    • 在调用实例方法时,python 解释器会自己把实例变量传递给函数中的 self。
    • 如果类的实例方法的第一个参数不是代表实例的 self,则调用实例方法时,该方法没有参数来接收自动传入的实例变量,程序会产生异常。
  2. 在类中,引用实例的属性 self.变量名

    • 引用实例的属性目的是为实例绑定属性,写入或读取实例的属性。
  3. 在类中,调用实例的方法 self.方法名()


3.19 Python的几种变量,按照作用域划分

  • 全局变量:在模块内、在所有函数之外、在 class 外。

  • 局部变量:在函数内、在 class 的方法内(但未加 self 修饰)。

  • 静态变量/类属性:在 class 内,但是不在 class 的方法内的。

    • 类的所有实例均可以访问到该类属性,用 类名。变量名 的方式。
  • 实例变量/实例属性:在 class 的方法内,用 self 修饰的变量。

    • 实例属性的优先级高于类属性,所以若是同名,实例属性会覆盖类属性,优先输出实例属性。

3.20 Python的面向对象特性

  1. 封装
  2. 继承
  3. 多态
3.20.1 面向对象和面向过程语言的区别
  • 面向对象

    • 把问题抽象成一个个对象,给这些对象绑上属性和方法,即以功能而非步骤划分问题。
    • 优点:更易低耦合、易维护、易复用。
    • 缺点:因为需要实例化所以开销较大,性能比面向过程要低。
  • 面向过程

    • 把问题拆分成一个个函数和数据,按照一定的顺序来执行这些方法。
    • 优点:性能较高。
    • 缺点:不易维护,不易复用。

=========

测试秋招八股文集锦——Python高频考点详解

作者:是小婷婷吖
来源:牛客网讨论帖
整理时间:2024年
标签:#面经 #秋招 #测试开发 #Python #面试八股文


📝 目录

  1. Python基本数据结构
  2. Python数据类型
  3. Break和Continue区别
  4. Return和Yield的区别
  5. 深拷贝和浅拷贝
  6. Range和Xrange的区别
  7. Is和==的区别
  8. Lambda函数
  9. 字符串拆分方法
  10. 引号的区别
  11. Python传参注意事项
  12. 装饰器
  13. 作用域
  14. 解释型与编译型语言
  15. initnew的区别
  16. 常用模块
  17. List和Numpy.array的区别
  18. Self的概念及应用
  19. 变量按作用域划分
  20. 面向对象特征
  21. 评论区争议与澄清

1. Python基本数据结构

1.1 四种基本数据结构及区别

数据结构有序性可变性重复性索引/切片表示符号
List (列表)✅ 有序✅ 可修改✅ 可重复✅ 支持[ ]
Tuple (元组)✅ 有序❌ 不可修改✅ 可重复✅ 支持( )
Set (集合)❌ 无序*✅ 可修改❌ 无重复❌ 不支持set([ ])
Dict (字典)✅ 有序(Python 3.7+)✅ 可修改Key唯一✅ 通过Key查找{ }

*注:关于Set的有序性存在争议,详见文末评论区争议。理论上Set是无序的,不能通过下标访问。

1.2 应用场景

  • List:适用于简单的数据集合,需要通过索引快速查找或修改数据的场景。
  • Tuple:适用于将一组数据当作整体使用,且数据不允许被修改的场景(如配置项、数据库记录)。
  • Dict:适用于需要通过键(Key)快速关联和查找值(Value)的场景。
  • Set:适用于数据去重,或只关心数据是否存在而不关心位置的场景。

1.3 代码示例

mylist = [1, 2, 3, 4, 'oh']
mytuple = (1, 2, 'Hello', (4, 5))
mydict = {'wang': 1, 'Hu': 2, 'Liu': 3}
myset = set(['wang', 'Hu', 'Liu', 4, 'wa'])

2. Python数据类型

Python主要包含以下6种标准数据类型:

  1. String (字符串)

  2. Number (数字型)

    • int (整型)
    • float (浮点型)
    • complex (复数)
    • long (长整数,Python 3中已合并至 int)
  3. List (列表)

  4. Tuple (元组)

  5. Dictionary (字典)

  6. Set (集合)


3. Break和Continue区别

  • break:用于完全结束整个循环,跳出循环体,执行循环后的代码。
  • continue:用于跳过当前循环的剩余语句,直接进入下一次循环的判断。

4. Return和Yield的区别

4.1 核心区别

特性returnyield
功能返回结果并终止函数运行返回结果并暂停函数运行(生成器)
返回值返回具体值返回一个生成器对象
状态保持不保持,下次调用重新执行保持,下次调用从暂停处继续执行
内存占用一次性加载所有数据,占用大按需生成,节省内存

4.2 Yield的优势

  • 反应迅速:不需要等待所有数据计算完成即可开始处理。
  • 节省空间:适合处理大规模数据流。
  • 使用灵活:可实现协程等高级功能。

4.3 Print和Return的作用

  • print:将数据输出到控制台(标准输出),仅供查看,无法在程序中进一步使用该返回值。
  • return:将计算结果返回给调用者,可在程序中继续参与运算或赋值。

5. 深拷贝和浅拷贝

  • 浅拷贝 (Shallow Copy)

    • 创建一个新的容器对象。
    • 容器内的元素仍然是原对象元素的引用(地址相同)。
    • 修改容器内可变元素会影响原对象。
    • 比喻:新瓶装旧酒。
  • 深拷贝 (Deep Copy)

    • 递归复制对象及其内部所有子对象。
    • 新对象与原对象完全独立,内存地址完全不同。
    • 修改新对象不会影响原对象。

6. Range和Xrange的区别

6.1 版本差异

  • Python 2:

    • range(): 直接生成一个列表(List),占用内存较大。
    • xrange(): 生成一个生成器(Generator),按需生成数据,节省内存。
  • Python 3:

    • 取消了 xrange()
    • range() 的行为等同于 Python 2 的 xrange(),返回一个可迭代的 range 对象。

6.2 用法示例

# 生成 0-100 的序列
alist = range(0, 101) 

# 设置步长为 2,生成偶数序列
blist = range(2, 101, 2) 

7. Is和==的区别

  • is:判断两个对象的内存地址是否相同(即是否是同一个对象)。
  • ==:判断两个对象的是否相等。
a = [1, 2]
b = [1, 2]
c = a

print(a == b)  # True (值相等)
print(a is b)  # False (地址不同)
print(a is c)  # True (地址相同)

8. Lambda函数

  • 定义:匿名函数,形式为 f = lambda x: x表达式

  • 特点

    • 没有函数名,避免命名冲突。
    • 只能包含一个表达式,自动返回该表达式的结果(无需写 return)。
  • 适用场景:常用于作为参数传递给高阶函数(如 map, filter, sorted)。


9. 字符串拆分方法

  1. String.split()

    • 字符串内置方法。
    • 只能使用单一分隔符。
    line = "I am super man!"
    print(line.split(" "))  # ['I', 'am', 'super', 'man!']
    
  2. re.split()

    • 正则表达式模块方法。
    • 支持多个分隔符或复杂的正则模式。
    import re
    print(re.split("[m]", line))  # 以字符'm'拆分
    

10. 引号的区别

  • 单引号 ' ' 和 双引号 " "

    • 功能完全相同,均可表示字符串。
    • 方便互相嵌套(如 "Let's go"'He said "Hello"')。
  • 三引号 ''' '''""" """

    • 支持多行字符串,保留换行符。
    • 常用于文档字符串(Docstring)或包含大量换行的文本。

11. Python传参注意事项

11.1 可变与不可变对象

  • 不可变对象 (int, str, tuple, bool):

    • 传参类似“传值”。
    • 函数内部修改会创建新对象,不影响外部变量。
  • 可变对象 (list, dict, set):

    • 传参类似“传引用”。
    • 函数内部通过 append, remove 等方法修改内容,会影响外部变量。
    • 若直接赋值(=),则指向新对象,不影响外部。

11.2 参数类型与顺序

定义函数时参数顺序:必选参数 > 默认参数 > 可变参数 > 命名关键字参数 > 关键字参数

  • 默认参数:必须指向不可变对象(避免陷阱)。
  • 可变参数 (*args) :接收任意个位置参数,组装成 Tuple。
  • 关键字参数 (** kwargs):接收任意个关键字参数,组装成 Dict。
  • 命名关键字参数:限制传入的参数名,必须通过 key=value 形式传入。

12. 装饰器 (Decorator)

  • 定义:本质是一个高阶函数,接收一个函数作为参数,返回一个新的函数。

  • 作用:在不修改原函数代码和调用方式的前提下,为函数添加额外功能。

  • 常见应用

    • 日志记录
    • 性能测试(统计运行时间)
    • 权限校验
    • 事务处理

13. 函数或变量的作用域

  • Public (公有) :正常命名的变量/函数(如 x123, PI),可直接引用。
  • Special (特殊) :双下划线开头和结尾(如 __init__, __new__),有特殊用途。
  • Protected (半私有) :单下划线开头(如 _var),约定只能在类或子类内部使用。
  • Private (私有) :双下划线开头(如 __var),只能在类内部使用(名称改写机制)。

14. 解释型与编译型语言的区别

特性编译型语言 (C, C++, Go)解释型语言 (Python, JavaScript)
执行方式源代码先编译成机器码,再执行运行时逐行翻译执行
优点运行效率高跨平台性好,开发调试灵活
缺点移植性差,需针对不同平台编译运行效率相对较低

15. initnew的区别

特性newinit
调用时机实例创建之前实例创建之后
作用创建并返回实例对象初始化实例属性
类型静态方法 (Static Method)实例方法 (Instance Method)
参数至少包含 cls (类)至少包含 self (实例)
返回值必须返回实例对象无需返回值 (返回None)

执行流程__new__ 先执行并返回实例 -> 该实例传给 __init__self -> __init__ 进行初始化。


16. 常用模块

  • os:与操作系统交互(文件路径、环境变量等)。
  • sys:系统相关参数和函数(命令行参数、退出程序等)。
  • random:生成伪随机数。
  • time:时间处理(时间戳、休眠等)。
  • collections:扩展数据结构(deque双向队列, Counter计数器, defaultdict默认字典)。

17. List和Numpy.array的区别

特性Python ListNumpy Array
数据类型可混合存放不同类型 (int, str, object等)必须全部相同 (全int或全float)
内存存储存储元素的地址指针,内存不连续存储实际数据值,内存连续
空间效率较低 (需额外存储指针)高 (紧凑存储)
计算效率低 (循环操作)高 (支持向量化运算)
功能基础列表操作强大的矩阵/数组运算

18. Self的概念及应用

  • 概念self 代表类的实例本身(即对象的内存地址)。

  • 三种应用

    1. 方法定义:作为实例方法的第一个参数,接收调用该方法的实例对象。
    2. 访问属性:在类内部通过 self.variable 读写实例属性。
    3. 调用方法:在类内部通过 self.method() 调用其他实例方法。

19. 变量按作用域划分

  1. 全局变量:模块级别,函数和类之外定义。
  2. 局部变量:函数内部或类的方法内部(未加 self)定义。
  3. 类属性 (静态变量) :类内部、方法之外定义。所有实例共享,通过 类名.变量 访问。
  4. 实例属性:方法内部通过 self.变量 定义。每个实例独有,优先级高于类属性。

20. 面向对象特征

三大特征:封装、继承、多态

面向对象 vs 面向过程

维度面向对象 (OOP)面向过程 (POP)
核心思想将问题抽象为对象,关注“谁来做”将问题拆解为步骤,关注“怎么做”
优点易维护、易复用、低耦合性能较高,流程直观
缺点实例化开销大,性能略低不易维护,难以应对复杂变化

21. 评论区争议与澄清

原文发布后,在评论区引发了一些关于技术细节的讨论,以下是重点澄清:

争议点 1:Set 是否有序?

  • 用户质疑:有用户认为 Set 是有序的。

  • 作者及社区澄清

    • 理论定义:Set 在理论上是无序的,不支持索引访问。
    • 实际表现:在 Python 3.7+ 的某些实现中,遍历 Set 时可能表现出“看似有序”(通常是插入顺序或哈希顺序),但这属于实现细节,不能依赖
    • 面试建议:回答“无序”是标准答案,回答“有序”可能会被视为基础不牢。

争议点 2:Tuple 是否有序?

  • 澄清:Tuple 是有序的。原文曾笔误写错,已更正。

争议点 3:Number 和 Long 类型是否存在?

  • 用户质疑:Python 基础类型不存在 Number 和 Long。

  • 作者澄清

    • Number:是 Python 文档中定义的数值类型的总称(抽象基类),包含 int, float, complex, bool。
    • Long:在 Python 2 中存在独立的 long 类型;在 Python 3 中,intlong 已合并,统一为 int(无限精度整数),但概念上仍属于数值类型体系。

结语:本文整理了测试开发秋招中Python方向的高频面试题。除了上述内容,进程、线程、协程也是面试中的重中之重,建议另行深入复习。祝各位求职者 Offer 多多!