写在之前
Python 面试的时候会涉及到很多的八股文,我准备连载一个新的系列【最新Python面试题】
这些面试题是我结合自身经验,以及搜集整理的企业面试真题,主要有以下几个方面:
- Python基础
- Python机制
- Python面向对象
- Python笔试题
- Python算法
- Django框架
- Flask框架
- 其他开源框架
- Scrapy数据爬虫
- Python正则式
- Python数据分析
- Pandas框架
- Python拓展知识(数据结构,常见算法,数据库原理及调优,中间件…)
虽然这些是面试“八股文”,但是只会背答案与流畅的并能结合自身思考的回答,对于面试官来说还是有很大区别的。
所以除了在每道面试题后会提供仔细整理和验证后的答案以外,在每篇文章中会挑选一道难度高且重点的题目做详细的讲解。
希望大家不但能知其然也可以知其所以然,在面试的时候让面试官眼前一亮,这样白花花的offer不就到手了嘛
每天会更新10道题左右,无论是准备面试还是自己学习,这份面试题绝对值得你去看
大家可以关注我,再关注我,使劲关注我,不要错过每天的更新~
1.解释 Python 类变量和实例变量?
- 类变量(Class Variable):定义在类层级,由类的所有实例共享。它们属于类,而不是类的任何特定对象。
- 实例变量(Instance Variable):定义在类的
__init__
方法中,每个实例都有自己的独立副本。它们属于对象个体,每个对象的值可以不同。 - 总结:类变量是共享的,修改一个实例的类变量会影响所有实例;实例变量是独立的,每个对象可以有自己的值。类变量通常用于常量或所有实例都需要访问的共享数据,而实例变量用于存储每个对象特有的数据。
2.阐述Python 新式类和旧式类?
- 旧式类(Classic Classes):也称为经典类,是在 Python 2.x 版本中使用的类定义方式。它们继承自
object
的基类,或者不显式继承任何类。 - 新式类(New-style Classes):是在 Python 2.2 中引入的,并且在 Python 3.x 中成为唯一的类类型。所有新式类都隐式地继承自
object
类,这使得它们支持更多的特性,如描述符协议、属性访问控制等。 - 区别:新式类和旧式类的主要区别在于它们如何处理方法解析顺序(MRO)和属性访问。新式类提供了更一致和强大的行为,特别是在处理继承和属性时。
- 迁移:在 Python 3.x 中,所有的类都是新式类。如果你从 Python 2.x 迁移代码到 Python 3.x,你需要确保所有的类都继承自
object
,以避免兼容性问题。
3.__new__和__init__的区别?
__new__
负责创建对象,__init__
负责初始化对象。__new__
可以被继承的类重写以控制对象的创建过程,而__init__
通常被用来设置对象的状态或行为。__new__
必须返回一个类的新实例,而__init__
不需要返回值。
4.Python中的作用域是什么?
在 Python 中,作用域(Scope)是指变量和对象能够被访问的上下文区域。Python 有几种类型的作用域,它们决定了变量的可见性和生命周期:
- 局部作用域(Local scope):在函数或方法内部定义的变量,只能在该函数或方法内部访问。
- 嵌套作用域(Nested scope):在函数内部定义的函数(闭包)可以访问包含函数的局部变量。
- 全局作用域(Global scope):在模块或脚本的最顶层定义的变量,在整个模块或脚本的任何位置都可以访问。
- 内置作用域(Built-in scope):包含 Python 内置函数和变量的作用域,如
len()
、str()
等。 - 类作用域(Class scope):在类定义内部,但在方法外部定义的变量,可以被类的所有方法访问。
- 命名空间(Namespace):Python 使用命名空间来存储变量名和对象的引用,每个作用域都有自己的命名空间。
5.简述什么是Python函数式编程?
Python 函数式编程是一种编程范式,它将计算视为数学函数的评估,并避免状态和可变数据。在 Python 中,函数式编程的特点包括:
- 不可变数据:函数式编程倾向于使用不可变的数据结构,这意味着一旦创建,数据就不能被改变。
- 纯函数:函数不依赖于外部状态,也没有副作用,相同的输入总是产生相同的输出。
- 高阶函数:函数可以作为参数传递给其他函数,或者作为其他函数的返回结果。
- 函数组合:函数可以组合起来形成新的函数,以实现更复杂的操作。
- 使用迭代器和生成器:函数式编程经常使用迭代器和生成器来处理数据集合,这些可以是无限的数据流。
- 避免副作用:函数调用不改变程序的状态,所有外部修改(如文件操作、数据库更新等)都被视为副作用。
- 列表推导式和生成器表达式:Python 提供了列表推导式和生成器表达式等语法糖,使得函数式编程更加简洁和高效。
- 内置函数支持:Python 的标准库提供了许多支持函数式编程的函数,如
map()
、filter()
和reduce()
。
6.Python的is的含义?
在 Python 中,is
操作符用于检查两个变量是否引用同一个对象,即它们是否指向内存中的同一个位置。
7.Python中read,readline和readlines的区别 ?
read(size)
: 从文件中读取指定数量的字节,直到文件末尾或达到指定的字节数,返回读取的内容。readline(size)
: 从文件中读取一行,直到换行符或达到指定的字节数,返回读取的行,包括换行符。readlines()
: 读取文件的所有行,将它们作为字符串列表返回,不包括行之间的换行符。
8.Python中pass语句的作用是什么?
在 Python 中,pass 是一个空操作语句,它不做任何事情。pass 通常用作占位符,当语法上需要一条语句但程序逻辑不需要执行任何操作时,就会使用 pass。
- Python如何按字母顺序对字典排序?
#字典结构是无序的,可以按顺序输出,但无法对字典进行排序
d = {'c':3, 'd':4, 'b':2, 'a':1}
sorted(d.items())
#=> [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
重点题详解
是否遇到过python的模块间循环引用的问题,如何避免它?
循环引用(Circular Import)在 Python 中是指两个或多个模块相互导入对方,形成了一个闭环。这种情况在 Python 中是应该避免的,因为它会导致运行时错误或难以调试的问题。循环引用通常发生在包(目录包含 __init__.py
文件)中,而不是单个文件中。
循环引用的例子:
假设有两个模块 moduleA.py
和 moduleB.py
,它们的内容如下:
moduleA.py
:
import moduleB
def function_a():
print("Function A")
moduleB.function_b()
moduleB.py
:
import moduleA
def function_b():
print("Function B")
moduleA.function_a()
在上面的例子中,moduleA
导入了 moduleB
,而 moduleB
又导入了 moduleA
,形成了循环引用。
循环引用可能导致的问题:
- 导入错误:在某些情况下,Python 解释器可能无法正确解析模块,导致
ImportError
或ModuleNotFoundError
。 - 初始化问题:模块的全局变量和函数可能在被引用前未被完全初始化。
- 运行时错误:在模块执行过程中可能出现未定义或未初始化的错误。
如何避免循环引用:
-
重构代码:重新组织代码结构,避免模块间的直接依赖。例如,可以将共享的功能移动到一个单独的模块中,这样其他模块可以导入这个新的模块,而不是相互导入。
-
延迟导入:在函数或方法内部进行导入,而不是在模块顶部。这样可以在需要时才导入模块,避免在模块初始化时就形成循环。
moduleA.py
:def function_a(): print("Function A") import moduleB moduleB.function_b()
-
使用包:将相关的模块组织在一个包中,并通过包的
__init__.py
文件来协调模块间的依赖关系。 -
设计接口:定义清晰的接口,使得模块之间的依赖关系更加明确,减少不必要的相互依赖。
-
使用事件和回调:在模块间使用事件驱动的方法,通过回调函数来避免直接的导入。
-
使用服务定位器模式:通过一个中心化的服务来管理模块间的依赖关系,而不是让模块直接导入对方。
-
使用依赖注入:在模块间通过参数传递依赖,而不是通过导入语句。
循环引用是代码组织和设计中需要特别注意的问题,通过合理的代码重构和设计模式,可以有效地避免循环引用的发生。
更多资料干货、行业内幕 长期免费更新中!