面试考点

语言基础

python单元测试
动态语言不写单元测试风险就挺大的.

什么是单元测试?
unit testing
针对程序模块进行正确性检验
一个函数, 一个类进行验证
自底向上保证程序正确性
为什么要写单元测试?
三无代码不可取(无文档, 无注释, 无单侧)
保证代码逻辑的正确性(甚至有些采用测试驱动开发(tdd))
单测影响设计, 易测的代码往往是高内聚低耦合
回归测试, 防止改一处整个服务不可用

单元测试相关的库
nose/pytest较为常用
mock模块用来模拟替换网络请求等
coverage统计测试覆盖率.

算法和数据结构

编程范式

面向对象基础及python类常考问题

什么是面向对象编程

object orirnted programming oop

把对象作为基本单元, 把对象抽象成类(class), 包含成员和方法

数据封装, 继承, 多态

python中使用类来实现, 过程式编程(函数), oop类

1
2
3
4
5
6
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def print_name(self):
print('my name is {}'.format(self.name))

组合与继承

先使用组合而非继承

  • 组合是使用其他的类实例作为自己的一个属性(Has-a关系)
  • 子类继承父类的属性和方法(is a关系)
  • 优先使用组合保持代码简单

类变量和实例变量的区别

区分类变量和实例变量

  • 类变量是由所有实例共享
  • 实例变量是由实例单独享有, 不同实例之间不影响

  • 当我们需要在一个类的不同实例之间共享变量的时候使用类变量

classmethod/staticmethod区别

  • 都可以通过 class.method的方式使用
  • classmethod第一个参数是cls, 可以引用类变量
  • staticmethod使用起来和普通函数一样, 只不过放在类里去组织.

使用元类? 使用场景

元类(meta class) 是创建类的类

  • 元类允许我们控制类的生成, 比如修改类的属性
  • 使用type来定义元类
  • 元类最常见的一个使用场景就是orm框架

面向对象与python类常考题

  • 什么是面向对象编程, python如何使用类
  • 组合 vs 继承, 类变量 vs 实例变量; classmethod vs staticmethod

python装饰器 面向切面编程

什么是装饰器(decorator)

python中一切皆对象, 函数也可以当做参数传递

装饰器是接受函数作为参数, 添加功能后返回一个新函数的函数(类)

python中通过@使用装饰器

编写一个记录函数耗时的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import time
def log_time(func):
def _log(*args, **kwargs):
beg = time.time()
res = func(*args, **kwargs)
print('use time:{}'.format(time.time()-beg))
return res
return _log

@log_time
def mysleep():
time.sleep(1)

mysleep()

使用类编写

1
2
3
4
5
6
7
8
9
10
11
12
import time
class Logtime:
def __call__(self, func):
def _log(*args, **kwargs):
beg = time.time()
res = func(*args, **kwargs)
print('use time:{}'.format(time.time()-beg))
return res
return _log
@LogTime()
def mysleep():
time.sleep(1)

使用类装饰器比较方便实现装饰器

设计模式: 创建型模式python应用面试

创建型模式

工厂模式(Factory): 解决对象创建问题

构造模式(builder): 控制复杂对象的创建

原型模式(prototype): 通过原型的克隆创建新的实例

单例模式(borg/singleton)”:一个类只能创建同一个对象

对象池模式(pool):预先分配同一个类型的一组实例

惰性计算模式(lazy evaluation): 延迟计算(python 的property)


什么是工厂模式

解决对象创建问题

解耦对象的创建和使用

包括工厂方法和抽象工厂

什么是构造模式(builder)

用来控制复杂对象的构造

创建和表示分离, 比如你要买电脑, 工厂模式直接给你需要的电脑

但是构造模式允许你自己定义电脑的配置, 组装完成后给你.

原型模式

什么是原型模式
通过克隆模式来创建新的实例
可以使用相同的原型, 通过修改部分属性来创建新的示例
用途: 对于一些创建实例开销比较高的地方可以用原型模式

单例模式

单例模式的实现由多种方式
单例模式: 一个类创建出来的对象都是同一个
python的模块其实就是单例的, 只会导入一次
使用共享同一个实例的方式来创建单例模式.

操作系统

linux常考命令, 了解linxu工作原理和常用工具,需要了解查看文件, 进程, 内存相关的一些命令, 用来调试和排查

早期采用lamp/lnmp架构,现在采用微服务/容器架构.

linux命令众多, 如何知道一个命令的用法

  • 使用man命令查询用法, 但是man手册比较晦涩
  • 使用工具自带的help, 比如pip –help
  • 这里介绍一个man的替代工具tldr. pip install tldr.

掌握常见的文件操作工具

  • chown/chmod/chgrp
  • ls/rm/cd/cp/mv/touch/rename/ln(软连接和硬链接)等 软连接类似快捷方式, 保存了指向文件的绝对路径, 如果访问的时候把路径替换成原来的路径.对于操作系统来说, 它是通过inode来访问硬盘上的区块的, 对于软连接, inode值和原来的是不一样的,硬链接是一样.
  • locate/find/grep定位查找和搜索. find . -name ‘*.pyc’ -delete.

文件或者日志查看工具

  • 编辑器vi/nano
  • cat/head/tail 查看文件
  • more/less 交互式查看文件

进程操作命令

  • ps查看进程
  • kill杀死进程 -9 -15
  • top/htop 监控进程

掌握常见的内存操作工具

  • free 查看可用内存
  • 了解每一列的具体含义
  • 排查内存泄露问题

网络操作命令

  • ifconfig查看网卡信息
  • lsof/netstat 查看端口信息
  • ssh/scp 远程登录/复制. tcpdump抓包

用户/组操作命令

  • useradd/usermod
  • groupadd/groupmod

操作系统线程和进程常考题

进程和线程的区别

进程和线程对比

进程是对运行时程序的封装, 是系统资源调度和分配的基本单位.

线程是进程的子任务, cpu调度和匹配的基本单位, 实现进程内并发.

一个进程可以包含多个线程, 线程依赖进程存在, 并共享进程内存

并发和并行的区别

线程安全

一个操作可以在线程环境中安全使用, 获取正确的结果.

线程安全的操作好比线程是顺序执行而不是并发执行的(i+=1)

一般如果涉及到写操作需要考虑如何让多个线程安全访问数据.

线程同步的方式

了解线程同步的方式, 如何保证线程安全

互斥量(锁):通过互斥机制防止多个线程同时访问公共资源

信号量(semphare): 控制同一时刻多个线程访问同一个资源的线程

事件(信号): 通过通知的方式保持多个线程同步.

进程间通信的方式

进程间传递信号或者数据

管道/匿名管道/有名管道(pipe)

信号(signal): 比如用户使用ctrl-c产生sigint程序终止信号

消息对列(message)

共享内存(share memory)

信号量(semaphore)

套接字(socket):最常见的方式, 我们web应用都是这种方式.

底层的操作采用用的到.

threading.Thread类

python有gil, 可以用多进程是实现cpu密集程序

multiprocessing多进程模块

multiprocessing.Process类实现多进程

一般用在cpu密集程序里, 避免GIL的影响.


操作系统内存管理机制常见考题

什么是分页机制

逻辑地址和物理地址的内存分配管理方案

程序的逻辑地址划分固定大小的页(page)

物理地址分为同样大小的帧(Rrame)

通过页表对应逻辑地址和物理地址

什么是分段机制

分段为了满足代码的一些逻辑需求

数据共享, 数据保护, 动态链接等

通过段表实现逻辑地址和物理地址的映射关系

每个段内部是连续的内存分配, 段和段之间是离散分配的

分页vs分段

页是出于内存利用率的角度提出的离散分配机制.

段是出于用户角度, 用于数据保护, 数据隔离等用途的管理机制

页的大小是固定的, 操作系统决定;段大小不确定, 用户程序决定.

什么是虚拟内存

通过把一部分暂时不用的内存信息放到硬盘上

  • 局部性原理, 程序运行时候只有部分必要的信息装入内存
  • 内存中暂时不需要的内容放到硬盘上
  • 系统似乎提供了比实际内存大得多的容量, 称之为虚拟内存

什么是内存抖动(颠簸)

本质是频繁的页调度行为

  • 频繁的页调度, 进程不断产生缺页中断
  • 置换一个页, 又不断再次需要这个页
  • 运行程序太多, 页面替换策略不好.终止进程或者增加物理内存.

python的垃圾回收机制原理

python无需手动回收内存 ?他的垃圾回收机制是如何实现的呢?

  • 引用计数为主(缺点:循环引用无法解决)
  • 引入标记清除和分代回收解决引用计数的问题
  • 引用计数为主+ 标记清除和分代回收为辅

线程练习题

如何使用python的threading模块

请你使用python的threading模块完成一个多线程爬虫类

要求1:该类可以传入最大线程数和需要抓取的网址列表

要求2: 该类可以通过继承的方式提供一个处理response的方法

网络编程

网络协议tcp/udp/http常考题

浏览器输入一个url中间经历的过程

中间涉及了那些过程

包含那些网络协议

每个协议都干了什么?

dns查询-> tcp握手-> http请求->反向代理-> wsgi->web

tcp三次握手

tcp vs udp

面向连接, 可靠的, 基于字节流

无连接, 不可靠, 面向报文

了解常见的http响应状态码

数据库考察

redis的使用;缓存使用中的坑
为什么要使用缓存? 使用场景
主要讨论的是内存缓存(常见的有redis和mencached)
缓解关系数据库(常见的是mysql)并发访问的压力: 热点数据
减少响应时间: 内存IO速度比磁盘快
提升吞吐量:redis等内存数据库单机就可以支撑很大并发

redis和mencached主要区别
数据类型. redis单进程模式, mencached是多线程,非阻塞IO模式

redis的常用数据类型, 使用方式
5种类型:
string:用来实现简单的kv键值对存储, 比如计数器.
list(链表):实现双向链表, 比如用户的关注, 粉丝列表.
hash(哈希表): 用来存储彼此相关信息的键值对.
set(集合): 存储不重复元素, 比如用户的关注者.
sorted set(有序集合): 实时信息排行榜.
对于中高级工程师, 需要了解redis各种类型的c底层实现方式.
redis设计实现这本书.
string:整数或者sds(simple dynamic string)
list: ziplist或者double linkedlist
hash: ziplist或者hashtable
set: intset或者hashtable
sortedset: skiplist跳跃表
redis 实现的跳跃表是什么结构?
二分的方式.

redis有哪些持久化方式?

快照方式: 把数据快照放在磁盘二进制文件中, dump.rgb
aof: 每一个写命令追加到appendonly.aof
什么是redis事务?
redis和mysql的事务有什么不同?
将多个请求打包, 一次性, 按序执行多个命令的机制
redis通过multl,exec, watch等命令实现事务功能
redis如何实现分布式锁?
使用setnx实现加锁, 可以同时通过expire添加超时时间
锁的value值可以使用一个随机的uuid或者特定的命名
释放锁的时候,通过uuid判断是否是该锁, 是则执行delete释放锁.

缓存使用问题: 数据一致性问题, 缓存穿透, 击穿, 雪崩问题
使用缓存的模式?
cache aside: 同时更新缓存和数据库.
read/write through: 先更新缓存, 缓存负责同步更新数据库.
write behind caching: 先更新缓存, 缓存定期异步更新数据库.
数据库与缓存的数据一致性, 一般先更新数据库, 再更新缓存.

如何解决缓存穿透问题?
大量查询不到的数据的请求落到后端数据库, 数据库压力增大.
由于大量缓存查不到就去数据库取, 数据库也没有要查的数据
解决: 对于没查到返回为None的数据也缓存
插入数据的时候删除相应缓存, 或者设置较短的超时时间.

如何解决缓存击穿问题?
某些非常热点的数据key过期. 大量请求打到后端数据库.
热点数据key失效导致大量请求打到数据库增加数据库压力.
分步式锁: 获取锁的线程从数据库拉数据更新缓存, 其他线程等待
异步后台更新: 后台任务针对过期的key自动刷新.

如何解决缓存雪崩问题?
缓存不可用或者大量缓存key同时失效,大量请求直接打到数据库
多级缓存: 不同级别的key设置不同的超时时间
随机时间: key 的超时时间随机设置, 放止同时超时.
架构层: 提升系统可用性. 监控, 报警完善等
实事求是, 知道多少答多少.

web框架

前后端分离与resful常见面试题
什么是前后端分离? 什么是restful?
后端只负责提供数据接口, 不再渲染模板, 前端获取数据并呈现
前后端解耦, 接口复用(前端和客户端公用接口), 减少开发量
各司其职, 前后端同步开发, 提升工作效率.定义好接口规范
更有利于调试, 测试和运维部署.

restful是一种软件架构风格
representation state transfer
表现层状态转移, 由http协议的主要设计者roy fielding提出
资源(resources), 表现层, 状态转化
是一种以资源为中心的web软件架构风格, 可以用ajax和restfulweb服务构建应用.
三个名词的解释:
resources(资源):使用urI指向的一个实体
representation(表现层): 资源的表现形式, 比如图片, html文本
state transfer(状态转换): get, post, put, delete http动词来操作资源, 实现资源状态的改变.
利用这些动词增删改查.

设计概念和准则
所有事物抽象为资源(resource), 资源对应唯一的标识(identifier)
资源通过接口进行操作实现状态转移,操作本身是无状态的.
对资源的操作不会改变资源的标识.

什么是restful api
restful风格的api接口
通过 http get/post/put/delete 获取/新建/更新/删除 资源
一般使用json格式返回数据
一般web框架都有相应的插件支持restful api

tornado 也是一个微框架.

系统设计

感谢支持 !
0%