一.对象引用与垃圾回收
Q 1.1.深拷贝和浅拷贝之间的区别是什么?
Python中变量之间的赋值是按引用传递的
浅拷贝创建一个新的变量,是对引用的拷贝,新的变量会指向了旧变量值的地址。
深拷贝完全拷贝了一个副本,值也是一样的,但是变量指向值的地址不一样,与旧变量是独立存在的。
Q1.2.简要描述Python的垃圾回收机制(garbage collection)
Python中的垃圾回收是以引用计数为主,标记-清除和分代收集为辅。
引用计数:Python在内存中存储每个对象的引用计数,如果计数变成0,该对象就会消失,分配给该对象的内存就会释放出来。优点是简单,具有实时性,缺点是消耗计算资源,慢,无法处理循环引用。
标记-清除:一些容器对象,比如list、dict、tuple等可能会出现引用循环,对于这些循环,python加入了一种链表持续追踪活跃的容器对象,随后Python会循环遍历零代列表上的每个对象,检查列表中每个互相引用的对象,根据规则减掉其引用计数。
分代收集:Python把内存根据对象存活时间划分为三代,对象创建之后,垃圾回收器会分配它们所属的代。也就是说,活得越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。那么如何来衡量这个存活时间:通常是利用几次垃圾收集动作来衡量,如果一个对象经过的垃圾收集次数越多,可以得出:该对象存活时间就越长。
注:del语句删除名称,而不是对象。del命令可能会导致对象被当作垃圾回收,但是仅当删除的变量保存的是对象的最后一个引用,或者无法得到对象时。
python唯一支持的参数传递模式是共享传参,共享传参指函数的各个形参获得实参中各个引用的副本,即函数内部形参和外部实参指向同一个对象。函数可能会修改作为参数传入的可变对象,例如列表。注意:不要使用可变类型作为参数的默认值
二.函数
Q2.1.这两个参数是什么意思:*args,**kwargs?我们为什么要使用它们?
可变参数:加上*表示可变参数 可以接受0个或任意个参数 在函数调用时组装成一个tuple。如果我们不确定往一个函数中传入多少参数,或者我们希望以元组(tuple)或者列表(list)的形式传参数的时候,我们可以使用*args(单星号)。
关键词参数:关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。如果我们不知道往函数中传递多少个关键词参数或者想传入字典的值作为关键词参数的时候我们可以使**kwargs(双星号)。
三.数据结构
Q3.1. 列表和元组之间的区别是?
元组与多数python集合(列表,字典,集合)一样,保存的是对象的引用。二者的主要区别是列表是可变的,可以随时添加,修改,删除其中的元素。而元组是不可变的,所谓的“不变”是说保存的引用不变,tuple的每个元素,指向永远不变,它更安全。
Q3.2.迭代器与生成器: 将列表生成式中[]改成() 之后数据结构是否改变? yield关键字?
是,从列表变为生成器。通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算的机制。
>>> L = [x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x0000028F8B774200>
注意两者的区别不只是在于是否是生成器。后者生成器只能用for遍历一次。
yield关键字类似于return,区别在于使用yield的函数会返回一个生成器。
>>> def createGenerator():
... mylist = range(3)
... for i in mylist:
... yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
... print(i)
0
1
4
To master yield
, you must understand that when you call the function, the code you have written in the function body does not run. The function only returns the generator object, this is a bit tricky。