近年来,Python在编程语言界里赚足了风头,无论是受欢迎程度,还是薪资待遇,都非常可观,相应的,Python岗位要求也越来越高,无论你是零基础还是老前辈,在Python面试中都不能轻视。
不打无准备之战,在平时我们就需要多积累,比如面试的时候,面试官会出其不意的问一些问题,今天给大家分享一些Python面试内容,都是基础实例,经典实用,代码清晰可拿来即用,很适合学习提升使用,适用性广,实用性强。不仅可当作练习使用,也可以当作面试参考,建议人手一份。话不多说,一起来看看吧!
昨天分享了前10道,今天依旧更新10道
1.django的生命周期
Django的生命周期可以分为以下几个阶段:
-
请求阶段:当用户发送请求时,Django会根据URL路由规则找到对应的视图函数,并将请求传递给该函数处理。
-
视图函数阶段:视图函数会处理请求,并返回一个HttpResponse对象,该对象包含了要返回给用户的内容。
-
中间件阶段:在视图函数处理请求之前或之后,Django会执行中间件的相应方法,例如处理请求头、身份验证、缓存等。
-
模板渲染阶段:如果视图函数返回的是一个模板,Django会将模板渲染成HTML页面,并将其包含在HttpResponse对象中返回给用户。
-
响应阶段:最后,Django会将HttpResponse对象发送给用户的浏览器,完成请求响应过程。
在整个生命周期中,Django还会执行一些其他的操作,例如数据库查询、缓存读写、日志记录等。
2.进程和线程的区别
Python进程和线程的区别如下:
-
进程是操作系统资源分配的最小单位,而线程是程序执行的最小单位。
-
进程之间相互独立,每个进程都有自己的地址空间、数据栈、文件描述符等,而线程共享进程的地址空间和资源。
-
进程之间通信需要使用IPC(Inter-Process Communication)机制,如管道、消息队列、共享内存等,而线程之间可以通过共享内存、信号量、互斥量等方式进行通信。
-
进程的创建和销毁需要较大的系统开销,而线程的创建和销毁则比较轻量级。
-
进程之间的切换需要较大的系统开销,而线程之间的切换则比较轻量级。
-
进程可以利用多核CPU实现并行处理,而线程则不能。
总之,进程和线程都是实现并发编程的方式,但是它们的应用场景和使用方式有所不同。在Python中,可以使用multiprocessing和threading模块来创建进程和线程。
3.分布式系统中的单例任务是怎么实现的
在Python分布式系统中,单例任务可以通过以下方式实现:
-
使用分布式锁:可以使用第三方库如redis等实现分布式锁,确保同一时间只有一个节点可以执行该任务。
-
使用消息队列:将任务放入消息队列中,每个节点从队列中获取任务并执行,通过设置消息队列的消费者数量为1,确保同一时间只有一个节点可以执行该任务。
-
使用数据库:将任务信息存储在数据库中,每个节点从数据库中获取任务并执行,通过设置任务状态为“执行中”,确保同一时间只有一个节点可以执行该任务。
需要注意的是,以上方法都需要考虑分布式系统中的网络延迟、节点故障等问题,确保任务的正确执行。
4.pg与mysql的区别有哪些
PG(PostgreSQL)和MySQL是两种不同的关系型数据库管理系统,它们有以下区别:
-
数据类型:PG支持更多的数据类型,如数组、JSON、XML等,而MySQL则不支持。
-
ACID支持:PG支持完全的ACID(原子性、一致性、隔离性、持久性)事务,而MySQL只支持部分ACID事务。
-
复杂查询:PG支持更复杂的查询,如递归查询、窗口函数等,而MySQL则不支持。
-
存储引擎:MySQL支持多种存储引擎,如InnoDB、MyISAM等,而PG只支持一种存储引擎。
-
性能:在高并发、大数据量的情况下,PG的性能比MySQL更好。
-
开源许可证:PG采用的是BSD许可证,而MySQL采用的是GPL许可证。
总的来说,PG更适合处理复杂的数据结构和高并发的场景,而MySQL则更适合处理简单的数据结构和小型应用。
5.python列表和字典底层原理实现
Python中的列表和字典都是基于哈希表实现的。
列表底层实现:
Python中的列表是一种动态数组,它的底层实现是一个数组,数组中的每个元素都是一个指针,指向存储在其他地方的真实数据。当列表需要扩容时,Python会重新分配一块更大的内存空间,并将原来的数据复制到新的内存空间中。这种实现方式使得列表的随机访问非常高效,但在插入和删除元素时需要移动大量的数据,效率较低。
字典底层实现:
Python中的字典是一种哈希表,它的底层实现是一个数组,数组中的每个元素都是一个指针,指向一个链表或红黑树。哈希表的关键是哈希函数,它将键映射到数组的索引上。当发生哈希冲突时,Python会使用链表或红黑树来解决冲突。字典的插入、删除和查找操作都非常高效,时间复杂度为O(1)。
总结:
列表和字典都是Python中常用的数据结构,它们的底层实现都是基于哈希表。列表适用于随机访问,字典适用于键值对的存储和查找。
7.给了一个长度为m的列表,返回前n小的元素,要求比较次数尽可能少
可以使用堆排序来解决这个问题,堆排序的时间复杂度为O(nlogn)。
具体实现步骤如下:
-
构建一个大小为n的最大堆,堆中元素为列表中前n个元素。
-
遍历列表中剩余的元素,如果当前元素小于堆顶元素,则将堆顶元素替换为当前元素,并重新调整堆。
-
遍历完成后,堆中的元素即为前n小的元素。
代码实现如下:
import heapq
def get_n_smallest(nums, n):
heap = nums[:n]
heapq._heapify_max(heap)
for i in range(n, len(nums)):
if nums[i] < heap[0]:
heapq._heapreplace_max(heap, nums[i])
return heap
# 示例
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
n = 4
print(get_n_smallest(nums, n)) # 输出 [1, 1, 2, 3]
在上述代码中,使用了Python内置的heapq
模块来实现堆排序。其中,_heapify_max()
函数用于构建最大堆,_heapreplace_max()
函数用于替换堆顶元素并重新调整堆。
8.pg的事务隔离级别
PostgreSQL的事务隔离级别包括以下四种:
-
读未提交(Read Uncommitted):一个事务可以读取另一个事务未提交的数据,可能会导致脏读、不可重复读和幻读问题。
-
读已提交(Read Committed):一个事务只能读取另一个事务已经提交的数据,可以避免脏读问题,但是可能会出现不可重复读和幻读问题。
-
可重复读(Repeatable Read):一个事务在执行期间多次读取同一数据,保证每次读取的数据都是一致的,可以避免脏读和不可重复读问题,但是可能会出现幻读问题。
-
序列化(Serializable):最高的隔离级别,保证所有事务的执行顺序和结果与串行执行的结果相同,可以避免脏读、不可重复读和幻读问题,但是会影响并发性能。
在实际应用中,需要根据具体业务场景和性能需求选择合适的事务隔离级别。
9.进程和线程的区别,为什么线程的开销会比进程小
Python中的进程和线程都是用于实现多任务的方式,但它们之间有一些重要的区别。
进程是操作系统中资源分配的基本单位,每个进程都有自己独立的内存空间、代码和数据。进程之间的通信需要使用IPC(Inter-Process Communication)机制,如管道、消息队列、共享内存等。由于进程之间的资源是独立的,因此进程之间的通信开销较大。
线程是进程中的一个执行单元,每个线程都共享进程的内存空间和数据。线程之间的通信可以直接访问共享的内存,因此线程之间的通信开销较小。但是,由于线程共享进程的资源,因此需要进行同步和互斥操作,以避免多个线程同时访问共享资源导致的数据不一致问题。
线程的开销比进程小,主要是因为线程的创建和销毁比进程快,线程之间的切换也比进程快。此外,由于线程共享进程的资源,因此线程之间的通信开销也比进程小。
总之,进程和线程都有各自的优缺点,应根据具体的应用场景选择合适的方式。
10.Python为什么要设置GIL而不是允许开发者自己去设置线程锁
Python中的GIL(全局解释器锁)是一种机制,它确保同一时刻只有一个线程可以执行Python字节码。这意味着在多线程环境中,只有一个线程可以执行Python代码,而其他线程则被阻塞。这是因为Python的内存管理不是线程安全的,如果多个线程同时访问和修改Python对象,可能会导致内存错误和数据损坏。
进程和线程都是并发执行的方式,但是它们之间有一些重要的区别:
- 进程是操作系统分配资源的基本单位,而线程是进程的执行单位。
- 进程之间相互独立,而线程共享进程的资源。
- 进程切换的开销比线程大,因为进程之间需要切换地址空间和上下文,而线程只需要切换上下文。
由于Python的内存管理机制,如果没有GIL,多个线程同时访问和修改Python对象可能会导致内存错误和数据损坏。因此,Python选择使用GIL来保护Python对象,确保同一时刻只有一个线程可以执行Python字节码。虽然GIL会导致多线程程序的性能下降,但是它可以保证程序的正确性和稳定性。
如果Python允许开发者自己去设置线程锁,那么开发者需要手动管理线程锁,这会增加代码的复杂度和开发难度。而且,由于Python的内存管理机制,即使开发者手动管理线程锁,也不能完全避免内存错误和数据损坏。因此,Python选择使用GIL来保护Python对象,这是一种更加简单和可靠的方式。
未完待续。。。。。