文章目录

  • 分布式爬虫
  • django的请求周期
  • 0.深拷贝和浅拷贝的区别?
  • 1.\*args, ** kwargs是什么意思?
  • 2.谈一谈Python中的装饰器
  • 3.Python的垃圾回收机制以及内存管理
  • 4.Python多线程
  • 5.说明os、sys模块不同,并列举常用的模块方法
  • 6.什么是lambda表达式?它有什么好处?
  • 7.Python里面如何拷贝一个对象?
  • 8.__new__和__init__的区别。
  • 9.python中协程?协程的作用?
  • 10.Python的异常机制?
  • 11.python旧式类(经典类)和新式类的区别
  • 2.classmethod,staticmethod,property是什么?有什么作用?
  • 13.python中的绑定方法和未绑定方法是什么
  • 14.python上下文管理器是什么
  • 15.functools的wraps是做什么的?
  • 16.ORM实现原理
  • 17.迭代器和生成器区别?
  • 17.1 yield与return的区别
  • 18.描述一下type()的作用
  • 19.Python中列表与元组的异同?
  • 20.Python中的列表是如何实现的?
  • 21.Python中列表的索引查询的时间复杂度是多少?
  • 22.Python字典的实现原理?
  • 23.什么是pickling和unpickling?
  • 24.有哪些工具可以帮助debug或做静态分析?
  • 25.**Python中的作用域**?
  • 26.Python的参数传递是值传递还是引用传递?
  • 27.写一个函数, 输入一个字符串, 返回倒序排列的结果
  • 28.python中is和==的区别
  • 29.什么是Python的闭包?
  • 30. Python的自省?
  • 31.Python并发的解决方案
  • 操作系统相关
  • 1.进程的有哪几种状态以及导致转换的事件。
  • 2.进程与线程的区别。
  • 3.进程通信的几种方式。
  • 4.线程同步几种方式
  • 5.用户线程与内核线程的区别
  • 6.进程池、线程池的原理?
  • 7.进程为什么会产生死锁?
  • 8.操作系统的四个特性?
  • 9.什么是缓冲区溢出?有什么危害?其原因是什么?
  • 网络相关
  • 1.TCP为什么需要3次握手
  • 2.TCP和UDP有什么区别?
  • 3.TCP/IP的流量控制?
  • 4.HTTP的长连接和短连接?
  • http://5.IO中同步与异步,阻塞与非阻塞区别
  • 6.Cookies 和 Session的区别
  • 7.什么是TCP粘包、TCP粘包发生了怎么处理?
  • 8.TCP中的time_wait是什么情况?出现过多的close_wait可能是什么原因?
  • 9.epoll,select的区别?边缘触发,水平触发区别?
  • 10. tcp三次握手, 四次挥手
  • 数据储存与缓存相关
  • 1.数据库事务的四个特性及含义
  • 2.数据库索引使用了什么数据结构?
  • 3.数据库优化的思路
  • 4.MySQL中myisam与innodb的区别
  • 5.Redis支持的数据类型
  • 6.redis持久化的几种方式
  • 7. redis如何实现热数据缓存?
  • 8.Redis 常见的性能问题都有哪些?
  • 9.mysql字符集和排序规则?
  • 10.varchar与char的区别是什么?大小限制?utf8字符集下varchar最多能存多少个字符?
  • 11.primary key和unique的区别?
  • 12.外键有什么用,是否该用外键?外键一定需要索引吗?
  • 13.索引有什么用?
  • 14.redis的事务?用事务模拟原子+1操作?原子操作还有其它解决方案吗?
  • 1.python的常用的数据结构有哪些?
  • 2.python的常用的数据类型?
  • 3.python生成随机数 random(0,10)可以生成包含0~10的随机数吗?
  • 4.python反转列表
  • 5.python中有没有用过装饰器、用装饰器的场景,理解装饰器中的逻辑吗?
  • 6. python的匿名函数是什么?
  • 7. Python 函数参数前面一个星号(*)和两个星号(**)的区别
  • 8. 两个列表,list1 = [1,2,3], list2= [4,5,6], 怎么扩展让list1=[1,2,3,4,5,6,]
  • 9.list1 = [1,2,3], list2= [1,2,4,5,6]怎么取出两个列表不一样的内容 ?
  • 10. 列表用下标可以改变赋值,字符串可以吗 ?
  • 11. 想要改变字符串的某一个元素应该怎么办?
  • 12. 正则表达式限制只能输入5个数字, 应该怎么写正则表达式语句?
  • 13. json跟字典的区别
  • 14. 字典怎么遍历 key, value,如果同时要遍历key 和value 呢?
  • 15. 如何将两个列表转化未一个字典,列表a的值作为 key,列表b的值作为 value?
  • 1 Python垃圾回收机制是什么
  • 2 元组和列表的区别
  • 4 进程 线程 协程
  • 4.1 进程
  • 4.2 线程
  • 4.3 协程
  • 5 赋值、浅拷贝和深拷贝
  • 6 GIL
  • 7 列表去重
  • 8 最常用的排序算法及其复杂度
  • 8.1 冒泡排序
  • 8.3 快速排序
  • 9 闭包
  • 10 with
  • 11 实例方法 静态方法
  • 12 迭代器和生成器
  • 12.1 迭代器
  • 12.2 生成器
  • 13 匿名函数
  • 14 map reduce filter
  • 输出: [1, 3, 5, 7, 9]
  • Django
  • 1 什么是wsgi
  • 2 django请求的生命周期
  • 3 列举django的内置组件
  • 4 列举django中间件的5个方法?以及django中间件的应用场景
  • 5 简述什么是FBV和CBV
  • 6 django的request对象是在什么时候创建的
  • 7 如何在CBV添加装饰器
  • 8 列举django orm 中所有的方法
  • 9 select_related 和 prefetch_related的区别
  • 10 django 中 csrf 的实现机制
  • 12 django缓存如何设置
  • 13 django的缓存能使用redis吗?如果可以的话,如何配置
  • 14 django路由系统中name的作用
  • 15 django rest framework框架中都有那些组件
  • 16 简述 django rest framework框架的认证流程
  • 17.进程与线程的区别。
  • 18.Hadoop、Hive和Spark的具体介绍,它们之间主要有什么关系?

分布式爬虫

分布式爬虫是指在多个计算机上部署爬虫程序,共享队列,去重,让多个爬虫不爬取其他爬虫爬取过的内容,从而实现实现联合采集,是一种提高爬取效率的方法

django的请求周期

(1)用户输入网址,浏览器发起请求
(2)WSGI(服务器网关接口)创建socket服务端,接受请求
(3)中间件处理请求
(4)url路由,根据当前请求的url找到相应的视图函数
(5)进入view,进行业务处理,执行类或者函数,返回字符串
(6)再次通过中间件处理相应
(7)WSGI返回响应
(8)浏览器渲染

0.深拷贝和浅拷贝的区别?

  1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。好处:只拷贝引用,不增加内存
  2. copy.deepcopy 深拷贝 拷贝对象及其子对象 好处:可用于备份,源数据被修改它不会被影响
    可变类型(list,dict):浅拷贝只拷贝第一层,深拷贝会拷贝所有层
    不可变类型(int,string,float,tuple):深浅拷贝都一样,只拷贝引用
    注意:
    可变类型里嵌套不可变类型或不可变里面嵌套可变类型:浅拷贝只拷贝引用,而深拷贝为保证数据的独立性,它会从最外层到不可变类型都复制一遍
    作用:浅拷贝可以节省内存空间,pytho中大多数都是浅拷贝。可以根据需求进行浅拷贝还是深拷贝。例如是备份重要数据,不想被修改就采用深拷贝。(因为浅拷贝指向同一个地址,不会增加内存,相当于桌面快捷方式一样.)
import copy
a=[1,2,3,4]
#赋值拷贝
b=a # 赋值拷贝内存地址一致,有一方改动另一方跟着改动#浅拷贝
c=copy.copy(a)#只拷贝a子元素的引用,当该子元素有变动他也跟着变动,但原列表增删元素不会影响浅拷贝的个数,只是元素引用一致,内存地址不一致#深拷贝
d=copy.deepcopy(a) #引用和值一起拷贝,双方互不影响

1.*args, ** kwargs是什么意思?

*args: 可变位置参数。
*kwargs: 可变关键字参数。

2.谈一谈Python中的装饰器

Python中的装饰器其实也是一种函数, 它可以在不修改原函数代码情况下扩展原函数功能。装饰器函数与普通函数不同之处就在于装饰器函数返回了一个函数对象,装饰器利用了闭包的原理来实现。主要用于日志插入,权限管理等等。

3.Python的垃圾回收机制以及内存管理

垃圾回收机制:
作为Python的使用者来说,Python中的垃圾回收主要以引用计数为主,再引入标记、清除,分代为辅来解决循环引用的问题。
一个对象被引用时,引用计数加1,当对象被del时,引用计数减去1,为0时,对象就被清除,一般情况下用户不会去操作Python 的垃圾回收机制,但它留有API接口。
内存管理:
Python使用了内存池机制来管理内存,其内存以金字塔的形式对内存功能进行划分,-1、-2层主要用于对操作系统进行操作, 0层中是C的malloc,、free等等内存分配和释放函数。1、2层是一个内存池, 当对象小于265K时将直接由这片内存池进行分配内存,否则将调用第0层中的C函数来分配内存,当小于265K的对象被销毁时, 其内存也不会被销毁, 只是返回给了内存池以便二次利用。2层是对Python对象进行操作。

4.Python多线程

Python中多线程由于有GIL的影响, 导致在任意时间内只有一个线程在运行,所以Python的多线程在处理计算密集型任务上效果反而不如单线程, 只有在处理IO密集型任务上多线程才能发挥实力,在等待IO过程中Python C源码会释放GIL, 最终会导致线程在等待IO过程中会被暂停去执行其他的线程。python中GIL主要是由于历史原因导致Cpython虚拟机中的GIL难以移除,同时GIL的存在保证了多线程之间数据完整性以及状态同步。

5.说明os、sys模块不同,并列举常用的模块方法

os: 提供了对使用操作系统函数的高度封装
sys: 提供由解释器访问或者维护的变量以及与解释器交互的一些函数

os模块只负责程序与操作系统交互, 提供了访问操作系统底层的接口封装。
sys模块负责程序与解释器交互, 提供了一系列的函数用于操控Python运行的环境设置。
os模块常用方法:
os.getcwd() # 获取当前运行路径
os.remove() # 删除指定的文件
os.walk() # 生成指定目录下的文件夹以及文件
os.makedirs() # 生成多成目录
os.mkdir() # 生成目录
os.rmdir() # 删除指定目录
os.removedir() # 删除多层目录
os.listdir() # 列出指定目录下所有的文件夹以及文件
os.path.join() # 将分离的各部分组合成一个路径名
os.path.getsize() # 获取指定文件大小
os.path.exists() # 查看指定目录或者文件是否存在
os.path.isabs() # 查看指定目录是否为绝对路径

sys模块常用方法:
sys.argv# 命令行参数列表
sys.exit() # 退出程序并返回指定的整数
sys.maxunicode # 最大的Unicode值
sys.modules # 系统导入的模块名称
sys.path # python搜索模块时的路径
sys.stdout # 标准输出
sys.stdin # 标准输入
sys.stderr # 错误输出

6.什么是lambda表达式?它有什么好处?

lambda也是函数的一种, 在处理一些简单的操作时可以使用该表达式, 其好处是不用为一些实现简单功能的函数命名,毕竟编程只有两个难点: 缓存失效, 命名。

7.Python里面如何拷贝一个对象?

Python中拷贝分为深拷贝、浅拷贝。浅拷贝只拷贝父级对象, 不会拷贝对象内部的子对象,使用copy模块中的copy。深拷贝则会完全拷贝父对象以及子对象, 使用copy模块中的deepcopy。

8.__new__和__init__的区别。

__new__负责构建一个类对象并将其返回,init则负责初始化一些变量,不返回任何对象。在实例化一个类时, __new__方法将会先被运行, 其次才运行__init__方法。

9.python中协程?协程的作用?

  • 协程是一种线程工作的机制。正常情况下,一个线程处理一个函数或者是一个程序,但是协程是在处理函数的时候,这个函数还有调用其他函数,也就是还有子函数,所以协程在处理的时候使用这一个线程去处理这两个函数,在处理的时候呢,并不是按顺序执行完一个函数再去执行另一个函数,而是执行A函数到一半的时候又去执行函数,这两个函数相互交替执行,这么个机制,叫做协程。

  • 之前说过多线程在执行的时候,是抢夺资源式的执行任务,在读取同一个变量的时候可能会发生冲突,所以为了防止发生冲突,我们用到了线程锁。通过队列,一个线程写信息,一个线程读消息,线程锁控制线程的等待和队列的读写。

  • 但是协程不会发生这种冲突,因为只有一个线程在进行读取数据的操作,不存在同时读写冲突。

  • 所以协程是控制自身,在子程序之间进行切换

协程的作用:当遇到阻塞就去执行其他的程序,例如遇到yield语句就跳出去执行其他函数

import time
def task_1():while True:print('----1-----')time.sleep(3)yieldprint('++++++1++++++')
def task_2():while True:print('*****2******')time.sleep(3)yieldprint('++++++2++++++')
def main():t1 = task_1()t2 = task_2()while True:next(t1)#执行到t1的yield时,函数暂停,跳出t1的循环,进行到next(t2)next(t2)#执行到t2的yield时,函数暂停,跳出t2的循环,继续往下循环,即next(t1)# 以上在t1/t2两个线程间来回切换,实现了协程的原理,它比线程还小更有效率if __name__ == '__main__':main()

10.Python的异常机制?

Python中异常也是一个对象, 所有的异常的基类都是Exception。捕获异常使用try…except…语法,如果要try与except之间的代码出现了错误并且我们将其异常类型捕获了那么代码将会跳转代except中去执行。还可以使用raise 去手动的触发一个错误,也可以使用assert来触发异常, 只不过assert经常用来在测试中, 并且assert对程序的性能有着极大影响,只有内置的__debug__为True时assert才会执行。

11.python旧式类(经典类)和新式类的区别

经典类与新式类的区别是:继承搜索的顺序发生了改变,经典类多继承搜索顺序是深度优先, 按照从左至右的查找,并且将每一个父类的基类都查找一遍。新式类则是, 先从左至右的查找, 然后再向每一个父类的基类进行查找。(都是从左至右的顺序查找, 经典类查找一个父类时同时向上查找,新式类则是先查找所有的父类然后再向上查找)

2.classmethod,staticmethod,property是什么?有什么作用?

classmethod,staticmethod,property都是装饰器, 他们都作用在类的方法上。
classmethod:使得被装饰的方法成为一个类方法既不需要实例化类就可以直接调用的方法,第一个参数为cls。
staticmethod: 使得被装饰的方法成为一个静态函数既与普通的函数无区别。
property: 将一个方法变成一个属性来使用。

13.python中的绑定方法和未绑定方法是什么

绑定方法:绑定了实例化的方法既第一个参数是self
未绑定方法:没有绑定实例化的方法既类方法、静态方法

14.python上下文管理器是什么

Python中上下文管理器使用with来调用主要用于数据库连接,文件操作, 网络操作。
其作用是: 如果在进行一些打开资源操作时出现了异常,上下文管理器将会自动的执行一些资源清理操作。在进入上下文管理器时, Python会先调用对象的__enter__方法, 该方法返回一个对象用于进行一些操作,如果在进行一些操作时发生了异常Python则调用__exit__该对象接受三个参数第一个参数异常类,第二个参数异常提示字符串, 第三个参数traceback对象。

15.functools的wraps是做什么的?

wraps是一个装饰器功能是: 由于被装饰的函数传入到装饰器中时已经不是原函数了, 而是一个新的函数, 并且丢失一些原函数的属性, 为了不影响函数的使用, 可以使用wraps来抵消这种副作用。

16.ORM实现原理

ORM使用了Python的属性描述符协议实现,通过另外一个类来描述类变量的属性类型, 再给这个属性进行赋值时(对应数据库中的字段名称)会调用__set__方法,访问属性则会调用__get__方法删除则调用__delete__方法。

17.迭代器和生成器区别?

  • 迭代器:
    1、是一个可以记住遍历的位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能往前不会后退。
    2、因为迭代器需要 nextiter 两个方法,所以除了调用next()方法,以及捕获StopIteration异常之外,没有办法检查是否还有遗留元素。此外,也没有办法“还原”迭代器。如果想再次迭代,那就要调用iter(…),传入之前构造迭代器的可迭代对象。传入迭代器本身没用,因为前面说过Iterator.iter 方法的实现方式是返回实例本身,所以传入迭代器无法还原已耗尽的迭代器。
    3、 所以迭代器是这样的对象:实现了无参数的 next 方法,返回序列中的下一个元素;如果没有元素了,那么抛出StopIteration异常。Python中的迭代器还实现了 iter 方法,因此迭代器也可以迭代

  • 生成器:
    1、一种特殊的迭代器, 生成器自动实现了迭代器协议, 不需要手动的实现__iter__以及next方法,生成器在迭代的过程中可以改变当前的迭代值, 而普通的迭代器改变当前值时往往会发生错。迭代器必须实现__iter__以及next方法。
    2、在调用生成器运行的过程中,每次遇到 yield 关键字时函数会暂停并保存当前所有的运行信息,返回 yield 语句的值, 并在下一次执行 next() 方法时从当前位置继续运行,带有 yield 语句的函数不再是一个普通函数,python 解释器会将其视为一个 生成器(generator),所以只要python函数的定义体中有yield关键字,该函数就是生成器函数。

生成器示例
def yield_test():print('这一行被执行')yield 1yield 2run_test = yield_test()
print(next(run_test))  # 输出:这一行被执行   1
print(next(run_test))  # 输出:2
  • 区别
    1、生成器是迭代器的一种实现,所有生成器都是迭代器,因为生成器完全实现了迭代器接口,迭代器用于从集合中取出元素,而生成器用于“凭空”生成元素,生成器相较于迭代器更为简洁,它能极大程度的简化代码,使得执行流程更为清晰。
    2、迭代器需要我们定义一个类来实现相关的方法才能构造一个灵活的迭代器,而生成器则只需要在普通的函数中加入一个yield关键字,yield 语句的作用就是把一个函数变成一个生成器(generator),生成器的出现使得python能类似于协同程序(协同程序的概念一开始有介绍)工作。

17.1 yield与return的区别

  • yield
    包含 yield 关键字的函数体,返回的是一个生成器对象,该对象可以迭代遍历和通过 next() 方法取出对象中的值。能节省内存空间,可以达到随用随取的效果。

  • return
    用于结束函数体的运行,return 后面的代码块不会执行,返回该函数的执行结果。
    在一个生成器函数中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

18.描述一下type()的作用

当type只传入一个参数时将返回该参数的类型,如果传入了三个参数则返回一个类对象,同时Python中的所有类的基类都是type

19.Python中列表与元组的异同?

相同: 列表和元组都是容器并且是可迭代对象,二者可以包含任意类型的对象。
不同:列表是可变的, 元组是不可变。

20.Python中的列表是如何实现的?

Python中的列表使用了分离式技术实现的动态顺序表。

21.Python中列表的索引查询的时间复杂度是多少?

O(1)

22.Python字典的实现原理?

Python的字典使用了哈希表来储存key、value,当添加一个数据时首先会把key通过哈希函数转换成一个数字, 然后将该数字对存放value的数组长度取余并将取余结果当做数组的下标, 将value存放在该取余结果为下标的数组中。数据查询时将key转换为对应的数组下标,并定位到数组的位置获取value。

23.什么是pickling和unpickling?

Pickle模块读入任何Python对象,将它们转换成字符串,然后使用dump函数将其转储到一个文件中——这个过程叫做pickling,反之从存储的字符串文件中提取原始Python对象的过程,叫做unpickling。

24.有哪些工具可以帮助debug或做静态分析?

PyChecker是一个静态分析工具,它不仅能报告源代码中的错误,并且会报告错误类型和复杂度。
Pylint是检验模块是否达到代码标准的另一个工具。
dis用来查看Python对象的字节码。

25.Python中的作用域

在Python中,一个对象的作用于总是由代码被赋值的地方所决定的。当遇见一个变量时Python会按照: 本地作用域→ 当前作用域被嵌入的本地作用域→ 全局/模块作用域→ 内置作用域顺序搜索。

26.Python的参数传递是值传递还是引用传递?

可变对象使用引用传递, 不可变对象使用值传递

27.写一个函数, 输入一个字符串, 返回倒序排列的结果

def reverse(text):return text[::-1]

28.python中is和==的区别

is比较的是对象在内存的地址, ==比较的对象中的值

29.什么是Python的闭包?

内层函数引用了其外部作用域的变量,然后返回内层函数的情况,称为闭包,创建一个闭包必须满足以下几点:
\1. 必须有一个内嵌函数
\2. 内嵌函数必须引用外部函数中的变量,外层空间中被引用的变量叫做层函数的环境变量
\3. 外部函数的返回值必须是内嵌函数
\4. 环境变量和内层非全局函数一起构成了闭包

30. Python的自省?

type(),dir(),getattr(),hasattr(),isinstance()

31.Python并发的解决方案

Twisted是一个事件驱动型的网络引擎,不同于单线程和多线程模式,这种模式不需要过多去关心线程锁的问题,当遇到高并发问题时候,采用twisted会很好解决数据共享的问题。

Tornado既是一个web server,也是web framework。就是说这个web框架有自己内置的web server,在写web时候可以用到它的高性能网络库,甚至有公司拿这个来做游戏的服务器,可以用它处理高并发问题。

Gevent是基于协程的Python网络库,基于libev的快速事件循环,基于greenlet的轻量级执行单元,API的概念和Python标准库一致。

sanic基于uvloop和httptools实现高并发异步网络框架


操作系统相关

1.进程的有哪几种状态以及导致转换的事件。

进程有5种状态:
运行态:该进程正在执行。
就绪态:进程已经做好了准备,只要有机会就开始执行。
阻塞态(等待态):进程在某些事情发生前不能执行,等待阻塞进程的事件完成。
新建态:刚刚创建的进程,操作系统还没有把它加入到可执行进程组中,通常是进程控制块已经创建但是还没有加载到内存中的进程。
退出态:操作系统从可执行进程组中释放出的进程,由于自身或某种原因停止运行。
导致转换的事件:
\1. 空->新建:创建执行一个程序的新进程,可能的事件有:新的批处理作业、交互登录(终端用户登录到系统)、操作系统因为提供一项服务而创建、由现有的进程派生等。
\2. 新建->就绪:操作系统准备好再接纳一个进程时,把一个进程从新建态转换为就绪态。
\3. 就绪->运行:需要选择一个新进程运行时,操作系统的调度器或分配器根据某种调度算法选择一个处于就绪态的进程。
\4. 运行->退出:导致进程终止的原因有:正常完成、超过时限、系统无法满足进程需要的内存空间、进程试图访问不允许访问的内存单元(越界)、算术错误(如除以0或存储大于硬件可以接纳的数字)、父进程终止(操作系统可能会自动终止该进程所有的后代进程)、父进程请求终止后代进程等。
\5. 运行->就绪:最常见的原因是,正在运行的进程到达了“允许不中断执行”的最大时间段,该把处理器的资源释放给其他在就绪态的进程使用了;还有一中原因可能是由于具有更改优先级的就绪态进程抢占了该进程的资源,使其被中断转换到就绪态。
6.运行->阻塞:如果进程请求它必须等待的某些事件,例如一个无法立即得到的资源(如I/O操作),只有在获得等待的资源后才能继续进程的执行,则进入等待态(阻塞态)。
7.阻塞->就绪:当等待的事件发生时,处于阻塞态的进程转换到就绪态。
8.就绪->退出:在上图中没有标出这种转换,在某些进程中,父进程可以在任何时刻终止一个子进程,如果一个父进程终止,所有相关的子进程都被终止。
9.阻塞->退出:跟上一项原因类似。

2.进程与线程的区别。

进程是资源分配的最小单位,线程是程序执行的最小单位。
进程有自己的独立的地址空间, 线程共享进程中的数据,使用相同的地址空间。
进程自己通信方式主要使用特别的方式来进行通信。线程之间的通信非常的方便, 同一进程下的线程共享全局变量、静态变量等数据。
多进程程序更加的健壮,其中一个进程死掉了并不影响其他的进程,多线程中只要有一个线程死掉,那么整个进程也死掉了。

3.进程通信的几种方式。

进程之间进行通信常用的有几种方式:管道,消息队列, 信号量, 共享内存

管道通常指无名管道, 他的特点包括:
1.半双工:数据只能在一个方向流动,一端为读端,一端为写端
2.有关系进程通信: 管道只能在具有亲缘关系的进程之间进行通信,如父子进程、兄弟进程
3.文件: 管道是一种特殊的文件它有着像普通文件读写一样的API, 它只存在于内存中。
Python实现:

import os
from time import sleep
def child(wpipe):while 1:msg = "hello world!".encode()os.write(wpipe, msg)sleep(2)
def parent():rpipe, wpipe = os.pipe()pid = os.fork()if pid == 0:child(wpipe)else:os.close(wpipe)fb = os.fdopen(rpipe, 'r')while 1:recv = os.read(rpipe, 1024)print(recv.decode())
parent()
# 输出
"""
>>> python3.6 ./pipe.py
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
"""

消息队列存放在内核中, 一个消息队列有一个标识符来标识, 它的特点:
1.消息队列是面向记录的, 其中消息具有特定的格式和特点的优先级
2.消息队列独立于发送方和接受方,即使进程终止,消息队列中的消息并不会被删除。所以它可以用于无关进程之间通信
3.消息队列可以对消息实现随机读取, 不需要按在特定的顺序来读取。

信号量属于系统层面, linux系统也是通过信号量来管理进程,进程一旦接收到信号就会打断原来的程序执行流程来处理信号。

import os
import signal
def handler(signalnum, frame):global receive_timesprint("收到信号", signalnum, frame)
def main():print(os.getpid())signal.signal(signal.SIGTERM, handler)while True:pass
if __name__ == '__main__':main()

运行上面程序, 在另一个终端输入 kill pid,程序将会打印
…收到信号 15 <frame object at 0x7ff6ea259630>

共享内存是最简单的通信方式, 他允许多个进程(无关进程, 有关进程)访问同一片内存, 一个进程改变其中的数据后, 其他的进程也能看见数据的变化。共享内存特点:
1.进程共享同一块内存
\2. 访问共享内存和访问私有内存一样快
3.不需要系统调用和内核入口
4.不造成不必要的内存复制
Python可以使用multiprocessing中Value、Array、Manager等等实现

4.线程同步几种方式

线程同步通常有4中方式: 临界区、事件、互斥量、信号量。

临界区:拥有临界区的线程可以访问被保护起来的资源或者代码段, 其他线程如果想访问则被挂起, 直到拥有临界区对象放弃临界区为止。Python中使用:threading.Lock()实现。

事件:可以自定义一个事件, 如果这个事件一直不发生, 则这些线程将会阻塞, 直到事件发生。 Python中使用threading.Event()实现 。

互斥量:互斥量为资源引入了状态:锁定/非锁定, 某个线程要更改共享数据时, 先将其锁定, 此时其他线程不能对该资源进行操作, 直到资源被释放。Python中使用threading.Lock()实现 。

5.用户线程与内核线程的区别

用户线程的优点:
1.线程切换不需要内核态特权, 进程不需要为了线程管理而切换到内核态。
\2. 可以为应用程序量身定做调度算法而不影响系统调度程序。
3.用户级线程可以再多个平台上运行, 不需要对内核进行修改以支持用户级线程。
用户线程的缺点:
1.当一个用户级线程执行一个系统调用时, 不仅这个线程会被阻塞, 进程中的所有线程都会被阻塞。
2.在用户级线程策略中, 一个多线程应用程序不能利用多处理技术。
内核级线程优点:
1.线程切换由内核控制,可以很好的利用多核CPU。
2.由操作系统内核创建和撤销, 一个内核级线程阻塞并不影响其他的线程运行。
内核级线程缺点:
1.由内核进行调度。不能跨平台。
用户级线程和内核级线程的区别:
1.内核线程是内核可感知的, 用户级线程是内核不可感知的。
2.用户级线程创建,撤销等等不需要内核的支持, 内核级线程创建,撤销等等都需要内核的支持。
3.用户级线程在调用系统指令是会导致其所属的进程被中断, 内核级线程在调用系统指令时, 只会导致该线程被中断, 与其他线程无关。
4.用户级线程CPU调度以进程为单位, 用户程序进行线程的控制, 内核级线程CPU以线程为调度单位, 由系统的线程调度程序负责线程的调度工作。
5.用户级线程的程序实体运行在用户态下程序, 而内核级线程的程序则可以运行在任何状态上。

6.进程池、线程池的原理?

线程池: 开启一定数量的线程并让其睡眠, 当需要一个线程去执行某种任务时, 唤醒某个线程让它执行任务, 任务执行完毕又让其睡眠。
进程池同理

7.进程为什么会产生死锁?

导致死锁的原因:
1.因为系统资源不足
2.进程运行推进顺序不合适
3.资源分配不当
导致死锁的四个必要条件:
1.一次一个进程只能访问一个资源, 其他进程不能访问已分配的资源。
2.当一个进程等待其他进程时, 继续占有已分配的资源时
3.不能强行抢占进程已有的资源
4.存在一个封闭的进程链, 导致每一个进程都占有下一个进程所需的资源

8.操作系统的四个特性?

1.并行: 并行是指两个事件以上(包含)在同一时刻发生既物理上这些事件是同时发生的。
2.共享: 系统中的资源可供内存中的多个进程共同使用, 由于资源的属性不同, 多个进程对资源共享方式也不同。
3.虚拟:操作系统中的虚拟通过分时技术将多个物理设备转换成若干个逻辑上的对应物。
4.异步:在多道程序设计环境下允许多个进程并发执行。

9.什么是缓冲区溢出?有什么危害?其原因是什么?

缓存区溢出指计算机在向缓存区填充数据时超过了缓存区的最大值, 溢出的数据覆盖在了合法数据上。
其危害: 程序崩溃, 导致拒绝服务。跳转并执行恶意代码。
造成缓存区溢出的原因主要是没有对用户的输入进行检查。

##10.操作系统中进程调度策略有哪几种?

优先级服务,时间片轮换, 多级反馈


网络相关

1.TCP为什么需要3次握手

三次握手的目的是:防止已失效的连接请求报文又传入到服务端,导致错误。

2.TCP和UDP有什么区别?

tcp是传输控制协议,其提供面向连接、可靠的字节流服务,通信双方必须依照三次握手协议连接之后才能传输数据, tcp提供了超时重传、 丢弃重复数据、检验数据流量控制等功能。
UDP是用户数据包协议, 它提供了一个简单的不可靠的面向无连接的服务,在双方未连接时也能传输数据因而速度特别快。

3.TCP/IP的流量控制?

利用滑动窗口实现流量控制

4.HTTP的长连接和短连接?

短连接: 客户端与服务端每进行一次HTTP操作就建立一次连接,请求结束就断开连接。
长连接:客户端与服务器进行第一次HTTP操作后, TCP连接并不会断开连接, 下次请求将复用这条TCP通道

http://5.IO中同步与异步,阻塞与非阻塞区别

同步和异步关注的是消息通信机制。
同步:发出一个调用时, 在没有得到结果之前这个调用不会返回结果, 如果调用返回那么说明得到结果了。
异步:发出一个调用后立刻返回, 但是返回时没有结果的。
阻塞与非阻塞关注的是程序在等待调用的结果
阻塞:调用结果被返回前该线程被挂起, 直到得到结果后,该线程继续运行。
非阻塞:不能立刻得到结果之前, 该函数不会阻塞当前线程, 会立刻返回。

6.Cookies 和 Session的区别

cookies是一种保存在客户端上的字符串用于用户与服务端会话持久的保持数据
Session是一种保存在服务器的字符串, 其功能与cookies相同, 但是session是在cookies基础上实现的。

7.什么是TCP粘包、TCP粘包发生了怎么处理?

TCP粘包是指发送方发送了若干个包到接收方接受时都粘成了一个包, 从缓存区来看后一个包的头部数据紧紧的接着前一个包的尾部。
对于TCP粘包的情况有两种处理方式:
\1. 接收方: 可以选择关闭tcp默认的nagle算法来避免粘包
2.应用层处理: 格式化数据, 对于每一条数据都采用相同的格式必须有开始符以及结束符, 这样即使发生粘包也可以通过开始符和结束符判断数据边界, 也可以在数据开头就将该条数据的长度填充进数据中, 如果发生粘包则可以使用数据长度来区分每一条数据。
UDP不会发生粘包, 因为UDP没有使用块的合并优化算法,导致接收端的缓存区内按照链式的结构来储存每一个UDP包, 并且每一个UDP包都有消息头,这样接收方就很好的进行拆包。

8.TCP中的time_wait是什么情况?出现过多的close_wait可能是什么原因?

timewait值tcp中主动断开连接一方的一个状态, 当主动断开连接的一方发送给对方FIN包,且对方回复了ACK+FIN时, 主动断开连接的一方将进入time_wait状态, 并持续到2msl后进入CLOSE状态。
出现过多的close_wait的原因:被动关闭方未关闭socket造成。
解决办法:
1.为socket设置超时
2.调整系统参数, 包括句柄参数和TCP/IP参数

9.epoll,select的区别?边缘触发,水平触发区别?

epoll将每一个监听事件都储存在了红黑树中并且只返回被触发的事件。epoll在睡眠结束后只需要检测就绪链表是否为空。
select则将时间都放入一个列表中, 当其中某个事件被触发时,select将所有的事件返回给用户。select睡眠结束后需要遍所有的监听事件。

10. tcp三次握手, 四次挥手

三次握手:
客户端 服务端
->SYN=1, seq=x
<-ACK=1, ack=x+1, seq=y, SYN=1
-> ACK=1, ack=y+1, seq=x+1
<-> data
四次挥手:
主动关闭方 被动关闭方
<-> data
->FIN=1, seq=x
<- ACK=1, seq=y, ack=x+1
<- FIN=1, ACK=1, seq=z, ack=x+1
-> ACK=1, ack=z+1, seq=x+1


数据储存与缓存相关

1.数据库事务的四个特性及含义

数据库事务的4个特性:原子性、持久性、一致性、隔离性
原子性:整个事务中的所有操作要么全部完成, 要么全部都不完成, 如果在事务中操作出现异常,那么事务将会进行回滚, 就像这个事务从来没有执行过一样。
持久性:在事务完成后,该事务所有的操作都将持久化在数据库中, 不会被回滚。
一致性:在事务开始之前和事务结束之后, 数据库的完整性约束并没有被破坏。
隔离性:确保在同一时间类只有一个事务处理某个数据。

2.数据库索引使用了什么数据结构?

数据库索引对于非主键索引使用B树, 对于主键索引使用B+树

3.数据库优化的思路

SQL语句优化:
\1. 尽量避免在where语句后面使用 !=、<>操作符以及对NULL值得判断, 否则引擎将放弃索引而使用全表扫描。
\2. 使用exists替换in。
\3. 尽量放弃使用select *, 需要什么数据就取出什么数据。
\4. 使用join代替子查询。
\5. 设置合适的字段属性:例如尽量把字段设置为NOT NULL, 这样引擎就不要对比NULL值

4.MySQL中myisam与innodb的区别

\1. innodb支持事物, myisam不支持事物
\2. innodb支持行级锁, myisam支持表级锁
\3. innodb支持MVC, myisam不支持
\4. innodb支持外键, myisam不支持
\5. innodb不支持全文索引,myisam支持

5.Redis支持的数据类型

字符串,集合, 有序集合,哈希, 列表

6.redis持久化的几种方式

1. 快照: 默认使用这种方式,将数据快照存放在特定的二进制文件中。
2. AOF: 将每一条命令都储存, 恢复时再将每一天命令进行运行。

7. redis如何实现热数据缓存?

当redis的内存数据大小上升到一定大小时, 就会实施数据淘汰策略, redis提供了6中数据淘汰策略
volatile-LRU:从已经设置过期时间的数据中挑选最近最少使用的数据淘汰
volatile-TTL: 从已经设置过期时间的数据中挑选即将要过期的数据淘汰
volatile-RANDOM: 从已经设置过期时间的数据中随机选择数据进行淘汰
allkeys-LRU:从数据集中挑选最近最少使用的数据淘汰
allkeys-random:从数据集中任意选择数据淘汰
no-enviction:禁止驱逐数据

8.Redis 常见的性能问题都有哪些?

\1. master写内存快照, save命令调度rdbSave函数会阻塞主线程的工作, 可能会导致间断性的暂停服务。
\2. master AOF持久化, 最好不要使用AOF来进行持久化, 这个持久化方式对性能有着极大的影响。
\3. redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。

9.mysql字符集和排序规则?

mysql中一个字符集至少有一个或者多个排序方式, 比如utf8就有:utf8_general_ci , utf8_general_cs等等。
排序规则命名规则:字符集名字_语言_后缀, 其中
\1. _ci:不区分大小写的排序方式
\2. _cs:区分大小写的排序方式
\3. _bin:二进制排序方式,大小比较将根据字符编码,不涉及人类语言,因此_bin的排序方式不包含人类语言
字符集最常用的包括utf8, utf8md4。

10.varchar与char的区别是什么?大小限制?utf8字符集下varchar最多能存多少个字符?

char和varchar最大的不同就是一个是固定长度,一个是可变长度。由于是可变长度,因此存储的是实际字符串再加上一个记录字符串长度的字节。如果分配给char或varchar列的值超过 列的最大长度,则对值进行裁剪。

varchar(M)和char(M),M都表示字符数.varchar的最大长度为65535个字节,不同的编码所对应的最大可存储的字符数不同。char最多可以存放255个字符,不同的编码最大可用字节数不同。

字符类型若为utf8,每个字符最多占3个字节,varchar最大长度不能超过21845。

11.primary key和unique的区别?

一个表只能有一个primary key, 一个表可以有多个unique key。
unique key约束只针对非主键列, 可以为空值, primary key约束针对主键列, 不允许有空值。

12.外键有什么用,是否该用外键?外键一定需要索引吗?

外键是为了一张表记录的数据不会太过冗余,也是为了数据的一致性和完整性。

如果业务逻辑相当的复杂那么建议使用外键来保证数据的一致性和完整性, 如果业务逻辑不复杂则可以不使用外键, 仅靠程序中来保证数据的一致性和完整性, 或者业务对数据的一致性完整性要求相当的高, 那么一定要用外键。同时如果为了不让mysql在性能有任何的形象应该避免使用外键。 所有应该视当前业务,数据等情况决定是否使用外键。

外键需要索引, 因为外键在查询,更新,删除数据时会对数据进行查找, 所以需要对外键建立索引。

13.索引有什么用?

对于建立索引的列, mysql的查询效率会提高很多。

14.redis的事务?用事务模拟原子+1操作?原子操作还有其它解决方案吗?

redis的事务使用关键字multi开启事务, 使用exec执行事务中的语句,它可以执行多条语句, 所有的命令按照先进先运行的的运行, 不会被其他的命令加塞。
用事务模拟原子+1操作:
multi
incr xx
exec
原子操作 可以使用 incr操作实现

1.python的常用的数据结构有哪些?

Python中常见的数据结构可以统称为容器。
序列(如列表和元组)、
映射(如字典)
集合(set)是三类主要的容器。

2.python的常用的数据类型?

可变数据类型:列表、字典、集合
不可变数据类型:数字、元组、字符串

dict和list比较
dict特点:
1.查找和插入的速度极快,不会随着key的增加而增加
2.需要占用大量的内存,内存浪费多
3.dict是用空间来换取时间的一种方法

list的特点
1.查找和插入的时间随着元素的增加而增加
2.占用空间小,浪费内存很少
python怎么让列表去重(set)

tuple与list的区别
元组的特点:
1.比列表操作速度快
2.对数据“写保护“
3.可用于字符串格式化中
4.可作为字典的key

3.python生成随机数 random(0,10)可以生成包含0~10的随机数吗?

不包含0和10

4.python反转列表

reverse

li5 = [111, 22, 31, 41, 5, 6, 888, 8, 34, 8, 12, 7, 33]
li5.reverse()li5.reverse()
print(li5)
1
2
3
结果:

5.python中有没有用过装饰器、用装饰器的场景,理解装饰器中的逻辑吗?

简单来说装饰器就是一个函数,它的作用就是装饰一个其他的函数,用法就是@+定义的函数名,这样他在运行新函数前会先去运行调用的装饰器函数,这种被成为语法糖

https://mp.weixin.qq.com/s/nc9Lz9E3pHJdI16g82FK2w

6. python的匿名函数是什么?

https://zhuanlan.zhihu.com/p/78698111

匿名函数不需要显示地定义函数名,使用【lambda + 参数 +表达式】的方式,即:

lambda [arg1 [,arg2, … argN]] : expression
也就是说,lambda用来表示匿名函数,可以传入多个参数,但只能有一个表达式。

匿名函数的优点是什么呢?
不用取名称,因为给函数取名是比较头疼的一件事,特别是函数比较多的时候
可以直接在使用的地方定义,如果需要修改,直接找到修改即可,方便以后代码的维护工作
语法结构简单,不用使用def 函数名(参数名):这种方式定义,直接使用lambda 参数:返回值 定义即可

7. Python 函数参数前面一个星号(*)和两个星号(**)的区别

https://mp.weixin.qq.com/s/5EfcHd8_-gLTjTkF6htIag

8. 两个列表,list1 = [1,2,3], list2= [4,5,6], 怎么扩展让list1=[1,2,3,4,5,6,]

list1.extend(list2)

9.list1 = [1,2,3], list2= [1,2,4,5,6]怎么取出两个列表不一样的内容 ?

可以将他们先合并再去重
list3=list1.extend(list2)
list4=list(set(list3))

10. 列表用下标可以改变赋值,字符串可以吗 ?

不可以,字符串、数字、元组是不可变数据类型

11. 想要改变字符串的某一个元素应该怎么办?

12. 正则表达式限制只能输入5个数字, 应该怎么写正则表达式语句?

13. json跟字典的区别

JSON是一种轻量级的数据交换格式采用完全独立于编程语言的文本格式来存储和表示数据拥有简洁和清晰的层次结构
字典属于python语言中的一种可变数据类型,由python编译器进行识别
json.dumps() --》将dict转换成json
json.loads()—>将json转换成python识别的dict

14. 字典怎么遍历 key, value,如果同时要遍历key 和value 呢?

15. 如何将两个列表转化未一个字典,列表a的值作为 key,列表b的值作为 value?

import numpy as np

a = np.array([‘a’, ‘b’, ‘c’, ‘d’])
b = np.array([2, 2, 4, 12])

dict1 = dict(zip(a, b))

#结果
{‘a’: 2, ‘b’: 2, ‘c’: 4, ‘d’: 12}

1 Python垃圾回收机制是什么

作为Python的使用者来说,Python中的垃圾回收主要以引用计数为主,再引入标记、清除,分代为辅来解决循环引用的问题。

一个对象被引用时,引用计数加1,当对象被del时,引用计数减去1,为0时,对象就被清除,一般情况下用户不会去操作Python 的垃圾回收机制,但它留有API接口。

2 元组和列表的区别

主要区别是列表是可变的,而元组是不可变的。

mylist=[1,3,3]
mylist[1]=2

mytuple=(1,3,3)
mytuple[1]=2
Traceback (most recent call last):
File “<pyshell#97>”, line 1, in

3 元组可以作为字典的key?
首先一个对象能不能作为字典的key, 就取决于其有没有__hash__方法。 所以除了容器对象(list/dict/set)和内部包含容器对象的tuple 是不可作为字典的key, 其他的对象都可以。

4 进程 线程 协程

4.1 进程

1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立

2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制

多进程-进程池

# 生产者消费者_进程池import time
import random
from multiprocessing import Pool, Managerdef producer(num, buf, lock):run_flag = Truecount = 0while run_flag:t = random.uniform(0.1, 1.2)time.sleep(t)  # 模拟生产时间p = chr(random.randint(65, 90))  # 产品是随机生成的大写的英文字母with lock:f = open('mess.txt', 'a')if not buf.full():#print('生产者 {} 花费时间 {:.3f} 生成一个产品 {}'.format(num, t, p))buf.put(p)  # 加入缓冲区#print(f'此时,缓冲区中的产品个数为 {buf.qsize()}')f.write('生产者 {} 花费时间 {:.3f} 生成一个产品 {}\n'.format(num, t, p))f.write(f'此时,缓冲区中的产品个数为 {buf.qsize()}\n')f.close()else:count += 1if count == 5:run_flag = Falsereturn f'生产者 {num} 退出'def consumer(num, buf, lock):run_flag = Truecount = 0while run_flag:t = random.uniform(0.1, 1.2)time.sleep(t)  # 模拟消费时间with lock:f = open('mess.txt', 'a')if not buf.empty():p = buf.get()  # 从缓冲区中读取并删除#print('消费者 {} 花费时间 {:.3f} 消费一个产品 {}'.format(num, t, p))#print(f'此时,缓冲区中的产品个数为 {buf.qsize()}')f.write('消费者 {} 花费时间 {:.3f} 消费一个产品 {}\n'.format(num, t, p))f.write(f'此时,缓冲区中的产品个数为 {buf.qsize()}\n')f.close()else:count += 1if count == 3:run_flag = Falsereturn f'消费者 {num} 退出'if __name__ == '__main__':manager = Manager()  # 进程池中使用队列需要 Manager 类n = 10buf = manager.Queue(n)  # 通信队列lock = manager.Lock()  # 锁pool = Pool()  # 进程池,省略参数,默认使用 cpu 数量proces = []for i in range(2):proces.append(pool.apply_async(producer, (i, buf, lock,)))proces.append(pool.apply_async(consumer, (i, buf, lock,)))pool.close()  # 不再加入新进程pool.join()for it in proces:print(it.get())

4.2 线程

1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源

2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃

多线程实现

# 生产者消费者问题 --- 多线程实现import time
import random
from threading import Thread, Locklock = Lock()  # 锁n = 10
buf = []class producer(Thread):def __init__(self, num):super().__init__()self.num = numself.run_flag = Truedef run(self):count = 0while self.run_flag:t = random.uniform(0.1, 1.2)time.sleep(t)  # 模拟生产时间p = chr(random.randint(65, 90))  # 产品是随机生成的大写的英文字母with lock:if len(buf) < n:print('生产者 {} 花费时间 {:.3f} 生成一个产品 {}'.format(self.num, t, p))buf.append(p)  # 加入缓冲区print('--------------', buf, '---------------')else:count += 1if count == 7:self.stop()print(f'生产者 {self.num} 退出')def stop(self):self.run_flag = Falseclass consumer(Thread):def __init__(self, num):super().__init__()self.num = numself.run_flag = Truedef run(self):count = 0while self.run_flag:t = random.uniform(0.1, 1.2)time.sleep(t)  # 模拟消费时间with lock:if len(buf) > 0:print('消费者 {} 花费时间 {:.3f} 消费一个产品 {}'.format(self.num, t, buf[0]))del buf[0]  # 移出缓冲区print('--------------', buf, '---------------')else:count += 1if count == 4:self.stop()print(f'消费者 {self.num} 退出')def stop(self):self.run_flag = Falseif __name__ == '__main__':pros = []cons = []for i in range(3):p = producer(i)p.start()pros.append(p)for i in range(2):c = consumer(i)c.start()cons.append(c)for p in pros:p.join()for c in cons:c.join()

4.3 协程

'''
协程:协程是一种线程工作的机制。协程不是进程,也不是线程,它就是一个函数,一个特殊的函数——可以在某个地方挂起,并且可以重新在挂起处继续运行正常情况下,一个线程处理一个函数或者是一个程序,但是协程是在处理函数的时候,这个函数还有调用其他函数,也就是还有子函数,所以协程在处理的时候使用这一个线程去处理这两个函数,在处理的时候呢,并不是按顺序执行完一个函数再去执行另一个函数,而是执行A函数到一半的时候又去执行函数,这两个函数相互交替执行,这么个机制,叫做协程。(栗子:生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高)协程与进程、线程的比较:1 协程既不是进程,也不是线程,协程仅仅是一个特殊的函数,协程跟他们就不是一个维度。2 一个进程可以包含多个线程,一个线程可以包含多个协程。3 一个线程内的多个协程虽然可以切换,但是这多个协程是串行执行的,只能在这一个线程内运行,没法利用CPU多核能力。4 协程与进程一样,它们的切换都存在上下文切换问题。生成器的yield实现了协程的工作机制
'''
import time
def task_1():while True:print('----1-----')time.sleep(3)yieldprint('++++++1++++++')
def task_2():while True:print('*****2******')time.sleep(3)yieldprint('++++++2++++++')
def main():t1 = task_1()t2 = task_2()while True:next(t1)#执行到t1的yield时,函数暂停,跳出t1的循环,进行到next(t2)next(t2)#执行到t2的yield时,函数暂停,跳出t2的循环,继续往下循环,即next(t1)# 以上在t1/t2两个线程间来回切换,实现了协程的原理,它比线程还小更有效率if __name__ == '__main__':main()

5 赋值、浅拷贝和深拷贝

深拷贝就是将一个对象拷贝到另一个对象中,这意味着如果你对一个对象的拷贝做出改变时,不会影响原对象。在Python中,我们使用函数deepcopy()执行深拷贝

浅拷贝则是将一个对象的引用拷贝到另一个对象上,所以如果我们在拷贝中改动,会影响到原对象

6 GIL

GIL是python的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行python程序的时候会霸占python解释器(加了一把锁即GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。

多进程中因为每个进程都能被系统分配资源,相当于每个进程有了一个python解释器,所以多进程可以实现多个进程的同时运行,缺点是进程系统资源开销大

7 列表去重

先通过转换为集合去重,在转列表

8 最常用的排序算法及其复杂度

8.1 冒泡排序

外层循环从1到n-1,内循环从当前外层的元素的下一个位置开始,依次和外层的元素比较,出现逆序就交换,通过与相邻元素的比较和交换来把小的数交换到最前面。
def bubbleSort(array):if len(array) < 2:return arrayelse:isSorted = Falsecounter = 0while not isSorted:isSorted = Truefor idx in range(len(array) - 1 - counter):if array[idx] > array[idx + 1]:isSorted = False(array[idx + 1], array[idx]) = (array[idx], array[idx + 1])counter += 1在这里插入代码片return array

8.3 快速排序

通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

1、选定Pivot中心轴

2、从R指针开始,将大于Pivot的数字放在Pivot的右边

3、将小于Pivot的数字放在Pivot的左边

4、分别对左右子序列重复前三步操作

def quickSort(array):print(array)if len(array) < 2:return arrayelse:pivot_index = 0pivot = array[pivot_index]less_part = [i for i in array[pivot_index+1:] if i <= pivot]large_part = [i for i in array[pivot_index+1:] if i > pivot]return quickSort(less_part) + [pivot] + quickSort(large_part)

9 闭包

函数的返回值是函数对象,只有外部函数才可以对他进行访问,提高了安全性

10 with

with语句的使用,可以简化了代码,有效避免资源泄露的发生

打开文件在进行读写的时候可能会出现一些异常状况,如果按照常规的f.open

写法,我们需要try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行finally f.close()关闭文件,with方法帮我们实现了finally中f.close

11 实例方法 静态方法

实例方法只能被实例调用,静态方法(@由staticmethod装饰器的方法)、类方法(由@classmethod装饰器的方法),可以被类或类的实例对象调用。

1、实例方法,第一个参数必须要默认传递实例对象,一般使用self。

2、静态方法,参数没有必要。

3、类方法,第一个参数必须要默认传递,一般使用cls。

12 迭代器和生成器

12.1 迭代器

迭代器是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器有两个基本的方法:iter() 和 next()。

字符串,列表或元组对象都可用于创建迭代器:

list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
print (next(it)) # 输出迭代器的下一个元素
1
print (next(it))
2

12.2 生成器

使用了yield的函数被称为生成器

生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行

13 匿名函数

Python客栈送红包、纸质书
print [(lambda x:x*x)(x)for x in range(5)]
[0, 1, 4, 9, 16, 25]

14 map reduce filter

14.1 map
对可迭代对象中的每个元素进行相同的操作
def fn(x):return x+1resp = map(fn,li)
print(list(resp))[2, 3, 4]14.2 reduce
从左到右对一个序列的项累计地应用有两个参数的函数,以此合并序列到一个单一值。(例如累加或累乘列表元素等等)from functools import reduce
nums=[1, 2, 3, 4]
def fn(x, y):return x * yresp = reduce(fn, nums)
print(resp)

24

14.3 filter
filter函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。该接收两个参数: 第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表

1
2
3
4
5
6
7
8
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def fn(a):
return a%2 == 1

newlist = filter(fn, a)
newlist = [i for i in newlist]
print(newlist)

输出: [1, 3, 5, 7, 9]

Django

1 什么是wsgi

Python Web Server Gateway Interface,翻译过来是Python web服务器网关接口,实际上就是一种协议,我们的应用(Django,Flask)实现了WSGI,就可以配合实现了WSGI(uWSGI,gunicorn)的服务器工作了

2 django请求的生命周期

前端发送请求
wsgi, 他就是socket服务端,用于接收用户请求并将请求进行初次封装,然后将请求交给web框架(Flask、Django)
中间件处理请求,帮助我们对请求进行校验或在请求对象中添加其他相关数据,例如:csrf、request.session
路由匹配,根据当前请求的URL找到视图函数,如果是FBV写法,通过判断method两类型,找到对应的视图函数;如果是CBV写法,匹配成功后会自动去找dispatch方法,然后Django会通过dispatch反射的方式找到类中对应的方法并执行
视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:orm、view视图将数据渲染到template模板
视图函数执行完毕之后,会把客户端想要的数据返回给dispatch方法,由dispatch方法把数据返回经客户端
中间件处理响应
wsgi,将响应的内容发送给浏览器
浏览器渲染

3 列举django的内置组件

Admin: 对model中对应的数据表进行增删改查提供的组件
model:负责操作数据库
form:1.生成HTML代码 2.数据有效性校验 3校验信息返回并展示
ModelForm: 即用于数据库操作,也可用于用户请求的验证

4 列举django中间件的5个方法?以及django中间件的应用场景

process_request : 请求进来时,权限认证
process_view : 路由匹配之后,能够得到视图函数
process_exception : 异常时执行
process_template_responseprocess : 模板渲染时执行
process_response : 请求有响应时执行

5 简述什么是FBV和CBV

FBV和CBV本质是一样的,基于函数的视图叫做FBV,基于类的视图叫做CBV

在python中使用CBV的优点:

提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

6 django的request对象是在什么时候创建的

1
2
class WSGIHandler(base.BaseHandler):request = self.request_class(environ)
请求走到WSGIHandler类的时候,执行cell方法,将environ封装成了request

7 如何在CBV添加装饰器

7.1 方法
1
2
3
4
5
from django.utils.decorators import method_decorator@method_decorator(check_login)
def post(self, request):
...7.2 dispatch
1
2
@method_decorator(check_login)
def dispatch(self, request, *args, **kwargs):7.3 类@method_decorator(check_login, name="get")
@method_decorator(check_login, name="post")
class HomeView(View):
...

8 列举django orm 中所有的方法

<1> all(): 查询所有结果
<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象。获取不到返回None
<3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个。
如果符合筛选条件的对象超过一个或者没有都会抛出错误。
<4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
<5> order_by(*field): 对查询结果排序
<6> reverse(): 对查询结果反向排序
<8> count(): 返回数据库中匹配查询(QuerySet)的对象数量。
<9> first(): 返回第一条记录
<10> last(): 返回最后一条记录
<11> exists(): 如果QuerySet包含数据,就返回True,否则返回False
<12> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的
并不是一系 model的实例化对象,而是一个可迭代的字典序列
<13> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
<14> distinct(): 从返回结果中剔除重复纪录

9 select_related 和 prefetch_related的区别

有外键存在时,可以很好的减少数据库请求的次数,提高性能

select_related 通过多表 join 关联查询, 一次性获得所有数据, 只执行一次SQL查询

prefetch_related 分别查询每个表, 然后根据它们之间的关系进行处理, 执行两次查询

10 django 中 csrf 的实现机制

第一步:django第一次响应来自某个客户端的请求时,后端随机产生一个token值,把这个token保存在SESSION状态中;同时,后端把这个token放到cookie中交给前端页面;

第二步:下次前端需要发起请求(比如发帖)的时候把这个token值加入到请求数据或者头信息中,一起传给后端;Cookies:{csrftoken:xxxxx}

第三步:后端校验前端请求带过来的token和SESSION里的token是否一致。

11 django中如何实现orm表中添加数据时创建一条日志记录

# 使用Django的信号机制,可以在添加、删除数据前后设置日志记录:
pre_init    # Django中的model对象执行其构造方法前,自动触发
post_init   # Django中的model对象执行其构造方法后,自动触发
pre_save    # Django中的model对象保存前,自动触发
post_save   # Django中的model对象保存后,自动触发
pre_delete  # Django中的model对象删除前,自动触发
post_delete # Django中的model对象删除后,自动触发#使用
@receiver(post_save, sender=Myclass)       # 信号接收装饰器。由于内置信号,所以直接接收
def signal_handler(sender, **kwargs):      # 接收到信号后,在此处理logger = logging.getLogger()logger.success('保存成功')

12 django缓存如何设置

CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache',  # 缓存后台使用的引擎'TIMEOUT': 300,            # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期)'OPTIONS':{'MAX_ENTRIES': 300,          # 最大缓存记录的数量(默认300)'CULL_FREQUENCY': 3,          # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)},}
}

13 django的缓存能使用redis吗?如果可以的话,如何配置

CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient","CONNECTION_POOL_KWARGS": {"max_connections": 100}# "PASSWORD": "密码",}}
}

14 django路由系统中name的作用

主要是通过name的值,来查找url地址,可以理解为反射作用。在html模板中使用name来反射url优势就是后期url规则发生改变之后,只需调整urls.py即可,所有的模板文件都不需要修改。

15 django rest framework框架中都有那些组件

认证
权限(授权)
用户访问次数/频率限制
版本
解析器(parser)
序列化
分页
路由系统
视图
渲染器

16 简述 django rest framework框架的认证流程

当用户进行登录的时候,运行了登录类的as_view()方法,进入了APIView类的dispatch方法
执行self.initialize_request这个方法,里面封装了request和认证对象列表等其他参数
执行self.initial方法中的self.perform_authentication,里面运行了user方法
再执行了user方法里面的self._authenticate()方法

17.进程与线程的区别。

进程是资源分配的最小单位,线程是程序执行的最小单位。
进程有自己的独立的地址空间, 线程共享进程中的数据,使用相同的地址空间。
进程自己通信方式主要使用特别的方式来进行通信。线程之间的通信非常的方便, 同一进程下的线程共享全局变量、静态变量等数据。
多进程程序更加的健壮,其中一个进程死掉了并不影响其他的进程,多线程中只要有一个线程死掉,那么整个进程也死掉了。

18.Hadoop、Hive和Spark的具体介绍,它们之间主要有什么关系?

hadoop:Apache Hadoop软件库是一个框架,它允许使用简单的编程模型跨计算机集群的大型数据集的分布式处理。

它被设计成从单个服务器扩展到数千台机器,每个机器提供本地计算和存储。而不是依靠硬件上提供高可用性,本身的设计目的是检测和处理应用程序层的故障。

hadoop理解:用多台廉价的计算机组成集群,替代传统的服务器。每台机器都可以存储和计算。

1.数据文件被分成多个块存储在各个计算机上,提供冗余备份机制。这样,单台计算机坏掉数据也不会丢失。这就是HDFS分布式文件存储系统。

2.hadoop集群上的每台计算机都有自己的cpu,充分利用这些cpu进行并行计算。可以理解为一个计算任务被拆分为多个部分,分配到集群下的计算机上,多台机器并行计算然后再将结果汇总。这就是mapreduce。

hive:基于hadoop的数据仓库工作,可以将结构性的数据映射成一张数据库表,提供HiveQL语句(类sql),并将其转化为mapreduce任务运行在hadoop上。

hive理解:本质就是MapReduce,简化了MapReduce任务的开发。让使用sql语言的人可以很快的进行大数据的开发

spark:Spark是基于内存计算的大数据并行计算框架。Spark基于内存计算,提高了在大数据环境下数据处理的实时性,

同时保证了高容错性和高可伸缩性,允许用户将Spark部署在大量廉价硬件之上,形成集群

spark理解:思想与MapReduce相同,但是是基于内存计算,速度更快。

Hadoop、Hive、Spark之间的关系?

hadoop:一个大脑加一个口袋构成一个单体,大脑负责计算数据,口袋负责存储数据。多个单体构成集群。

hive:使用HiveQL语句,将其转化成MapReduce任务,让多个大脑同时计算存储在多个口袋里的数据。

spark:多个更聪明的大脑组成的集群,计算存储在hadoop集群上的数据。计算速度很快,可以进行实时的应用。

python web面试题部分汇总相关推荐

  1. 110 道 Python 面试笔试题超强汇总

    本 Chat 为免费基础入门篇,获取更多面试知识点请大家参阅我的另一个 Chat :致金三银四辛勤找工作的你们:Python 面试必备. 本 Chat 你将会获得以下知识: 110 道 Python ...

  2. 面试前赶紧看了5道Python Web面试题,Python面试题No17

    目录 本面试题题库,由公号:非本科程序员 整理发布 第1题: Flask中的请求上下文和应用上下文是什么? 第2题:django中间件的使用? 第3题: django开发中数据做过什么优化? 第4题: ...

  3. 110道Python面试笔试题超强汇总

    1.一行代码实现1--100之和 利用sum()函数求和 print(sum(range(1,101))) 2.如何在一个函数内部修改全局变量 利用global 修改全局变量 a=5 def fun( ...

  4. Python的面试题/测试题汇总,带答案

    *来源于网络整理 1.what does the following code do?(B) def a(b, c, d): pass A.defines a list and initializes ...

  5. 笔试、面试题收集(主要是Python Web开发)编辑中。。。

    Python 语言 1 Python的函数参数传递 <Python 学习手册> 看两个例子: a = 1 def fun(a):a = 2 fun(a) print a # 1 a = [ ...

  6. Python二级考试试题汇总(史上最全)

    Python二级考试试题(一) ✅作者简介:大家好我是编程ID

  7. python软件测试面试题2020_【面试】2020软件测试面试题及答案汇总

    Time will tell. 1.你的测试职业发展是什么?你自认为做测试的优势在哪里? 测试经验越多,测试能力越高.所以我的职业发展是需要时间累积的,一步步向着高级测试工程师奔去.而且我也有初步的职 ...

  8. java面试笔试题大汇总

    java面试笔试题大汇总 JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题 ...

  9. Java集合方面的面试题大汇总

    集合容器概述 什么是集合 集合框架:用于存储数据的容器. 集合框架是为表示和操作集合而规定的一种统一的标准的体系结构. 任何集合框架都包含三大块内容:对外的接口.接口的实现和对集合运算的算法. 它减少 ...

最新文章

  1. 董东 java_Java面向对象程序设计
  2. 怎样将计算机添加桌面快捷方式,Win10系统下如何将程序快捷方式添加到桌面上?【图文教程】...
  3. 前后端分离架构一直没机会实战?1周完成Vue+Core WebApi移动商城实战(含源码)!...
  4. 前端学习(573):margin无效情形table无效
  5. 新能源补贴退坡 广汽新能源、比亚迪不涨价 蔚来最狠!
  6. Linux服务器安装JavaWeb环境(二) Redis,MySql,Zookeeper,Keepalive
  7. 3Sum Closest
  8. Intel笔记本处理器发展简史(二)
  9. NonEmpty和Hierarchize嵌套的bug
  10. IT讲师韩顺平:我为什么辞去百万年薪,自己创业?
  11. DOSBox安装及使用详解
  12. VASP_Si的能带结构计算_步骤整理
  13. Unity_粒子系统特效制作_051
  14. Elasticsearch笔记
  15. 购买Blender cloud支援今年官方开源电影Gooseberry
  16. eclipse运行出现unable to launch 错误
  17. 图片加载失败后---加载默认图片
  18. 台式计算机一般多大功率,电脑的功率有多大,台式电脑的功率是多少
  19. 畅通无阻的公式:乘员组从几乎破产变成了吸引500万游客的方式
  20. 临床病理的计算机辅助读片,第二军医大学附属长海医院病理科

热门文章

  1. 量子力学奇妙之旅-算符和电子自旋
  2. 《小鸡快跑》的成功故事
  3. spring cloud 实现服务不间断
  4. 食品科学与工程考研可以考计算机吗,食品科学与工程女汉子,对于考研比较迷茫,有几个问题麻烦各位前辈指点迷津,谢谢 。 - 考研 - 小木虫 - 学术 科研 互动社区...
  5. A2. Gsensor调试
  6. android 彻底 关 亮度,Android设置屏幕亮度为0关闭屏幕 – 如何避免
  7. ZooKeeper篇:2PC、3PC以及ZAB协议
  8. 你的每行代码值多少钱?
  9. js layui跳转页面_Layui数据表格跳转到指定页的实现方法
  10. 实训日记(二)——分镜