Python进阶题
1、如何获取列表中第二大的值?
#先去重,在排序,取值
lst = [1,2,3,4,5,5,5,5,5,5,5,5]
setvar = set(lst)
# 列表.sort 类型有局限性,只能是列表,基于原有列表进行修改
# sorted 容器类型数据皆可以,返回新列表
lst = sorted(setvar)
print(lst) # [1, 2, 3, 4, 5]
res = lst[-2]
print(res)
2、简述Python内存管理机制。
# 一.计数器
#特点:引用技术如果是0,把这个值从内存中释放掉
a = 100
b = a
print(b)
del b
a = 100 (100这个值计数为1,被引用过1次)
b = a (100这个值计数为2,被引用过2次)
del b (100这个值计数为1,被引用过1次,100本身不会被删掉)
del a (100这个值计数为0,被引用过0次,100本身被删掉)
#缺点:在维护引用计数时,又可能数据产生循环引用,造成数据不能删除,造成内存泄漏
lst1 = [1,2]
lst2 = [5,6]
lst1.append(lst2)
lst2.append(lst1)
del lst1
print(lst1)
print(lst2)
3、简述Python的垃圾回收机制。
计数器,垃圾回收,内存池
# 一.计数器
特点:引用技术如果是0,把这个值从内存中释放掉
a = 100
b = a
print(b)
del b
缺点:在维护引用计数时,又可能数据产生循环引用,造成数据不能删除,造成内存泄漏
lst1 = [1,2]
lst2 = [5,6]
lst1.append(lst2)
lst2.append(lst1)
del lst1
print(lst1)
print(lst2)
# 二.垃圾回收:引用计数为主,标记清除和分带回收为辅
标记清除 : 检测标记该对象,避免出现循环引用不能删除的现象
分带回收 :
把内存中的数据分成三个区域: 新生代0,老年代1,永久代2
新生代0数据超过700 , 或者老年代1,永久代2数据超过10,自动触发内存中的垃圾回收机制
新生代0触发将清除所有三代的区域
老年代1触发会清理1,2代
永久代2触发只会清理自己
# 三.内存池
# 在同一个文件当中 (python3.6)
# -->Number 部分
1.对于整型而言,-5~正无穷范围内的相同值 id一致
2.对于浮点数而言,非负数范围内的相同值 id一致
3.布尔值而言,值相同情况下,id一致
4.复数在 实数+虚数 这样的结构中永不相同(只有虚数的情况例外)
# -->容器类型部分
5.字符串 和 空元组 相同的情况下,地址相同
6.列表,元组,字典,集合无论什么情况 id标识都不同 [空元组例外]
# 在不同的文件当中
小数据池 ; 比如整型默认开辟 -5~256 这么多数据提前在内存中驻留
4、请用两个队列来实现一个栈。
"""
栈: 先进后出,后进先出
队列: 先进先出,后进后出
"""
from queue import Queue
class Stack():
def __init__(self):
self.master_queue = Queue()
self.minor_queue = Queue()
# 入栈
def push(self,val):
self.master_queue.put(val)
# 出栈
def pop(self):
# qsize() 队列长度为0等于没数据返回None
if self.master_queue.qsize() == 0:
return None
while True:
if self.master_queue.qsize() == 1:
# 拿出队列里面最后一个元素
value = self.master_queue.get()
break
# 把临时获取的值存在辅队列里
self.minor_queue.put(self.master_queue.get())
# 重置主队列,把辅队列临时存储的值放回去
self.master_queue, self.minor_queue = self.minor_queue , self.master_queue
return value
obj = Stack()
# push 添加数据
obj.push(1)
obj.push(2)
obj.push(3)
# pop 获取数据 3 2 1
print(obj.pop())
print(obj.pop())
print(obj.pop())
print(obj.pop())
5、请用Python实现一个链表。
class Node():
def __init__(self,value,next):
self.value = value
self.next = next
head = Node("头",None)
last = head
for i in range(5):
# 创建节点对象n0 n1 n2 n3 n4
node = Node( "n%s" % (i) , None)
# 把当前创建的节点塞到上一个节点的next属性中
last.next = node
# 向下一个节点移动
last = node
# 查看链表关系
print(head.value)
print(head.next.value)
print(head.next.next.value)
print(head.next.next.next.value)
print(head.next.next.next.next.value)
print(head.next.next.next.next.next.value)
print(head.next.next.next.next.next.next)
>>>
头
n0
n1
n2
n3
n4
None
6、请用Python实现链表的逆转。
# ### (1) 创建链表
class Node():
def __init__(self, value, next):
self.value = value
self.next = next
head = Node("头", None)
last = head
for i in range(5): # v0 v1 v2 v3 v4
node = Node("v%s" % i, None)
last.next = node
last = node
# 查看链表的关系
print(head.value)
print(head.next.value)
print(head.next.next.value)
print(head.next.next.next.value)
print(head.next.next.next.next.value)
print(head.next.next.next.next.next.value)
print("<========>")
# 2.链表的逆转
def reverse_link_list(head):
# 要是空的,或者None,直接返回head
if not head or not head.next:
return head
# 获取上一个节点对象
prev_node = None
# 获取下一个节点对象
next_node = head.next
# 获取当前节点对象
current_node = head
while True:
# 修改next,所指向的对象
current_node.next = prev_node
# 如果下一个阶段对象是None
if not next_node: # not None
break
# 重新获取上一个对象,即把当前丢向单独存一份,以准备第二次循环时插进next属性中
prev_node = current_node
# 重新获取当前对象 , 即把下一个对象单独存储起来(下个)
current_node = next_node
# 重新获取下一个对象,即把下一个对象单独存储起来,所指向的下个新对象赋值给next_node(下下个)
next_node = current_node.next
return current_node
head = reverse_link_list(head)
print(head.value)
print(head.next.value)
print(head.next.next.value)
print(head.next.next.next.value)
print(head.next.next.next.next.value)
print(head.next.next.next.next.next.value)