语言特性
-
Python语言与其它语言的区别。
Python语法简洁易懂,拥有强大的第三方库,适用范围广,且Python是解释型语言,运行时一行行解释并运行调试代码方便,开发效率高。 -
编译型语言和解释型语言的区别。
编译型语言:写好的程序可直接运行。执行速度快效率高,依赖编译器,跨平台性差。
解释型语言:把写好的代码翻译成机器语言再运行。执行速度慢,效率低,依赖解释器,跨平台型好。
通俗的讲,编译语言是在编译后可以直接运行,而解释语言的执行需要一个解释环境。 -
Python解释器的种类和特点。
Cpython:由C语言开发的解释器,在命令行下运行Python就启动了CPython解释器。
IPython:基于Cpython基础上的交互式解释器,IPython只在交互方式上有所增强,但执行代码的功能和Cpython完全一样。
PyPy:目标是速度,采用JTI(即时编译)技术,对python代码进行动态编译,可以显著提高Python的执行速度。
Jpython:运行在java平台的解释器,将python代码编译成java字节码执行。
IronPython:运行在微软.Net平台上的解释器,可以直接将Python代码编译成.Net的字节码。 -
说说你知道的Python3 和 Python2 之间的区别?
1.Print: print语句与print函数
2.输入函数:
P2:input_raw()
P3:input()
3.Super():好处是不需要显式地调用父类,代码维护成本低
P2:必须在参数中写上基类
P3:直接无参数调用即可
4.除法的结果:
P2:整数相除得到整数结果,浮点数相除得到浮点数结果。2/3=0,
P3:相除完整数字。
5.编码:
P2:默认使用ascii
P3:默认编码utf-8
6.字符串:
P2:unicode表示字符串,str表示字节
P3:str字符串,bytes字节
7.不等号运算符:
P2:<>,!=
P3: !=
8.数据类型:
Py3没用long类型,只有int型,但其行为和long差不多
9.打开文件的语法:
Py2:file(),open()
Py3:open()
10.Map,filter类型从内置函数变为类,返回结果从列表到迭代对象。 -
Python3 和 Python2 中 int 和 long 区别?
Python2中int类型有固定的长度,32位系统长度为32位,64位系统长度64位,long类型则不受限制。。在Python2中所有的整型都是长整型。 -
xrange 和 range 的区别?
在Python2中Range返回的是列表,xrange返回的是生成器
Python3中没有了xrange,只有range且会返回迭代器。 -
python是如何进行内存管理的?
a、对象的引用计数机制【引用计数为0时被当做垃圾回收】
python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收。
b、垃圾回收
1>当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
2>当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象 的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。
c、内存池机制
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。【以256k为分界线分为大内存和小内存】
数据类型
-
列举 Python 中的基本数据类型? Python3中有6种基本数据类型,列表(list)、元组(tuble)、字典(dict)、集合(sets)、字符串(string)、数字(digit)。
-
如何区别可变数据类型和不可变数据类型
可变数据类型:在改变值之后内存地址不变(列表字典是可变,字典的key不可变)
不可变数据类型:改变值之后内存地址改变 -
将"hello world"转换为首字母大写"Hello World"
“hello world”.title() -
如何检测字符串中只含有数字?
‘123bp’.isdigit()----------返回True or False
或者使用正则:bool(re.search(r’\d’,’qw123’))
或者使用Unicode码:if uchar >= u’\u0030’ and uchar <= u’\u0039’ -
将字符串"ilovechina"进行反转
“ilovechina”[::-1] -
Python 中的字符串格式化方式你知道哪些?
a. ‘I %s her %s’%(‘love’,‘cat’)
b.‘I {a} her {b}’.format(a=‘love’,b=‘cat’)
c. f’I {a} her {b} ’【Python3.6推荐写法】 -
有一个字符串开头和末尾都有空格,比如“ adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。
def strip_function(str_):
return str_.strip() -
获取字符串”123456“最后的两个字符。
Str[-2: ] -
一个编码为 GBK 的字符串 S,要将其转成 UTF-8 编码的字符串,应如何操作?
encode(gbk)以gbk方式编码;
decode(utf-8,ignore) 以utf-8方式解码。 -
(1)s=“info:xiaoZhang 33 shandong”,用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]。(2)a = "你好 中国 “,去除多余空格只留一个空格。
re.split(r”:| ", s)
‘’.join(s.split()) -
(1) 怎样将字符串转换为小写。 (2) 单引号、双引号、三引号的区别?
A.字符串大小写转换:upper,lower
B.单引号和双引号可以相互包含,在单引号中使用双引号不需要转义,\n 而三引号一般用于需要换行的字符串,它可以不使用换行符\n即可换行
数据类型 - 列表
- 已知 AList = [1,2,3,1,2],对 AList 列表元素去重,写出具体过程。
List(set(AList)) - 如何实现 “1,2,3” 变成 [“1”,“2”,“3”]
s.split(",") - 给定两个 list,A 和 B,找出相同元素和不同元素
A、B 中相同元素::set(A)&set(B)
A、B 中不同元素:set(A)^set(B) - [[1,2],[3,4],[5,6]] 一行代码展开该列表,得出 [1,2,3,4,5,6]
x=[j for i in l for j in i] - 合并列表 [1,5,7,9] 和 [2,2,6,8]
L1.extend(L2) OR L1+L2
L1.append(l2)::不可以,会把整个表添加进去。 - 如何打乱一个列表的元素?
random.shuffle(l1)
数据类型 - 字典
-
字典操作中 del 和 pop 有什么区别
del d[key] 直接删除
d.pop(key) 返回键的值 -
按照字典的内的年龄排序
d1 = [
{‘name’:‘alice’, ‘age’:38},
{‘name’:‘bob’, ‘age’:18},
{‘name’:‘Carl’, ‘age’:28},
]
sorted(d1,key=lambda x:x[‘age’]) -
请合并下面两个字典 a = {“A”:1,“B”:2},b = {“C”:3,“D”:4}
a. update(b) -
如何把元组 (“a”,“b”) 和元组 (1,2),变为字典 {“a”:1,“b”:2}
dict(zip(a,b)) -
下列字典对象键类型不正确的是?
A:{1:0,2:0,3:0}
B:{“a”:0, “b”:0, “c”:0}
C: {(1,2):0, (2,3):0}
D: {[1,2]:0, [2,3]:0}
D:列表不是可hash对象,不可以作为字典的键
List,set,dict不可哈希对象 -
如何交换字典 {“A”:1,“B”:2}的键和值
{value:key for key value in dict.items()} -
Python 里面如何实现 tuple 和 list 的转换?
tuple(list) -
我们知道对于列表可以使用切片操作进行部分元素的选择,那么如何对生成器类型的对象实现相同的功能呢?
from itertools import islice
for i in islice(gen,0,1):
print(i)
答: 这个题目考察了 Python 标准库的 itertools 模快的掌握情况,该模块提供了操作生成器的一些方法。 对于生成器类型我们使用 islice 方法来实现切片的功能。 -
请将 [i for i in range(3)] 改成生成器
(i for i in range(3))
- a=“hello” 和 b=“你好” 编码成 bytes 类型
b'hello'
a.encode('utf-8')
bytes('hello',encoding='utf-8')
47.下面的代码输出结果是什么?
a = (1,2,3,[4,5,6,7],8)
a[2] = 2::::::::::报错
a = (1,2,3,[4,5,6,7],8)
a[3][0] = 2:::::::::(1,2,3,[2,5,6,7],8)
48.Python 交换两个变量的值
答:语法糖 a, b = b, a。
操作类题目
-
在读文件操作的时候会使用 read、readline 或者 readlines,简述它们各自的作用 答:read将整个文本都读取为一个字符串,占用内存大,readline读取一行。readlines将文本读取为列表,占用空间大。
-
json 序列化时,可以处理的数据类型有哪些?如何定制支持 datetime 类型? 可以处理包括:list,dict,tuple,int,str,none,bool,
而datetime不支持json序列化,因此我们可以用strftime转换。 -
json 序列化时,默认遇到中文会转换成 unicode,如果想要保留中文怎么办?
Json.dumps(….,ensure_ascii=False) -
有两个磁盘文件 A 和 B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件 C 中。
With open(…) as f1:
F1.text=f1.readline()
…….f3=f1+f2
………sorted(f3) -
如果当前的日期为 20190530,要求写一个函数输出 N 天后的日期,(比如 N 为 2,则输出 20190601)。
Datetime.date.tody()+datetime.timedelta(days=2) -
写一个函数,接收整数参数 n,返回一个函数,函数的功能是把函数的参数和 n 相乘并把结果返回。
def test(num):
def nei(num1):
return num*num1
return nei
neii=test(5)
neii(4)-----返回20 -
请写一个 Python 逻辑,计算一个文件中的大写字母数量
with open('A.txt') as fs:
count = 0
for i in fs.read():
if i.isupper():
count += 1
print(count)
-
说一说Redis的基本类型
Redis支持的数据类型:zset(有序集合)、set、str、list、set、hash -
请写一段 Python连接Redis数据库的代码。
-
请写一段 Python连接Mysql数据库的代码。
-
了解Redis的事务么 Redis事务是一些redis命令的集合,有如下2个特点:1事务是一个单独的隔离操作,:事务中所有的命令都会序列化按顺序执行,执行过程中不会被其它客户端发来的命令请求打断,2事务是一个原子操作:事务中的命令要么全部执行,要么全部不执行。。
一个事务从开始到执行有三个阶段:开始事务,命令入队,执行事务。 -
了解数据库的三范式么 第一范式:列的原子性:即列不能再分为其它列 第二范式:表必须有个主键,没有包含在这个主键中的列必须依赖于这个主键
第三范式:不能存在传递依赖,即非主键列A依赖于非主键列B,非主键列B依赖于主键。 -
了解分布式锁么
正则表达式
- 使用正则表达式匹配出
<html><h1>www.baidu.com</html>
中的地址 - a=“张明 98 分”,用 re.sub,将 98 替换为 100
- 正则表达式匹配中(.)和(.?)匹配区别?
- 写一段匹配邮箱的正则表达式
爬虫相关
- 在 requests 模块中,requests.content 和 requests.text 什么区别
requests.content:二进制字符串,保存图片等二进制文件。
Request.text:保存普通文件。 - 简要写一下 lxml 模块的使用方法框架
from lxml import etree
Html=etree.HTML(要解析的网页或文本)
Html.xpath(‘’)
-
说一说 scrapy 的工作流程 答:首先engine向spider请求初始url,然后engine将初始url传给调度器以request的方式进行调度,再之后,engine向调度器请求热确实他,engine将request发送给下载器进行下载,下载器将下载后的响应发送给engine,engine将response发送个给spider进行解析,spider解析后会生成item或热确实他,将item和request传送给engine,engine会将item发送给itempipline,itempipeline会将item保存进数据库或者是本地,engine会将request发送给调度器,,,然后engine会向调度器请求request。
-
scrapy 的去重原理 :
Scrapy会依据每个request的method,url等计算其独特的指纹,然后依据python集合(set)的不可重复性进行去重。 -
scrapy 中间件有几种类,你用过哪些中间件
下载中间件:位于engine和dowonloader之间,处理request【添加cokies,scrapy对接selenium】和response。
Spider中间件:位于engine和spider之间,处理response和spider生成的item与request。主要功能是在爬虫运行过程中进行一些处理。
下载器中间件 Downloader Middleware:这个中间件可以实现修改 User-Agent 等 headers 信息,处理重定向,设置代理,失败重试,设置 cookies 等功能。 -
你写爬虫的时候都遇到过什么反爬虫措施?你是怎么解决的? 答:
Headers: 从用户的 headers 进行反爬是最常见的反爬虫策略。Headers 是一种区分浏览器行为和机器行为中最简单的方法,还有一些网站会对 Referer
(上级链接)进行检测(机器行为不太可能通过链接跳转实现)从而实现爬虫。 相应的解决措施:通过审查元素或者开发者工具获取相应的
headers 然后把相应的 headers 传输给 Python 的 requests,这样就能很好地绕过。IP 限制 一些网站会根据你的 IP 地址访问的频率,次数进行反爬。也就是说如果你用单一的 IP 地址访问频率过高,那么服务器会在短时间内禁止这个 IP 访问。
解决措施:构造自己的 IP 代理池,然后每次访问时随机选择代理(但一些 IP 地址不是非常稳定,需要经常检查更新)。
UA 限制 UA 是用户访问网站时候的浏览器标识,其反爬机制与 ip 限制类似。 解决措施:使用随机 UA
验证码反爬虫或者模拟登陆 验证码:这个办法也是相当古老并且相当的有效果,如果一个爬虫要解释一个验证码中的内容,这在以前通过简单的图像识别是可以完成的,但是就现在来讲,验证码的干扰线,噪点都很多,甚至还出现了人类都难以认识的验证码。
相应的解决措施:验证码识别的基本方法:截图,二值化、中值滤波去噪、分割、紧缩重排(让高矮统一)、字库特征匹配识别。(Python 的
PIL 库或者其他),复杂的情况需求接入打码平台。Ajax 动态加载 网页的不希望被爬虫拿到的数据使用 Ajax 动态加载,这样就为爬虫造成了绝大的麻烦,如果一个爬虫不具备 js 引擎,或者具备 js 引擎,但是没有处理 js 返回的方案,或者是具备了 js
引擎,但是没办法让站点显示启用脚本设置。基于这些情况,ajax 动态加载反制爬虫还是相当有效的。 Ajax
动态加载的工作原理是:从网页的 url 加载网页的源代码之后,会在浏览器里执行 JavaScript
程序。这些程序会加载出更多的内容,并把这些内容传输到网页中。这就是为什么有些网页直接爬它的 URL 时却没有数据的原因。处理方法:找对应的 ajax 接口,一般数据返回类型为 json。
-
为什么会用到代理? 答:很多网站限制 IP 访问的速度和次数,导致大规模采集的时候影响速度,所以用代理的方式绕过。
-
代理失效了怎么处理? 答: 一般通过大家代理池来实现代理切换等操作,来实现时时使用新的代理 ip,来避免代理失效的问题。
-
列出你知道 header 的内容以及信息 答:UA:浏览器头信息,refer:表示从哪个网页跳转的,Accept:指定客户端能够接收的内容类型。
Accept-Encoding:指定浏览器可以支持的 web 服务器返回内容压缩编码类型。
Accept-Language:浏览器可接受的语言。 Connection:表示是否需要持久连接。(HTTP 1.1
默认进行持久连接)。 Content-Length:请求的内容长度。
If-Modified-Since:如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回 304 代码。
Referer:先前网页的地址,当前请求网页紧随其后,即来路。 -
说一说打开浏览器访问 www.baidu.com 获取到结果,整个流程。 答:先向 DNS 服务器查询对应 IP ,浏览器访问 IP ,网站响应若是 HTTPS 的验证一下证书,然后 TCP 三次握手开始传数据。
-
爬取速度过快出现了验证码怎么处理 答:降速,上打码平台,尝试登录后爬取,挂代理多 IP 爬。
一般在爬取过程中出现了验证码根据不同的情况,处理不一样。 如果在一开始访问就有验证码,那么就想办法绕开验证码,比如通过 wap 端或者 app 去发现其他接口等,如果不行就得破解验证码了,复杂验证码就需要接入第三方打码平台了。
如果开始的时候没有验证码,爬了一段时间才出现验证码,这个情况就要考虑更换代理 ip 了。 可能因为同一个访问频率高导致的。 -
scrapy 和 scrapy-redis 有什么区别?为什么选择 redis 数据库?
答:scrapy 是一个 Python 爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而 scrapy-redis 一套基于 redis 数据库、运行在
scrapy 框架之上的组件,可以让 scrapy 支持分布式策略,Slaver 端共享 Master 端 redis 数据库里的
item 队列、请求队列和请求指纹集合。
为什么选择 redis 数据库,因为 redis 支持主从同步,而且数据都是缓存在内存中的,所以基于 redis 的分布式爬虫,对请求和数据的高频读取效率非常高。 -
分布式爬虫主要解决什么问题 答: 使用分布式主要目的就是为了给爬虫加速。解决了单个 ip 的限制,宽带的影响,以及 CPU 的使用情况和 io 等一系列操作
-
写爬虫是用多进程好?还是多线程好? 为什么? 答:多线程,因为爬虫是对网络操作属于 io 密集型操作适合使用多线程或者协程。。
-
解析网页的解析器使用最多的是哪几个 答:BeautifulSoup,lxml。
-
需要登录的网页,如何解决同时限制 ip,cookie,session(其中有一些是动态生成的)在不使用动态爬取的情况下? 答: 解决限制 IP 可以搭建代理 IP 地址池、adsl 拨号使用等。 不适用动态爬取的情况下可以使用反编译 JS
文件获取相应的文件,或者换用其他平台(比如手机端)看看是否可以获取相应的 json 文件,一般要学会习惯性的先找需要爬取网站的 h5
端页面,看看有没有提供接口,进而简化操作。 -
验证码的解决(简单的:对图像做处理后可以得到的,困难的:验证码是点击,拖动等动态进行的?) 答:答: 图形验证码:干扰、杂色不是特别多的图片可以使用开源库 Tesseract 进行识别,太过复杂的需要借助第三方打码平台。
点击和拖动滑块验证码可以借助 selenium、无图形界面浏览器(chromedirver 或者 phantomjs)和 pillow
包来模拟人的点击和滑动操作,pillow 可以根据色差识别需要滑动的位置。 -
使用最多的数据库(mysql,mongodb,redis 等),对他的理解?
答: MySQL
数据库:开源免费的关系型数据库,需要实现创建数据库、数据表和表的字段,表与表之间可以进行关联(一对多、多对多),是持久化存储。mongodb
数据库:是非关系型数据库,数据库的三元素是,数据库、集合、文档,可以进行持久化存储,也可作为内存数据库,存储数据不需要事先设定格式,数据以键值对的形式存储。redis
数据库:非关系型数据库,使用前可以不用设置格式,以键值对的方式保存,文件格式相对自由,主要用与缓存数据库,也可以进行持久化存储。
编码规范
-
什么是 PEP8?
答:PEP8是Python编程的一种格式要求,为了提高程序的可读性和规范性,在程序员之间互相约定好的一种代码格式 -
了解 Python 之禅么?
Python交互模式下输入:import this 即可看到 -
了解 dosctring 么?
答:Python推崇代码即文档,通常在函数中第一个语句即表明了函数的用法及接受的参数,可以通过functiong.__doc__属性来获得。 -
了解类型注解么?
答:类型注解是Python3中引入的新特性,通过def(x:int, y:int) -> int: 这样的方式,标记参数及返回值的类型,这里要注意,即使添加了了类型注解也不会对代码产生影响,它的作用更像是注释,只是方便其他程序员了解参数及返回值类型。 -
例举你知道 Python 对象的命名规范,例如方法或者类等
答:模块:尽量使用小写,单词太多用下划线分割。
类:使用驼峰命名,单词首字母大写,不使用下划线。
函数:全部使用小写,单词太多用下划线链接,私有函数前添加一个下划线。
变量:全部使用小写,常量全部使用大写,均用下划线链接。 -
Python 中的注释有几种?
-
单行注释在行首是 #。
-
多行注释可以使用三个单引号或三个双引号,包括要注释的内容
-
如何优雅的给一个函数加注释? 答:可以通过变量名:类型的方式如下
a: str = "this is string type"
-
14.Python 代码缩进中是否支持 Tab 键和空格混用。 答:不允许 tab 键和空格键混用,这种现象在使用 sublime 的时候尤为明显。一般推荐使用 4 个空格替代 tab 键。
-
是否可以在一句 import 中导入多个库?
答:可以是可以,但是不推荐。因为一次导入多个模块可读性不是很好,所以一行导入一个模块会比较好。同样的尽量少用 from modulename import *,因为判断某个函数或者属性的来源有些困难,不方便调试,可读性也降低了。 -
在给 Py 文件命名的时候需要注意什么?
答:给文件命名的时候不要和标准库库的一些模块重复,比如 abc。 另外要名字要有意义,不建议数字开头或者中文命名。 -
例举几个规范 Python 代码风格的工具 答:pylint 和 flake8
高级特效
-
函数装饰器有什么作用?请列举说明? 函数装饰器可以在不修改函数代码的情况下增加函数的功能。例如:对函数的每个参数进行检查 https://foofish.net/python-decorator.html
-
Python 垃圾回收机制? 引用计数法:当发现对python 的引用计数为0时,python会自动销毁变量。
-
魔法函数 __call__怎么使用? 让类的实例化对象可以像函数一样被调用;
-
Python 中的接口如何实现?
接口是在类中定义了某些方法而没有去实现,在其子类中去实现此方法. 一、 在普通类中定义空方法,在继承的子类中实现此方法
二、 定义抽象类,并在抽象类中定义空方法;;由继承的子类实现该方法,并且子类必须实现抽象类中所有方法,否则会编译错误。链接:https://blog.csdn.net/qq_21033779/article/details/79071887
-
如何判断一个对象是函数还是方法?
通过type方法,返回为method即为方法,返回function即为函数,函数与方法并无本质不同,与类关联后的函数即为方法,通过类实例化后调用,函数直接调用即可。@classmethod 和@staticmethod 用法和区别
在python中,静态方法和类方法都是可以通过类对象和类对象实例访问。 @classmethod
类方法,使用后第一个参数由self变为cls @ staticmethod静态方法,类似于一个全局函数。
两者都可以使类不实例化就可调用。 【@classmethod
是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法。
类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例。 普通对象方法至少需要一个self参数,代表类对象实例
类方法有类变量cls传入,从而可以用cls做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。
对于类方法,可以通过类来调用,就像C.f(),有点类似C++中的静态方法,
也可以通过类的一个实例来调用,就像C().f(),这里C(),写成这样之后它就是类的一个实例了。
静态方法则没有,它基本上跟一个全局函数相同,一般来说用的很少】 -
python中的反射机制了解吗?
答: Python 的反射机制设定较为简单,一共有四个关键函数分别是 getattr、hasattr、setattr、delattr。 -
metaclass 作用?以及应用场景?
答:metaclass元类,创建类的模板;我们可以使用元类创建单例模式和实现 ORM 模式。 -
hasattr()、getattr()、setattr() 的用法
答:hasattr()判断类是否拥有某种属性,getattr()获取类的属性值,setattr()为属性进行赋值操作
示例代码如下: -
请列举你知道的 Python 的魔法方法及用途。
答:init 初始化类中的部分属性,new 最先执行的部分,可用来实现单例类,功能与78题类似的 __getattr__试图访问类中不存在的属性时会调用该方法,可自定义返回值, setattr 对类的属性进行新增和赋值,可以进行简单的条件筛选, __delattr__用于删除类中的方法或是属性, del(self) 当一个实例被销毁的时候调用的方法. -
.如何知道一个 Python 对象的类型?
答:可以使用type方法 -
Python 的传参是传值还是传址?
答:传的是对象的引用。 -
Python 中的元类(metaclass)使用举例
答 :略 -
简述 any() 和 all() 方法
答:any()方法:对象中任意对象都为真值返回True
all()方法:对象中所有对象都为真值返回True,
85.filter 方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
答:list(filter(lambda x:x if x%2==1 else None,a))
Filter的意思是过滤器,接收一个函数和列表,返回不符合函数输出的值
其它内容
-
解释一下 python 中 pass 语句的作用? 答:类似一个占位符,程序执行到这里默认执行一个空语句,通常用来给后续功能留位置的。
-
简述你对 input()函数的理解
答:输入函数,用于接受用户的输入,在Python3中默认输入内容为字符串类型。 -
python 中的 is 和= =
答:is检查对应的内存地址是否相同,==只检查值是否相同。 -
Python 中的作用域
答:作用域指的是函数名或者变量名的寻找顺序,优先级从高到低分别为局部作用域(子函数)、闭包函数外的函数中(父函数)、全局作用域(当前Python模块)、内建作用域(Python标准库)。 -
三元运算写法和应用场景?
答:形如 a= ‘a’ if b>1 else ‘b’,想用都能用,我个人感觉没有什么特定场景,属于一种偷懒写法。 -
了解 enumerate 么?
1答:内置函数,用来枚举迭代器,返回结果为(index,
value),可以方便的获得迭代器的下标和值,也可以接受第三个参数,用于修改起始下标,for index, value in enumerate(list, 1): print(index, value)
-
列举 5 个 Python 中的标准模块
答:time(延时、日期)、re(正则)、random(随机)、urllib(网络请求)、os(系统)、csv(csv文件读写)、hashlib(哈希处理)、logging(日志)。 -
如何在函数中设置一个全局变量
答:使用global关键字,例如 global a; a=a+1这样即可在函数中修改全局变量a的值。 -
pathlib 的用法举例
答:不会,略。。。。。 Python 中的异常处理,写一个简单的应用场景 答:对文件的读写经常因为编码问题报错,这里使用 try …except的方法进行一个简单处理:try: open(‘filename’, ‘r’) as f: f.readlines() except:
print(‘error’) finally: f.close() -
Python 中递归的最大次数,那如何突破呢?
答:默认最大递归次数为1000,通过以下代码进行修改 import sys sys.setrecursionlimit(10000) # set the maximum depth as 10000
根据系统不同还存在解释器上限,windows下最大迭代次数约4400次,linux下最大迭代次数约为24900次。 -
什么是面向对象的 mro
答:。。。 -
isinstance 作用以及应用场景?
答:用于判断对象是否与已知对象类型一致,功能上类似type()函数 -
什么是断言?应用场景?
答:断言也是一种异常处理的方式,可以判断关键字后方的表达式是否为真,若为真则继续执行,若为假则抛出异常。常用于一些数据的检验。 -
lambda 表达式格式以及应用场景?
答:labmda又被称为匿名函数,用于一些简单的函数处理,例如:lambda x:x^2,这里将传入的x平方后返回,常常和循环结合在一起使用。 -
新式类和旧式类的区别 答:
算法和数据结构
略
网络编程
-
TCP 和 UDP 的区别?
答:
区别总结:
1.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接;
2.TCP连接传输的数据更可靠。
3. TCP面向字节流,实际上TCP把数据看出一连串无结构的字节流,UDP是面向报文的。
4. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
5. TCP 相对于 UDP 速度慢一点,要求系统资源较多,UDPUDP 速度快、操作简单、要求系统资源较少 -
简要介绍三次握手和四次挥手】 答:TCP 是面向连接的通讯协议,通过三次握手建立连接,通讯完成时四次挥手。
三次握手:
四次挥手
三次握手:
第一次握手:客户机向服务机发送同步报文段(SYN)请求建立连接。第二次握手:服务机听到连接请求,将该连接请求放入内核等待队列当中,并向客户机发送针对SYN的回应ACK,同时服务机也会发送自己的请求建立连接(SYN)。第三次握手:客户机针对服务机发送回应ACK
四次握手: 第一次握手:客户机发送一个FIN,用来关闭客户机到主机的数据传送,客户机进入FIN_WAIT_1状态;
第二次握手:服务机接收到FIN之后,发送一个回应ACK给客户机,服务机进入CLOSE_WAIT状态。第三次连接:服务机准备关闭连接,向客户机发送一个FIN结束报文段。
第四次握手:客户机接收到FIN结束报文段后,进入TIME_WAIT状态,冰箱主机发送一个ACK表示连接几点释放。为什么二三次握手不能合在一次挥手中:因为客户机在发送FIN字段后虽然不可以发送数据了,但是可以接受数据,而且主机可能还有数据要发送给客户机,所以两次握手不能合并为1次。
-
什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?
答:
粘包:TCP 粘包通俗来讲,就是发送方发送的多个数据包,到接收方后粘连在一起,导致数据包不能完整的体现发送的数据。
导致 TCP 粘包的原因
可能是发送方的原因,也有可能是接受方的原因。
TCP是流式协议,只有字节流,流是没有边界的,因此他会开辟出一个缓冲区,发送端往其中写入数据 每过一段时间就发送出去 然后接收端接收到这些数据 但是并不是说我发送了一次数据就肯定发送出去了 数据会在缓冲区中 有可能后续发送的数据和之前发送的数据同时存在缓冲区中随后一起发送 这就是粘包的一种形式 接收端也有产生粘包的情况 如果应用程序没有及时处理缓冲区中的数据 那么后续到达的数据会继续存放到缓冲区中 也就是2次接收的数据同时存在缓冲区中 下次取缓冲区的时候就会取出2次粘包后的数据 这是粘包的另外一种形式 还有其他许多形式 比如填充缓冲区到一半缓冲区满了直接发送了 但是其实那个包还没填充完全 这个就是不完整的粘包了 剩余数据会在下次发送的时候补上。
并发
-
举例说明 concurrent.future 的中线程池的用法
-
说一说多线程,多进程和协程的区别
答:以前看过一个描述,程序运行就像大家一起吃饭,多线程就是一个人拿两个勺子吃,勺子再多只有一张嘴。多进程就是一堆人一起吃,虽然只有一个勺子,但是嘴多吃的快。多线程只能提高效率,本身占用的资源取决于进程。协程是线程手下的小弟,和线程的关系可以类比于线程和进程的关系。但是协程间切换的消耗远低于线程间切换的消耗,原因是线程和进程的控制取决于内核,而协程的控制取决于程序。
区别:进程与线程比较: 线程是指进程内的一个执行单元,也是进程内的可调度实体。
线程与进程的区别:
1)地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,它们共享进程的地址空间, 而进程有自己独立的地址空间 2)
资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源 3) 线程是处理器调度的基本单位,但进程不是 4)
二者均可并发执行 5) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,
但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制协程与线程进行比较:
1)一个线程可以多个协程,一个进程也可以单独拥有多个协程,这样 Python 中则能使用多核 CPU。 2)
线程进程都是同步机制,而协程则是异步 3) 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态 -
简述 GIL GIL:全局解释锁,每个线程在执行过程中都需要获取GIL,保证统一时刻只有一个线程可以执行代码。 Python3.x
使用计时器(执行时间达到阈值后,当前线程释放 GIL)。 Python 使用多进程是可以利用多核的 CPU 资源的。
多线程爬取比单线程性能有提升,因为遇到 IO 阻塞会自动释放 GIL 锁 -
进程之间如何通信。
答:
可以通过队列的形式,代码示例如下: -
IO 多路复用的作用?
阻塞I/O可以阻塞一个I/O操作,IO多路复用可以阻塞多个I/O操作,。
阻塞IO:当数据没有准备好时进程会休眠。
非阻塞IO:当数据没有准备好时会返回错误。
IO多路复用可以用于提升效率,单个进程可以同时监听多个网络连接IO。在IO密集型系统中,相对于线程切换的开销问题,IO 多路复用可以极大的提升系统效率。 -
select、poll、epoll 模型的区别?
答:
select,poll,epoll 都是 IO 多路复用的机制。I/O 多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
select 模型:
select 目前几乎在所有的平台上支持,select 的一 个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在 Linux 上一般为 1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但 是这样也会造成效率的降低。
poll 模型:
poll 和 select 的实现非常类似,本质上的区别就是存放 fd 集合的数据结构不一样。select 在一个进程内可以维持最多 1024 个连接,poll 在此基础上做了加强,可以维持任意数量的连接。
但 select 和 poll 方式有一个很大的问题就是,我们不难看出来 select 是通过轮训的方式来查找是否可读或者可写,打个比方,如果同时有 100 万个连接都没有断开,而只有一个客户端发送了数据,所以这里它还是需要循环这么多次,造成资源浪费。所以后来出现了 epoll 系统调用。
epoll 模型:
epoll 是 select 和 poll 的增强版,epoll 同 poll 一样,文件描述符数量无限制。但是也并不是所有情况下 epoll 都比 select/poll 好,比如在如下场景:在大多数客户端都很活跃的情况下,系统会把所有的回调函数都唤醒,所以会导致负载较高。既然要处理这么多的连接,那倒不如 select 遍历简单有效。
71.什么是并发和并行?