admin管理员组

文章数量:1630183

大家好呀,我是 Rocky0429。

Python 面试的时候,会涉及到很多的八股文,我结合自己的经验,整理Python 最强面试题

Python 最强面试题主要包括以下几方面:

  • Python 基础(已完成)
  • Python 进阶
  • Python 后台开发
  • 爬虫
  • 机器学习

对每道面试题会附带详细的答案,无论是准备面试还是自己学习,这份面试题绝对值得你去看,去学习。


1、什么是 Python?

Python 是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理,可以加入其他语言的对比。

Python 是一种解释型语言,Python 在代码运行之前不需要解释。

Python 是动态类型语言,在声明变量时,不需要说明变量的类型。

Python 适合面向对象的编程,因为它支持通过组合与继承的方式定义类。

在 Python 语言中,函数是第一类对象。

Python 代码编写快,但是运行速度比编译型语言通常要慢。

Python 用途广泛,常被用走"胶水语言",可帮助其他语言和组件改善运行状况。

使用 Python,程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。

2、赋值、浅拷贝和深拷贝的区别?

(1) 赋值

在 Python 中,对象的赋值就是简单的对象引用,这点和 C++不同,如下所示:

a = [1,2,"hello",['python', 'C++']]
b = a

在上述情况下,a 和 b 是一样的,他们指向同一片内存,b 不过是 a 的别名,是引用。

我们可以使用 b is a 去判断,返回 True,表明他们地址相同,内容相同,也可以使用 id() 函数来查
看两个列表的地址是否相同。

赋值操作(包括对象作为参数、返回值)不会开辟新的内存空间,它只是复制了对象的引用。也就是说除了 b 这个名字之外,没有其他的内存开销。修改了 a,也就影响了 b,同理,修改了 b,也就影响了 a。

(2) 浅拷贝

浅拷贝会创建新对象,其内容非原对象本身的引用,而是原对象内第一层对象的引用。

浅拷贝有三种形式:切片操作、工厂函数、copy 模块中的 copy 函数。

比如上述的列表 a,切片操作:b = a[:] 或者 b = [x for x in a];

工厂函数:b = list(a);

copy 函数:b = copy.copy(a);

浅拷贝产生的列表 b 不再是列表 a 了,使用 is 判断可以发现他们不是同一个对象,使用 id 查看,他们也不指向同一片内存空间。但是当我们使用 id(x) for x in a 和 id(x) for x in b 来查看 a 和 b 中元素的地址时,可以看到二者包含的元素的地址是相同的。

在这种情况下,列表 a 和 b 是不同的对象,修改列表 b 理论上不会影响到列表 a。

但是要注意的是,浅拷贝之所以称之为浅拷贝,是它仅仅只拷贝了一层,在列表 a 中有一个嵌套的 list,如果我们修改了它,情况就不一样了。

比如:a[3].append(‘java’),查看列表 b,会发现列表 b 也发生了变化,这是因为,我们修改了嵌套的 list,修改外层元素,会修改它的引用,让它们指向别的位置,修改嵌套列表中的元素,列表的地址并未发生变化,指向的都是用一个位置。

(3) 深拷贝

深拷贝只有一种形式,copy 模块中的 deepcopy() 函数。

深拷贝和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因此,它的时间和空间开销要高。

同样的对列表 a,如果使用 b = copy.deepcopy(a),再修改列表 b 将不会影响到列表 a,即使嵌套的列表具有更深的层次,也不会产生任何影响,因为深拷贝拷贝出来的对象根本就是一个全新的对象,不再与原来的对象有任何的关联。

(4) 注意点

对于非容器类型,如数字、字符,以及其他的“原子”类型,没有拷贝一说,产生的都是原对象的引用。

如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。

3、init 和__new__的区别?

当我们使用「类名()」创建对象的时候,Python 解释器会帮我们做两件事情:第一件是为对象在内存分配空间,第二件是为对象进行初始化。「分配空间」是__new__ 方法,初始化是__init__方法。

new 方法在内部其实做了两件时期:第一件事是为「对象分配空间」,第二件事是「把对象的引用返回给 Python 解释器」。当 Python 的解释器拿到了对象的引用之后,就会把对象的引用传递给 init 的第一个参数 self,init 拿到对象的引用之后,就可以在方法的内部,针对对象来定义实例属性。

之所以要学习 new 方法,就是因为需要对分配空间的方法进行改造,改造的目的就是为了当使用「类名()」创建对象的时候,无论执行多少次,在内存中永远只会创造出一个对象的实例,这样就可以达到单例设计模式的目的。

4、Python 的变量、对象以及引用?

首先把结论抛出来:

  • 变量是到内存空间的一个指针,也就是拥有指向对象连接的空间;

  • 对象是一块内存,表示它们所代表的值;

  • 引用就是自动形成的从变量到对象的指针。

以下是具体解释:

在 Python 中使用变量的时候不需要提前声明变量及其类型,变量还是会正常工作。在 Python 中,这个是以一种非常流畅的方式完成,下面以 a = 1 为例我们来看一下它到底是个什么情况。

首先是怎么知道创建了变量:对于变量 a,或者说是变量名 a,当程序第一次给它赋值的时候就创建了它,其实真实情况是 Python 在代码运行之前就先去检测变量名,我们不去具体深究这些,你只需要当作是「最开始的赋值创建了变量」。

再者是怎么知道变量是什么类型:其实这个很多人都没有搞清楚,「类型」这个概念不是存在于变量中,而是存在于对象中。变量本身就是通用的,它只是恰巧在某个时间点上引用了当时的特定对象而已。就比如说在表达式中,我们用的那个变量会立马被它当时所引用的特定对象所替代。

上面这个是动态语言明显区别于静态语言的地方,其实对于刚开始来说,如果你适应将「变量」和「对象」分开,动态类型你也就可以很容易理解了。

我们还是以 a = 1 为例,其实从上面的讲述中,我们很容易的可以发现对于 a = 1 这个赋值语句 Python 是如何去执行它的:创建一个代表值 1 的对象 --> 创建一个变量 a --> 将变量 a 和对象 1 连接。 下面我用一个图来更清晰的表示一下:

由上图我们可以看出,变量 a 其实变成了对象 1 的一个引用。如果你学过指针的话,你就会发现在内部「变量其实就是到对象内存空间的一个指针」。

同样还是上图,我们还可以看出在 Python 中「引用」是从变量到对象的连接,它就是一种关系,在内存中以指针的形式实现。

另外,我也打包成 PDF 方便阅读。

5、创建百万级实例如何节省内存?

可以定义类的 slot 属性,用它来声明实例属性的列表,可以用来减少内存空间的目的。

具体解释:

首先,我们先定义一个普通的 User 类:

class User1:
    def __init__(self, id, name, sex, status):
        self.id = id
        self.name = name
        self.sex = sex
        self.status = status

然后再定义一个带 slot 的类:

class User2:
    __slots__ = ['id', 'name', 'sex', 'status']
    def __init__(self, id, name, sex, status):
        self.id = id
        self.name = name
        self.sex = sex
        self.status = status

接下来创建两个类的实例:

u1 = User1('01', 'rocky', '男', 1)
u2 = User1('02', 'leey', '男', 1)

我们已经知道 u1 比 u2 使用的内存多,我们可以这样来想,一定是 u1 比 u2 多了某些属性,我们分别来看一下 u1 和 u2 的属性:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'id', 'name', 'sex', 'status']
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '

本文标签: 面试题最强答案基础Python