python数据结构面试_Python面试题

is 和 ==的区别

is: 比较对象的id值,也就是是否指向同一个内存地址

==: 比较对象的值是否相等,默认会调用对象的eq()方法

python内置数据结构

列表、字典、字符串、集合、元组

变量作用域

LEGB

L: local函数内部作用域

E: enclosing函数内部与内嵌函数之间

G: global全局作用域

B: build-in 内置作用域

var_a=1

var_b=10

var_c=100

def outer():

var_a=2

var_b=20

def inner():

var_a=3

print(var_a) # L local 优先使用本地

print(var_b) # E enclosing 本地没有找嵌套作用域

print(var_c) # G global 全局作用域

print(__name__,max,min,id) # B built-in 找内置作用域

inner()

outer()

super举例

class Base:

def __init__(self):

print('Base.__init__')

class A(Base):

def __init__(self):

super().__init__()

print('A.__init__')

class B(Base):

def __init__(self):

super().__init__()

print('B.__init__')

class C(A,B):

def __init__(self):

super().__init__() # Only one call to super() here

print('C.__init__')

>>> c = C()

Base.__init__

B.__init__

A.__init__

C.__init__

>>> C.__mro__

(, , , , )

单例

class Singleton2(object):

def __new__(cls, *args, **kwargs):

if not hasattr(cls, '_instance'):

cls._instance = super(Singleton2, cls).__new__(cls, *args, **kwargs)

return cls._instance

class foo(Singleton2):

pass

foo1 = foo()

foo2 = foo()

print (foo1 is foo2)

字典按值排序

>>> a={"a":2, "v": 1, "ds": 100}

>>> sorted(a.items(), key=lambda x:x[1])

[('v', 1), ('a', 2), ('ds', 100)]

>>> sorted(a.items(), key=lambda x:x[1], reverse=True)

[('ds', 100), ('a', 2), ('v', 1)]

>>> dict(sorted(a.items(), key=lambda x:x[1], reverse=True))

{'ds': 100, 'a': 2, 'v': 1}

找出列表中相同和不同的元素

list1 = [1,2,3]

list2 = [3,4,5]

set1 = set(list1)

set2 = set(list2)

print(set1 & set2) #相同的

print(set1 ^ set2) #不同的

GIL(global interpreter lock - 全局解释器锁)

并行:多个CPU同时执行多个任务,就好像有两个程序,这两个程序是真的在两个不同的CPU内同时被执行。

并发:CPU交替处理多个任务,还是有两个程序,但是只有一个CPU,会交替处理这两个程序,而不是同时执行,只不过因为CPU执行的速度过快,而会使得人们感到是在“同时”执行,执行的先后取决于各个程序对于时间片资源的争夺

单线程: 双核cpu使用率50%

多线程:双核cpu使用率50%

多进程:双核cpu使用率100%

如何解决GIL锁的问题

1、更换Cpython为Jpython

2、使用多进程完成多线程任务

什么时候会释放GIL锁

1、遇到像 i/o操作这种 会有时间空闲情况 造成cpu闲置的情况会释放Gil

2、会有一个专门ticks进行计数 一旦ticks数值达到100 这个时候释放Gil锁 线程之间开始竞争Gil锁(说明:

ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)

互斥锁和GIL锁的关系

Gil锁 : 保证同一时刻只有一个线程能使用到cpu

互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱

内存管理机制

1、引用计数

引用计数是一种非常高效的内存管理手段,当一个pyhton对象被引用时其引用计数增加1,当其不再被引用时引用计数减1,当引用计数等于0的时候,对象就被删除了。

2、垃圾回收

引用计数

标记清除

标记清除用来解决循环引用产生的问题,循环引用只有在容器对象才会产生,比如字典,元祖,列表等。首先为了追踪对象,需要每个容器对象维护两个额外的指针,用来将容器对象组成一个链表,指针分别指向前后两个容器对象,这样可以将对象的循环引用摘除,就可以得出两个对象的有效计数。

分代回收

随着你的程序运行,Python解释器保持对新创建的对象,以及因为引用计数为零而被释放掉的对象的追踪。从理论上说,创建==释放数量应该是这样子。但是如果存在循环引用的话,肯定是创建>释放数量,当创建数与释放数量的差值达到规定的阈值的时候,当当当当~分代回收机制就登场啦。

分代回收思想将对象分为三代(generation 0,1,2)

0代表幼年对象,

1代表青年对象,

2代表老年对象。

根据弱代假说(越年轻的对象越容易死掉,老的对象通常会存活更久。)

新生的对象被放入0代,如果该对象在第0代的一次gc垃圾回收中活了下来,那么它就被放到第1代里面(它就升级了)。如果第1代里面的对象在第1代的一次gc垃圾回收中活了下来,它就被放到第2代里面。

从上一次第0代gc后,如果分配对象的个数减去释放对象的个数大于threshold0,那么就会对第0代中的对象进行gc垃圾回收检查。

从上一次第1代gc后,如果第0代被gc垃圾回收的次数大于threshold1,那么就会对第1代中的对象进行gc垃圾回收检查。

从上一次第2代gc后,如果第1代被gc垃圾回收的次数大于threshold2,那么就会对第2代中的对象进行gc垃圾回收检查。

gc每一代垃圾回收所触发的阈值可以自己设置。

3、内存池

Python的内存机制呈现金字塔形状,-1,-2层主要有操作系统进行操作

第0层是C中的malloc,free等内存分配和释放函数进行操作

第1层和第2层是内存池,有python接口函数,PyMem_Malloc函数实现,当对象小于256k的时由该层直接分配内存

第3层是最上层,也就是我们对python对象的直接操作

Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效 率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值