第1题: python下​​多线程​​的限制以及​​多进程​​中传递参数的方式?

python多线程有个全局解释器锁(global interpreter lock),简称GIL,这个GIL并不是python的特性,他是只在Cpython解释器里引入的一个概念,而在其他的语言编写的解释器里就没有这个GIL例如:Jython。

这个锁的意思是任一时间只能有一个线程运用解释器,跟单cpu跑多个程序一个意思,我们都是轮着用的,这叫“并发”,不是“并行”。

为什么会有GIL?

多核CPU的出现,充分利用多核,采用多线程编程慢慢普及,难点就是线程之间数据的一致性和状态同步

说到GIL解释器锁,我们容易想到在多线程中共享全局变量的时候会有线程对全局变量进行的资源竞争,会对全局变量的修改产生不是我们想要的结果,而那个时候我们用到的是python中线程模块里面的互斥锁,哪样的话每次对全局变量进行操作的时候,只有一个线程能够拿到这个全局变量;看下面的代码:

import threading
global_num = 0


def test1():
global global_num
for i in range(1000000):
global_num += 1

print("test1", global_num)


def test2():
global global_num
for i in range(1000000):
global_num += 1

print("test2", global_num)

t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
t2.start()


接下来加入互斥锁

import threading
import time
global_num = 0

lock = threading.Lock()

def test1():
global global_num
lock.acquire()
for i in range(1000000):
global_num += 1
lock.release()
print("test1", global_num)


def test2():
global global_num
lock.acquire()
for i in range(1000000):
global_num += 1
lock.release()
print("test2", global_num)

t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
start_time = time.time()

t1.start()
t2.start()


哪些情况适合用多线程呢:

只要在进行耗时的IO操作的时候,能释放GIL,所以只要在IO密集型的代码里,用多线程就很合适

哪些情况适合用多进程呢:

用于计算密集型,比如计算某一个文件夹的大小

多进程间同享数据

多进程间同享数据,能够运用multiprocession.Value和multiprocessing.Array

第2题:解释一下python的and-or语法

bool and a or b

相当于bool? a: b

>>> a = "first"
>>> b = "second"
>>> 1 and a or b # 输出内容为 'first'
>>> 0 and a or b # 输出内容为 'second'


上述内容你应该可以理解,但是还存在一个问题,请看下面的代码

>>> a = ""
>>> b = "second"
>>> 1 and a or b # 输出内容为 'second'


因为 a 是一个空串,空串在一个布尔环境中被Python看成假值,这个表达式将“失败”,且返回 b 的值。
如果你不将它想象成象 bool ? a : b 一样的语法,而把它看成纯粹的布尔逻辑,这样的话就会得到正确的理解。
1 是真,a 是假,所以 1 and a 是假。假 or b 是b。

应该将 and-or 技巧封装成一个函数:

def choose(bool, a, b):
return (bool and [a] or [b])[0]


因为 [a] 是一个非空列表,它永远不会为假。甚至 a 是 0 或 ” 或其它假值,列表[a]为真,因为它有一个元素。

第3题: 请至少列举5个 PEP8 规范?

PEP8 规范 官方文档:​​https://www.python.org/dev/peps/pep-0008/​

PEP8中文翻译:javascript:void(0)

这个在于平时的积累的了

  • 缩进。4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。
  • 每行最大长度79,换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。
  • 类和top-level函数定义之间空两行;类中的方法定义之间空一行;函数内逻辑无关段落之间空一行;其他地方尽量不要再空行。
  • 块注释,在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔
  • 各种右括号前不要加空格。
  • 逗号、冒号、分号前不要加空格。
  • 函数的左括号前不要加空格。
  • 序列的左括号前不要加空格。
  • 操作符左右各加一个空格,不要为了对齐增加空格。
  • 函数默认参数使用的赋值符左右省略空格。
  • 不要将多句语句写在同一行,尽管使用‘;’允许。
    i- f/for/while语句中,即使执行语句只有一句,也必须另起一行。
  • 类的方法第一个参数必须是self,而静态方法第一个参数必须是cls。

第4题: HTTPS和HTTP的区别:

  • https协议要申请证书到ca,需要一定经济成本
  • http是明文传输,https是加密的安全传输
  • 连接的端口不一样,http是80,https是443
  • http连接很简单,没有状态;https是ssl加密的传输,身份认证的网络协议,相对http传输比较安全。

还有很多,自己去整理一下吧

第5题:简述Django的orm

ORM,全拼Object-Relation Mapping,意为对象-关系映射

实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码只需要面向对象编程

ORM操作本质上会根据对接的数据库引擎,翻译成对应的sql语句,

所有使用Django开发的项目无需关心程序底层使用的是MySql、Oracle、SQLite…,如果数据库迁移,只需要更换Django的数据库引擎即可。