python面试八股与常见知识点

1.0 生成器,迭代器,装饰器

生成器(Generator)

生成器函数是一种特殊的迭代器,它允许在每次迭代时生成一个值,而不是一次性生成所有值。生成器函数使用yield关键字而不是return关键字来返回值。可以通过for循环或其他迭代器协议来迭代生成器对象。

生成器的创建方式通常有两种:

使用 yield 关键字:

def my_generator():

    for i in range(5):

        yield i  这里是使用yield 关键字来返回值,而不是return

gen = my_generator()

for value in gen:

    print(value)

使用生成器表达式:

gen = (x * x for x in range(5))

for value in gen:

print(value)

迭代器(Iterator)

迭代器是一个可以遍历容器(如列表、元组、字典、集合等)的对象,它实现了__iter__()和__next__()两个方法。迭代器对象能够记住遍历的位置,以便于下次迭代时从上次离开的地方继续进行

以下是迭代器的一个简单示例:

my_list = [1, 2, 3, 4]

my_iterator = iter(my_list)

print(next(my_iterator))  # 输出: 1

print(next(my_iterator))

装饰器:装饰器是一种设计模式,用于在不修改原有函数代码的情况下,给函数添加额外的功能。装饰器本质上是一个接受函数作为参数并返回一个新函数的函数

  def decorator_name(func):

    def inner(*args, **kwargs):

        # 在调用原始函数之前执行的操作

        # 可以添加一些代码

        

        # 调用原始函数

        result = func(*args, **kwargs)

        

        # 在调用原始函数之后执行的操作

        # 可以添加一些代码

        

        return result  # 返回原始函数的结果

return inner

1.1Init,new

init 在对象创建后,对对象进行初始化init是一个实例方法

new 是在对象创建之前创建一个对象,并将该对象返回给 init。new是一个静态方法,每次在init方法前调用,并需要返回一个实例。

1.2 浅拷贝深拷贝

浅拷贝: 只复制指向某个对象的指针,而不复制对象本身,简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。因此,如果你修改了原容器中的数据,浅拷贝中的相应数据也会被修改,即使是嵌套的也会改变,反之亦然。

深拷贝:深拷贝就是完全创建一个新的对象,与原来的没有任何关系,只是数值一样而已

import copy

list1 = [1, 2, [3, 4]]

list2 = copy.copy(list1)  # 浅拷贝

# 修改外层不可变元素

list2[0] = 100

print(list1)  # [1, 2, [3, 4]],list1 不受影响

# 修改内层可变元素

list2[2][0] = 300

print(list1)  # [1, 2, [300, 4]],list1 的内层被修改了

list2 = copy.deepcopy(list1)  # 深拷贝

# 修改外层元素

list2[0] = 100

print(list1)  # [1, 2, [3, 4]],list1 不受影响

# 修改内层元素

list2[2][0] = 300

print(list1)  # [1, 2, [3, 4]],list1 完全不受影响

1.3 sort,sorted

Sort:直接修改原列表

Sorted:创建并返回一个新的排序列表,而不是修改原列表

reverse=False(默认值)(升序)

1.4 类,实例,静态

类方法:通过装饰器@classmethod来标识。它的第一个参数是cls(表示类本身),而不是实例对象,可以在没有实例的情况下被调用

实例方法:定义时不需要额外的装饰器,第一个参数通常是self,表示实例本身,通过实例对象调用。其实实例就是动态的,可以自己定义方法和属性,而静态就是没办法自己定义,每一个静态方法的值都是相同的

静态方法:通过@staticmethod装饰器来声明。与普通方法和类方法不同,静态方法既不需要传递类对象(cls)也不需要传递实例对象(self)作为第一个参数,可以通过类名直接访问,而不需要创建类的实例。

1.5 递归和迭代

迭代就是循环,如for,while

递归就是通过函数调用自身,将原问题分解为更小的子问题

终止条件:用于决定什么时候由“递”转“归”。

递归调用:对应“递”,函数调用自身,通常输入更小或更简化的参数。

返回结果:对应“归”,将当前递归层级的结果返回至上一层。

1.6 继承,多态,封装

继承:允许一个类(子类)继承另一个类(父类)的属性和方法,子类可以扩展或修改父类的功能,同时保持父类的属性和方法

封装:就是以函数进行封装,只暴露一个接口供调用

多态:定义子类继承父类,在子类中实现新的功能,实现同一方法但是返回了不同结果

1.7 进程线程协程

进程:一个运行的程序(代码)就是一个进程,进程是系统资源分配的最小单位

线程: 调度执行的最小单位

协程:是一种用户态的轻量级线程,协程的调度完全由用户控制

所以 Python 里常常使用协程技术来代替多线程,协程是一种更轻量级的线程,进程和线程的切换时由系统决定,而协程由我们程序员自己决定。三者的关系:进程里有线程,线程里有协程。

多进程适合在 CPU 密集型操作(cpu 操作指令比较多,如位数多的浮点运算)。

多线程适合在 IO 密集型操作(读写数据操作较多的,比如爬虫)

线程是并发,进程是并行;

1.8 四种数据类型

Str:不可变

列表:有序可变

元组:不可变

字典:无序可变

集合:不重复唯一,它还支持|(联合), &(交),-(差)和^(对称差集)等数学运算.

1.9  read、readline 和 readlines 的区别?

read:读取整个文件

readline:读取下一行使用生成器方法

readlines:读取整个文件到一个迭代器以供我们遍历

lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数

1、lambda 函数比较轻便,即用即仍,很适合需要完成一项功能,但是此功能只在此一处使用,连名字都很随意的情况下

2.0 内存管理方式

内存管理机制:引用计数、垃圾回收、内存池

2.1 垃圾回收机制

1. 引用计数

引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。当 Python 的某个对象的引用计数降为 0 时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。比如某个新建对象,它被分配给某个引用,对象的引用计数变为 1。如果引用被删除,对象的引用计数为 0,那么该对象就可以被垃圾回收。不过如果出现循环引用的话,引用计数机制就不再起有效的作用了

2. 标记清除

如果两个对象的引用计数都为 1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为非 0,但实际上有效的引用计数为 0。所以先将循环引用摘掉,就会得出这两个对象的有效计数。

3. 分代回收

从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作就越少;反之,当需回收的内存块越少时,垃圾检测就将比垃圾回收带来更少的额外操作。

2.2 死锁与解决方法

锁(Lock)是 Python 提供的对线程控制的对象。有互斥锁、可重入锁

GIL 锁,全局解释器锁(只在 cpython 里才有)限制多线程同时执行,保证同一时间只有一个线程执行

1.加锁顺序:加锁顺序是避免死锁的重要方法之一。如果多个线程总是按照相同的顺序请求锁,那么就不会出现死锁的情况。

2.使用try-except-finally,不管有没有异常,finally中都释放锁。

3.使用超时机制:lock.acquire(timeout=5)设置获取锁的超时时间,若规定时间内取法获取锁,就放弃获取锁并执行其他操作。

4.使用RLock: Python中的RLock是可重入锁,与普通锁不同的是,同一个线程可以多次获取同一个RLock,而不会出现死锁的情况。

2.3 并行并发,同步异步

同步:多个任务之间有先后顺序执行,一个执行完下个才能执行。

异步:多个任务之间没有先后顺序,可以同时执行有时候一个任务可能要在必要的时候获取另一个同时执行的任务的结果,这个就叫回调!

并行:同一时刻多个任务同时在运行。

并发:在同一时间间隔内多个任务都在运行,但是并不会在同一时刻同时运行,存在交替执行的情况。

2.4 *args 和**kwargs的区别是什么

*args 是不定长参数,他可以表示输入参数是不确定的,可以是任意多个。

**kwargs 是关键字参数,赋值的时候是以键 = 值的方式,参数是可以任意多对在定义函数的时候不确定会有多少参数会传入时,就可以使用两个参数。

2.5 jwt

想象一下,你有一张电影票,这张票上面有电影院的名字、座位号、电影名称和放映时间等信息。电影院的检票员看到这张票后,就能知道你是来看哪场电影的,坐在哪个座位上。在这个例子中,电影票就像是一个JWT。

其实就是身份认证,他有三部分,头部,载荷,头部和载荷通过一个密钥进行加密,生成签名,用户登录一个网站时,服务器验证用户的凭证后,会创建一个JWT并发送给用户。用户在随后的请求中带上这个JWT,就像带上电影票一样,JWT就像是你的网络身份通行证。

JWT与Session的差异 相同点是,它们都是存储用户信息;然而,Session是在服务器端的,而JWT是在客户端的。Session方式存储用户信息的最大问题在于要占用大量服务器内存存在内存中),增加服务器的开销

JWT与OAuth的区别 -OAuth2是一种授权框架 ,JWT是一种认证协议OAuth2用在使用第三方账号登录的情况(比如使用weibo, qq, github登录某个app),而JWT是用在前后端分离, 需要简单的对后台API进行保护时使用

3.0 Tcp,udp

TCP(传输控制协议) 是一种面向连接的协议,提供可靠的数据传输

 UDP(用户数据报协议) 是一种无连接的协议,不保证数据传输的可靠性,数据可能丢失或损坏

对于文件传输或网页浏览等需要可靠传输的应用,通常会选择 TCP。而对于视频会议或在线游戏等需要实时性的应用,可能会选择 UDP

3.1 七层结构

物理层,数据链路层,网络层,传输层,会话层,表示层,应用层

IP: 网络层

TCP/UDP: 传输层

HTTP、RTSP、FTP: 应用层协议

3.2 三次握手,四次挥手

三次握手:

想象一下,你想要和你的朋友通过电话交谈。但是你们都不知道对方是否可以听到你的声音。所以你们会这样做:

你拿起电话,说:“喂?”(客户端发送SYN(同步序列编号)

你的朋友听到你的声音,拿起电话,说:“喂?”(服务器发送SYN+ACK(确认序列编号)

你听到你的朋友的声音,知道他已经准备好通话了,于是你说:“我准备好了。”(客户端发送ACK包

现在你们可以开始聊天了。

四次挥手

想象一下,你和你的朋友聊完天,想要挂断电话。但是你们都不想显得粗鲁,所以你们会这样做:

你说:“我要挂电话了。”(客户端发送FIN(结束)

你的朋友听到你说要挂电话,于是他说:“好的,我也要挂电话了。”(服务器发送ACK包

你的朋友说完后,他也准备挂电话了,于是他说:“我要挂电话了。”(服务器发送FIN包

你听到你的朋友说要挂电话,于是你说:“好的,再见。”(客户端发送ACK包

3.3 描述用浏览器访问 www.baidu.com 的过程

域名解析:

您的浏览器首先通过DNS服务器解析 www.baidu.com 对应的IP地址

建立连接:

使用TCP/IP协议来建立一个连接。浏览器会发送一个SYN包到服务器的IP地址和端口。

服务器响应:

服务器收到SYN包后,会发送一个SYN+ACK包作为响应,表示它也想要建立连接,并且确认了客户端的SYN包。

客户端确认

浏览器收到服务器的SYN+ACK包后,会发送一个ACK包给服务器,表示它收到了服务器的SYN+ACK包,确认了服务器的请求。

发送请求:

浏览器会向服务器发送一个HTTP请求,请求访问网站的首页。

服务器响应:

服务器接收到请求后,会处理请求并返回一个HTTP响应。

接收响应:

浏览器接收到服务器的响应后,会解析响应头信息和响应体,将网页内容显示在浏览器窗口中。

关闭连接:

一旦网页内容被浏览器完全显示,或者没有更多的数据需要传输,浏览器会发送一个FIN包给服务器,表示它没有更多的数据要发送了。服务器收到FIN包后,会发送一个ACK包给浏览器,表示它确认了客户端的请求。如果服务器也没有数据要发送了,它会向客户端发送一个FIN包。最后,客户端收到服务器的FIN包后,会发送一个ACK包给服务器,表示它确认了服务器的请求。完成这四次挥手后,浏览器和服务器之间的连接就被关闭了。

3.4 说说 HTTP 和 HTTPS 区别

HTTP 协议传输的数据都是未加密的,也就是明文的,因此使用 HTTP 协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了 SSL(Secure Sockets Layer)协议用于对 HTTP 协议传输的数据进行加密,从而就诞生了 HTTPS。简单来说,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 http 协议安全。

4.0 Cookie和session

cookie 数据存放浏览器上,session 数据放在服务器上(也就是内存中)

Cookie其实就是记录你的个人信息,主要用于登录注册,session就是记录你的会话状态,主要用于记住你上次是什么时间访问了什么页面什么内容,下次你登录就可以直接到上次访问的页面(登录状态保持)

Django性能为什么比Java的差,如何提升他的高并发

1.Python:使用解释器执行,这意味着它在运行时逐行解释Python代码。虽然现代Python 解释器(如CPython)使用了即时编译(JIT)技术来提高性能,但与完全编译的语言相 比,它的执行速度通常较慢。

Java:使用编译器将Java代码编译成字节码,然后由Java虚拟机(JVM)执行。JVM使 用即时编译(JIT)和热路径优化等技术来优化字节码的执行,这使得Java应用程序在 运行时可以达到接近本地编译代码的性能

2.Python:CPython(最流行的Python解释器)使用全局解释器锁(GIL)来防止多个原生线程同时执行Python字节码。这限制了在多核处理器上并行执行的能力,从而影响了多线程程序的性能。

Java:Java虚拟机通常能够更有效地利用多核处理器,因为它允许真正的多线程并行执 行。

3.python:是一种动态类型语言,这意味着类型检查在运行时进行。动态类型可以提供更大的灵活性,但也会引入额外的性能开销。

Java:是一种静态类型语言,类型检查在编译时进行。这有助于JVM进行更有效的优化

Java与python的区别:

Java:半解释半编译语言,源代码首先被编译成字节码(一种中间表示),这种字节码可以在任何支持 Java 虚拟机(JVM)的环境上运行。(启动慢,调试复杂,执行代码速度快)

Python:Python 是强类型的动态脚本语言。

强类型:不允许不同类型相加。

动态:不需要声明数据的类型,比如int a这种。

脚本语言:Python 解释器逐行读取、翻译和执行源代码,没有单独的编译阶段(启动快,容易调试,执行代码慢)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值