python基础面试题
1、对字典操作和深浅拷贝的理解
def func(m):
for k,v in m.items():
m[k+2] = v + 2 #这样做是会报错的,RuntimeError: dictionary changed size during iteration
m = {1:2,3:4}
l = m
l[9]=10
# func(l) #
m[7]=8
# 1、在python中遍历字典的时候是不能对字典涉及的键进行操作(键的添加和删除)
# 2、深浅拷贝
print(l) # 注释掉函数后的结果是 {1: 2, 3: 4, 9: 10, 7: 8}
print(m) # {1: 2, 3: 4, 9: 10, 7: 8}
from copy import deepcopy
m = {1:2,3:4}
l = m # 浅拷贝
l2 = deepcopy(m) # 深拷贝
l[9]=10
m[7]=8
print(l) # 注释掉函数后的结果是 {1: 2, 3: 4, 9: 10, 7: 8}
print(m) # {1: 2, 3: 4, 9: 10, 7: 8}
print(l2) #{1: 2, 3: 4}
2、字符串格式化:%和format有什么区别
'''
1、python新版本推荐使用format
2、python2.6才加入的支持format语法支持
3、python3.6引入了新特性f-string
'''
name = 'Fred'
res = f"he said his name is {name}"
print(res) #he said his name is Fred
3、可变对象不建议做关键字参数
def foo(arg,li=[]):
li.append(arg)
return li
list1 = foo(21)
list2 = foo(21,[1,])
list3 = foo(28)
print(list1) #[21,28]
print(list2) #[1,21]
print(list3) #[21.28]
4、列表切片
li = [11,22,33,44]
print(li[10:]) #[]
5、fib 斐波那契
# 1
fib = lambda n:n if n<2 else fib(n-1) + fib(n-2)
print(fib(6))
# 2
def fib(n):
a,b = 0,1
for _ in range(n):
a,b = b, a+b
return b
6、去重
# set集合
l1 = ['b','c','d','b','a','c','c']
print(set(l1))
# 用字典
l2 = {}.fromkeys(l1).keys()
print(l2)
#列表推导式
l3 = []
[l3.append(i) for i in l1 if i not in l3]
print(l3)
for i in l1:
if i not in l3:
l3.append(i)
print(l3)
7、合并两个有序列表
def loop_merge_sort(l1,l2):
tmp = []
while len(l1)>0 and len(l2)>0:
if l1[0]
tmp.append(l1[0])
del l1[0]
else:
tmp.append(l2[0])
del l2[0]
tmp.extend(l1)
tmp.extend(l2)
return tmp
print(loop_merge_sort([1,3,5],[1,2,7]))
8、单例模式:在__new__方法上把类实例绑定到类变量_instance上,如果cls._instance为None表示还没有实例化过实例化该类并返回,如果cls._instance不为None表示该类已经实例化,直接返回cls._instance
class SingleTon(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls,'_instance'):
cls._instance = object.__new__(cls,*args,**kwargs)
return cls._instance
class TestSingle(SingleTon):
a = 1
t1 = TestSingle()
t2 = TestSingle()
print(id(t1),'--',id(t2))
9、读li进行计数,返回出现次数最多的
l1 = ['a','b','c','d','a','v','s','d','c','a','c','c']
# 法1
from collections import Counter
result = Counter(l1).most_common(1)
print(result)
# 法2
def all_list(l1):
"""获取所有元素的出现次数,使用list中的count方法"""
result = {}
for i in set(l1):
result[i] = l1.count(i)
return result
result = all_list(l1)
for k,v in result.items():
if result[k] == max(result.values()):
print(k,v)
10、上下文实现原理
'''
上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
作用:
1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,
你无须再去关系这个问题,这将大有用处
'''
class Open:
def __init__(self,filepath,mode="r",encode="utf-8"):
self.f = open(filepath,mode=mode,encoding=encode)
def write(self):
pass
def __getattr__(self, item):
return getattr(self.f,item)
def __del__(self):
print("--->del")
self.f.close()
def __enter__(self):
print("出现with语句,对象会调用我")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("with结束之后,会执行我啦")
with Open('1.txt') as f:
f.write()
'''
出现with语句,对象会调用我
with结束之后,会执行我啦
--->del
'''
socket问题
1、为什么会出现粘包?
首先只有在TCP协议中才能出现粘包现象,这是因为TCP协议是面向流的协议,
在发送数据的数据传输过程中还有缓存机制来避免数据丢失,因此在连续发送
小数据的时候以及接受大小不符的时候都容易出现粘包现象,本质还是因为我们在接受数据的时候
不知道发送的数据的长度。
2、如何解决粘包?
在传输大量数据之前先告诉接收端要发送的数据的大小。如果要想更好的解决问题,可以采用struct
模块来定制协议。
3、GIL锁?
1、GIL导致了同一时刻只能有一个线程访问CPU。2、锁的是什么?锁的是线程3、GIL是python语言的问题吗?不是,是CPython解释器的特性。
4、线程的概念?
进程是最小的内存分配单元,线程是操作系统调度的最小单位,线程直接被CPU执行,进程内至少含有一个线程
也可以开启多个线程。
特点:
开启一个线程所需要的时间要远小于开启一个进程,
多个线程内部有自己的数据栈,数据不共享
全局变量在多个线程之间是共享的。