前言:欢迎各位留言补充遗漏的知识点,本文适用于初中级开发求职~
文章目录
-
-
- 0. 开发者(程序猿)tip(杂)
- 1.游戏后端架构设计
- 2 面试控场
- 3 python
- 4 系统编程
- 5 DB
-
- 5.1 DB-mysql
- 5.2 DB-mongoDB
- 5.3 DB-redis
- 5.4 QS:MySQL和MongoDB区别
- 5.5 行式数据库与列式数据库
- 5.6 数据库范式
- 6 网络编程
- 7 数据结构
-
- 7.1 数据结构种类
- 7.2 算法
- 7.3 排序算法(至少熟练掌握三种)
- 7.4 数据结构与算法面试题
-
- 7.4.1 QS: 单链表反转: --- 必须会写
- 7.4.2 QS:判断两个单向链表是否相交 --- 要会思路,不要求现场代码
- 7.4.3 QS:求满足指定和的子集
- 7.4.4 QS: 纸币组合(星商,较难)
- 7.4.5 QS:洗牌算法(较为简单,游戏必问)
- 7.4.6 QS:从1亿个整数中找出其中出现次数最多的数
- 7.4.7 QS:两个大文件A,B,每一行都为一个字符串,找出在两个文件中都出现的字符串
- 7.4.8 QS: 某整数开方如何实现,保留指定位数 --二分逼近
- 7.4.9 QS:九宫格 --排列组合问题 --通过进制(难)
- 7.4.10 QS:给你几张扑克牌,扑克牌的牌值通过运算得出24,用代码求出可能的组合,用到的符号: +, -, /, 括号(难)
- 7.4.11 旋转数组
- 7.4.12 从100亿个数中找出最大/小的1000个数
- 7.4.13 有1亿个整数,其中只有1个整数只出现了1次,怎么快速找出来
- 7.4.14 python中sort 是如何实现的
- 8 开发杂谈
- 9 linux
- 9.1 docker的好处和缺陷
- 9.2 CPU负载怎么理解,比如四核机器负载多少算超载
- 10 git
- 11 django详细(待完善)
- 12 vue(待完善)
-
0. 开发者(程序猿)tip(杂)
以下跟面试无直接相关,但是是日常编程和学习中非常有用的知识点或者可以带来提升的小建议(因为是突然想到或者不知道放哪,就统一放这里了,可跳过)。
tip01: 多浏览技术新闻,博客,论文,论坛等,想想当前或者以后工作中哪些能用到?
tip02: 熟透部分数字的量级;做到立即反应;举例:40亿bit = 512Mbytes等;
tip03: 空间局部性原理:如果一条数据在某一时刻被访问了,则大概率预测其旁边的数据也即将被访问。
tip04: 存储器速率:寄存器(1ns) > 高速缓存(L1(k ns),L2, L3) > 内存(100ns) > 硬盘(50ms) > 外部存储;
CPU高速缓存是位于CPU和内存之间的临时数据交换器,他的容量比内存小得多但是交换速度却比内存要快得多。
CPU缓存一般直接跟CPU芯片集成或位于主板总线互连的独立芯片上。
tip05: 多核和多CPU区别:多个cpu,cpu通过总线进行通信,效率比较低;
多核cpu,不同的核通过L2 cache进行通信,存储和外设通过总线与cpu通信
多cpu
多核CPU
tip06: 进程和线程在多核CPU,多CPU中的运行关系
多CPU的运行,对应进程的运行状态;多核CPU的运行,对应线程的运行状态。
操作系统会拆分CPU为一段段时间的运行片,轮流分配给不同的程序。对于多CPU,多个进程利用并行在多个CPU中计算,当然也存在进程切换;对于单CPU,多个进程则是并发运行,根据时间片读取上下文->读取上下文->保存上下文。同一个进程同一时间段只能在一个CPU运行,如果进程数小于CPU数,那么未使用的CPU将会空闲。
进程有自己独立的地址空间,每启动一个进程,系统就会为他分配一个地址空间,建立数据表来维护代码段,堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据,使用相同的地址空间,因此CPU切换一个线程的开销花费远比进程小的多,同时创建一个线程的开销也比进程小的多。
对于多核CPU,进程中的多线程并行执行,执行过程中存在线程切换,线程切换开销较小。对于单核CPU,多线程在单CPU中并发执行,根据时间片切换。同一个线程同一时间只能在一个CPU内核中运行,如果线程数小于CPU内核数,那么将有多余的内核空间。
总结:
1. 单CPU中进程只是并发,多CPU中计算机中进程可以并行。
2. 单CPU单核中线程只能并发,单CPU多核中线程可以并行。
3. 无论是并发还是并行,使用者来看,看到的是多进程,多线程。
tip07: mysql5.7 单表 建议数据 不要超过1000万
mongodb4.0+ 固态硬盘 单collection 1-2亿条数据
tip08: 数据规模:数据库里记录数据最多的一张表的记录量级;
tip09: Python中有序的结构: 列表, 元组, 有序集合, 有序字典
无序的结构: 普通集合, 普通字典
tip10: 敲sql命令时: 修改操作时, 建议先把条件敲上, delete from user where id=10;防止手误条件没加上删多了数据!!!
tip11: unspecified:最差的结果,有可能报错,有可能不报错(不代表没有错误)
tip12: protobuf协议:
tip13: 初创公司(高内聚,高耦合)–>中型公司->大型公司(耦合性越来越低,高耦合,低内聚,运维成本越来越高)
tip14: 编码封装函数的时候,尽量不要修改传入的参数(容器对象)
tip15:QPS:每秒处理的请求数
tip16:微服务:微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,
服务之间相互协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,
服务和服务之间采用轻量级的通信机制相互沟通(通常是基于HTTP的Restful API).
每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。
另外,应尽量避免统一的、集中的服务管理机制,对具体的一个服务而言,
应根据业务上下文,选择合适的语言、工具对其进行构"---- Martin Fowler
1.游戏后端架构设计
1.1 设计方案
a. 性能卓越 和 高可用性
分布式架构
高并发
游戏推送 – 周期性批量推送
故障自动切换
热更新
安全因素: DDos防护,防重放,sql注入 …
b. 监控运维,测试
用户行为模拟
通知
监控系统
linux上线操作脚本自动化
ELK 体系
1.2 web服务架构
web接口层: 收到路由过来的请求,只对消息参数做基本的验证;
业务逻辑层: 该请求的业务逻辑在此处理;
数据接口层: 封装了所有的数据存取操作; – 不让调用者关注数据存取底层是如何存储的;
数据存取层: 直接操纵数据的存取,操作 mysql, redis, mongodb, mssql, memcache;
1.3 运维监控
- 服务器层面|主机层面监控: — 云厂商
云主机状态: 存活, 内存, 硬盘, 网络, cpu…
是否可用, 是否超过阈值
是否反常(某个时间段的状态是否明显和其他时候不一样) - 服务层面|业务层面: — 有部分三方厂商可以监控一部分
mysql 响应时间, 登录服务响应时间… — google sre
99.9% 99.99% : 服务可用时间 - 业务逻辑层面 — 公司内部自己做
检查货币情况是否有误差
2 面试控场
面试课知识点较多: 先背再理解
技术能力: 符合岗位要求;
综合素质: (价值观,协作,沟通,逻辑思维)优良;
控场: 你的亮点(优势);常见问题与技术可以不会,但是不能不知道;
2.1 技术面
2.1.1 专业能力
–知识面广度(对常识性知识点必须了解)
–知识点深度(关键所在)
–逻辑思维能力:场景设计和算法逻辑(高级岗位必需)
2.1.2 综合素质
比重较小,面试过程尊重面试官
2.2 leader面
–基础知识点不多
–开放型问题较多
–重点在综合素质
tip: 回答的时候尽量挑某个熟悉或者无异议的点来回答,尽量闭坑或者避免有争议的东西。
原则:遵循客观事实,承认劣势;强调优势,举例证明;道明兴趣,展现自信;
2.3 HR面
人品,诚信,价值观,薪资
2.4 自我介绍
time: 30s-2min; 不要低头; 尽量不要背,眼神互动;切忌卡顿,尽量流畅;
2.5 职业规划
避免谈太长周期3-5年即可;避免规划管理方向,尽量往技术方向上说;
2.6 离职原因(丧命题)
不要非议上家公司和leader;
大公司:做的事情很窄,螺丝钉(劣势);最前沿的技术,知识点深度(优势);
小公司:接触很广,体验产品从0-1的过程(优势);技术深度不够(劣势)
2.7 公司认同
公司领域业务认同;
有没有什么要了解的(提问);
期望薪资(根据自己面试情况,招聘岗位薪资范围自我认知)
询问自己与岗位需求的差异或差距(询问面试结果情况)
3 python
3.1 语言特点
3.1.1 设计哲学
简洁,明确,优雅
3.1.2 追根溯源
1991 发布第一个版本; 2000 发布稳定的2.7版本;2008 Python3发布; 2020 Python2 将不再维护;
3.1.3 python2 与 python3 对比
思路:
- 核心类差异(编码方式&字符串类型的差异,import方式的区别,类的区别,缩进)
- 废弃类差异(答5条即可,如 long整数类型废弃,xrange函数废弃,print、exec、execfile语句,rawinput函数废弃)
- 修改类差异(for循环,比较操作符,round函数,异常处理,除法运算的区别)
3.1.4 QS:Python综述
- 什么情况下使用Python语言开发比较好?
- 你对Python怎么看?
- 为什么要用Python?
回答思路: 时间线 + 空间线 + 引子(带入自己熟悉的领域)
时间线: 91,第一个稳定的Python版本;00,Python2.7稳定版发布;08,Python3发布;20,Python2不再维护;
空间线:Python设计哲学 + Python2,3特性 + 和其他编程语言(如c++对比)+ 语言选型考虑因素;
引子:Python2 与 Python3 的区别;
话术串联(历史->Python本质特性->如何选型(语言精华,语言对比)->埋引子)
# 参考案例1
Python自1991年发布其第一个稳定版本以来,
一致秉承着其“简单、明确、优雅”的设计哲学,
这从根本上决定了Python这门语言在编程开发上的易用性和工作高效性。
同样的业务需求实现,可能传统编程语言C++需要一周工期
,而Python可能三天就能完成,并且可能隐藏的问题也会少很多。
因为Python本身目前有着非常庞大的开源第三方库,
同时封装了很多复杂的语言底层操作如内存分配与释放,指针的相关的操作等;
在具体的项目实践过程中,开发语言的选型具体要考虑几个方面:
业务的本身特点适合哪个语言、公司的历史技术栈和技术人员技术储备倾向于哪种语言、
选型语言当前的生态体系和发展前景(如是否不维护);
如果项目非计算密集型项目。此时Python语言就有一定的优势,
碰到其中少部分算法性能瓶颈的地方可以用c++等语言重写,
然后Python调用,这样就可以兼顾Python开发低成本和C++高性能两方面的优势;
具体选用Python后,新项目推荐使用Python3,
自08年发布Python3以来,Python3生态圈三方库已经非常完备和齐全,
且Python2宣布自2020年以后不再做维护,
另外Python3相比Python2性能上也有一定提升。
# 参考案例2
Python语言和C++, Java等其他编译型语言不一样,它是一种动态解释型脚本语言,
代码在执行时会一行一行的解释成CPU能理解的机器码。
同时它又是跨平台的,可以允许在windows,linux,mac等系统上,
同样的程序逻辑,可能C语言需要1000行代码,java有100行,
而Python实现可能只需要20行,这极大程度上提升了企业的项目开发效率。
记得之前看到一篇报道说,到2014年为止,
哈佛、麻省理工、伯克利等顶尖高校都已经使用Python作为教学语言,
而最近这一两年来Python也多次被各大机构评为年度最佳编程语言。
对于企业项目后台开发而言,不是说一定需要使用Python开发,
但至少应该是一个首选考虑项,
当然Python本身从根本上来说性能是比不上C/C++这些编译型语言,
但现在语言本身的性能差距在实际开发的过程中,相对业务功能合理性设计、
代码编写架构质量等等,语言底层本身造成的性能损失越来越可以忽略不计;
针对于一些特定的功能模块,Python当前也出现了pypi,
JIT等大幅提高Python程序运行效率的相关技术,能够满足大多数功能需求业务场景。
编程语言的本质是人与机器沟通的工具,将人类希望机器做的事翻译成机器本身能够理解的指令;
语言发展进化的历史也已经表明,越符合人类自身思维逻辑及习惯的编程语言将越受到大众欢迎。
目前从云端、客户端,到物联网终端,python应用无处不在,
同时也是人工智能首先的编程语言(Python在在人工智能上的优势至今无人能够撼动)。
Python当前也已经具备了非常完备丰富的开源三方生态圈(
比如web框架tornado,sanic, 运维监控zabbix,游戏引擎firefly等等不胜枚举)。
对于大多数企业新后台项目开发,个人倾向于推荐Python作为首选语言。
具体选用Python后,新项目推荐使用python3,2008年Python3发布后,
十几年来Python3生态圈三方库已经非常完备和齐全,而官方已宣布Python2在2020年将不再维护,
另外Python3本身性能也相较Python2有一定的提升;
3.1.5 QS: 什么是解释型语言
思路:解释型,编译型语言特点,举例说明
# 回答案例
1.解释器语言是指,通过专门的解释器对程序逐行翻译成机器码,并立即执行。
特点:每次运行都需要将源代码解释成机器码,运行效率低;
逐行执行,开发效率高;平台提供解释器即可运行程序,
移植性高;python是解释型语言。
2.编译器语言是指,针对特定的平台使用专门的编译器一次性翻译成平台可以识别的机器码,
并可以包装成平台能识别的可执行性程序的格式。
特点:一次编译,永久执行,运行效率高;与平台有关,
移植性较差;需要全部翻译才能运行,
开发效率低;c,c++都属于编译型语言。
3.2 GIL
(Global Interpreter Lock) 全局解释器锁 — cpython解释器
原因:多线程安全问题
运作机制: 一个进程同一时间只有一个线程在真正运行
# 并行并发是针对操作系统执行来说的
并行:绝对同一时间在做多件事情;
并发:短时间段内做多件事情;表面上一个cpu同时做了多件事,本质上是交替进行;
# 同步异步关注的是消息通信机制
同步:程序在发出一个调用时,在没有得到结果之前,该调用就不返回;即调用者主动等待这个调用的结果;
异步:程序在调用发出后,这个调用就直接返回了,调用者不会立即得到结果。被调用者通过状态,通知或回调函数来告知调用者结果;
GIL释放时机: 线程IO操作时,每隔100 opcode 或者 15ms
Python的多线程只对IO密集型计算产生正面效果,而当其中有一个CPU密集型任务时,多线程效率会急剧下降
IO密集型:输入输出较多,占用内存资源不多;
CPU密集型:占用内存资源较多,输入输出较少;
( cython与cpython )
避免 GIL 带来的影响: 多进程 + 协程 ; 其他解释器(很多三方库用不了);
3.2.2 QS:谈谈你对GIL的认识?
答题思路:
概念、背景、特性和使用场景,缺陷,缺陷解决替代方案。
# 回答实例
(历史背景,概念,特性)1991年Rossum设计Python的时候,当时世界上并无多核处理器的存在,而在Cpython解释器中内存管理不是线程安全的(同一进程中的不仅有代码执行的线程,也有解释器开启的垃圾回收进程),因此GIL应运而生。GIL用来保证同一进程只有一个线程能修改共享资源。因此python多线程大多时候并不能真正的并行,只有获取GIL的线程才能运行,难以发挥多核处理器的性能。
(使用场景与缺陷)GIL锁的释放时机有两种情况:
a.线程开始IO操作时,会先释放GIL
b.计算任务时,解释器每隔100次opcode或15ms释放GIL
因此python的多线程因为GIL的存在对IO密集型产生正面效果,而但凡有一个CPU密集型任务存在,多线程效率都会大大下降。
(改善)改善GIL带来的影响:
1.GIL是cpython的特性,而不是python特性。因为可以使用其他解释器来避免GIL的影响,但是同时也会损失使用很多c语言有用模块的机会。
2.使用多进程+协程的方式代替多线程充分发挥多核处理器的优势,每个进程中的GIL都是独立的,不会相互影响。
3.2.3 QS:既然有GIL的存在,为什么我们在代码中我们自己经常还选择加锁(普通互斥锁)?
思路:1.理解锁存在的作用 2.理解GIL与普通锁的级别
# 回答实例
锁是用来保护多线程共享数据的安全的。
GIL和自己代码中的锁都是这个作用,
但是不同的是,锁的级别不一样,保护的数据级别也不一样。
GIL是解释器级别的锁,用来保护解释器级别的数据(如解释器要回收的数据),
而自己加的普通互斥锁主要是保护用户自己程序级别的数据。
3.3 python对象与存储
-
万物皆对象
-
python 对象存储:
简言之,Python在内存中缓存了整数和短字符串,容器对象则是进行(赋值)引用;
(1)同一文件(模块)中变量缓存机制:
number类型: int:-5 ~ +∞ float: 非负 bool 复数:纯虚 以上值相同时,地址相同; 容器类型: 只有字符串和空元组相同时,地址才相同,否则不相同;
(2)不同文件(模块)里,部分数据驻留小数据池中(更多指的是这种情况)
int: -5 ~ 256 ; str: 长度为0,1; 只含字母数字下划线; 字符串*1得到的字符串; 指定驻留:sys模块导入的intern函数导入的数据;
(3)赋值(这也一点也可不说)
>>> values = [0,1,2] >>> values[1] = values >>> values [0, [...], 2] # 此案例解释了python中赋值的操作实际上是对象的引用,该对象的第二个元素就是对自己本身的引用,引用造成了无限循环,故该对象第二个元素的结果是无限的;
Python中的对象的缓存机制以及赋值(实际上是引用)都能起到节省内存的操作;
3.4 python内存回收
3.4.1 引用计数(主)
一个对象会计算自己被引用的次数,每增加一个引用,引用次数+1,相反-1,如果对象作为参数传递给函数,则引用次数+2,因为函数调用时内部有两个属性引用;查看引用计数:sys.getrefcount;当对象间出现相互循环调用时,则不能通过引用计数器进行销毁。
3.4.2 标记清除(辅)
如果两个对象的引用计数都为 1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被 回收的,也就是说,它们的引用计数虽然表现为非 0,但实际上有效的引用计数为 0。所以先将循环引 用摘掉,就会得出这两个对象的有效计数
3.4.3 分代回收(辅)
Python里面将对象回收分为三代;
默认一个对象创建之后,处于0代,0代的检测频率最高,当经过一定的检测频率该对象还存活,则移入下一代;
1代的检测频率比0代低,回收一定次数若该对对象还存活,则迁移至下一代;
2代的检测频率最低;
get_threshold():
(700, 10, 10)
700代表 新增的对象数 - 消亡的对象数 > 700时,触发一次0代回收
第一个10代表,每进行一次0代回收触发一次1代回收
第二个10代表,每进行一次1代回收触发一次2代回收
手动回收 gc.collect:
弱引用 weakref.ref:
3.4.4 内存池机制
Python按256kb这个分界点分为大内存和小内存:
–操作系统相关操作(第 -1,-2层)
–大内存:malloc函数进行分配,free函数释放内存(第0层)
-小内存调用:PyObject_Malloc 分配内存,不会调用free函数释放,该内存块直接留在内存池中以便下次使用(第1,2层)
–用户对Python对象的操作(第3层)
3.4.5 QS:Python内存泄漏
- Python会不会存在内存泄漏
- 你在项目过程中有没有遇到性能问题
分析:以上两个问题都可以用内存泄漏来回答;
思路:Python内存管理方式->自动管理分配的弊端->引用计数(相互调用)造成内存泄漏->引子;
# 案例
(答2:有出现过性能问题。之前的项目中出现过内存泄漏的情况。当时项目代码过程中出现了两个对象相互引用的情况。)
内存泄漏并非指内存在物理上的消息,而是应用程序分配某段内存后,由于涉及错误,失去了对该段内存的控制,因而造成了内存的浪费
(答1,2)编程语言的内存管理管理方式分为两种:手动管理和自动管理。手动管理机制的语言代表有C++,而Python是自动内存管理机制的编程语言。自动内存管理带来了开发效率的提升,但同时在某些场景下也存在隐患。在引用计数时,若两个对象相互引用,则会导致两个对象的技术一直≥1而导致两个对象一直不能被回收,从而导致内存泄漏的情况。
如何避免:
不使用一个对象时使用:del object来删除一个对象的引用计数就可以有效防止内存泄漏问题。
通过Python扩展模块gc来查看不能回收的对象的详细信息。
可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为0来判断是否内存泄漏。
3.4.6 内存管理调优手段
- 手动垃圾回收(gc.collect)
- 调高垃圾回收阈值
- 避免循环引用(手动解循环引用和使用弱引用)
弱引用:
(1)引用不会增加对象的引用次数
(2)弱引用返回被引用的对象,如果没有则返回None
(3)弱引用在缓存应用中很有用,因为我们不想仅因为被缓存引用着而始终保存缓存对象。
3.5 python异常处理
3.5.1 QS:列举常用异常
# 尽量写自己项目中常见的
IndexError # 索引超出范围
keyError # (字典)键不存在
IndentationError # 缩进异常
AttributeError # 尝试访问未知的对象属性
typeError # 不同类型异常操作
NameError # 尝试访问不存在的变量
3.5.2 python异常处理方式
- 主动抛出异常
raise xxError
- 用异常解决程序处理
try ... except xxError #python3 建议except 后面加异常类(PEP8)
try ... finally # 无论是否报错,finally代码块都执行
try ... except ... else ... # 没有报错执行else代码块,报错不执行
for/while ... else ... # 如果遇到break就执行else代码块内容,否则else代码块一律不执行
3.7 python正则处理
3.7.1 常用正则(必须会!!!)
# 1. email地址
\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{
2,14}
# 2.url地址
^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+
# 3.手机号(国内)
0?(13|14|15|17|18|19)[0-9]{
9}
# 4.电话号码(国内)
[0-9-()()]{
7,18}
# 5.腾讯qq号
[1-9]([0-9]{
5,11})
# 6.格式日期
\d{
4}(\-|\/|.)\d{
1,2}\1\d{
1,2}
# 7.身份证号
\d{
17}[\d|x]|\d{
15}
#8.整数 负整数 正整数
-?[1-9]\d*
-[1-9]\d*
[1-9]\d*
# 9. 浮点数 负浮点数 正浮点数
-?([1-9]\d*.\d*|0.\d*[1-9]\d*)
-([1-9]\d*.\d*|0.\d*[1-9]\d*)
[1-9]\d*.\d*|0.\d*[1-9]\d*
3.7.2 常用正则函数比较
findall 匹配字符串中相应内容,返回列表 [用法: findall("正则表达式","要匹配的字符串")]
search 通过正则匹配出第一个对象返回,通过group取出对象中的值
match 验证用户输入内容
split 切割
sub 替换
subn 替换
finditer 匹配字符串中相应内容,返回迭代器
compile 指定一个统一的匹配规则
3.8 python函数
3.8.1 python内置函数
尽量挑一些项目用的多的回答,注意不要写到三方模块的函数就行。
诸如:
len(), type(), chr(), dict(), eval(), exec(), filter(), id(), len(), map(), max(), min()等;
3.8.2 需要关注的函数
(1)返回迭代器的函数
### (1)enumerate
enumerate(iterable,[start=0])
功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
参数:
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
start: 可以选择开始的索引号(默认从0开始索引)
返回值:迭代器
### (2)zip
zip(iterable, ... ...)
功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
返回: 迭代器
(2)高级函数
高阶函数:能够把函数当成参数传递的就是高阶函数
# map
map(func,iterable)
功能:
把iterable里面所有数据 一一的放进到func这个函数中进行操作 ,把结果扔进迭代器
参数:
func 内置或自定义函数
iterable 具有可迭代性的数据 ([迭代器],[容器类型的数据],[range对象])
返回值:
返回最后的迭代器
# reduce
reduce(func,iterable)
功能:
先把iterable里面的前2个数据拿到func函数当中进行运算,得到结果,
在把计算的结果和iterable中的第三个数据拿到func里面进行运算,
依次类推 ,直到iterable里面的所有数据都拿完为止,程序结束
参数:
func 内置或自定义函数
iterable 具有可迭代性的数据 ([迭代器],