Python面试笔记二

一、算法

1、归并排序

2、快速排序

3、算法复杂度

4、哈希表数据结构

二、数据库

1、设计一个用户关注系统的数据库表

多对多自关联:用户互粉时,一张表可以自己跟自己实现多对多的关联:m = models.ManyToManyField('表名',related_name='utu')

2、写三个相关的SQL语句

#-- Mysql在执行sql语句时的执行顺序:
#-- from  where  select group by  having order by

select JS as JS成绩 from ExamResult having JS成绩 >90

select A.num, A.name, B.name from A inner join B on A.nid = B.nid

select sum(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))
                                                    as 总成绩 from ExamResult;

3、创建索引

# 普通索引
INDEX index_emp_name (name)
或者
KEY index_dept_name (dept_name)

# 唯一索引
UNIQUE INDEX index_emp_name (name)

# 全文索引
FULLTEXT INDEX index_resume (resume)

#多列索引(联合索引)
INDEX index_name_resume (name, resume)

#CREATE在已存在的表上创建索引
CREATE  [UNIQUE | FULLTEXT | SPATIAL ]  INDEX  索引名 ON 表名 (字段名[(长度)]  [ASC |DESC]) ;
    
#ALTER TABLE在已存在的表上创建索引
 ALTER TABLE 表名 ADD  [UNIQUE | FULLTEXT | SPATIAL ] INDEX索引名 (字段名[(长度)]  [ASC |DESC]) ;

# 删除索引
DROP INDEX index_emp_name on emp1

4、MySQL引擎

5、MySQL优化

三、操作系统和网络编程

1、TCP/IP协议,TCP和UDP的区别

互联网协议(Internet Protocol Suite)是一个网络通信模型,以及一整个网络传输协议家族,为互联网的基础通信架构。它常被通称为TCP/IP协议族,简称TCP/IP。

TCP协议是面向连接,保证高可靠性(数据无丢失,数据无失序,数据无错误,数据无重复达到)
UDP:面向无连接的通讯协议,不可靠的传输,数据丢失,不管数据包的顺序、错误或重发(qq基于udp协议)

2、HTTP协议

HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型,是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。 
HTTP连接最显著的特点是:客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。

3、应用层实现协议的细节,比如HTTPS,DNS

HTTPS协议 = HTTP协议 + SSL/TLS协议,在HTTPS数据传输的过程中,需要用SSL/TLS对数据进行加密和解密,需要用HTTP对加密后的数据进行传输,由此可以看出HTTPS是由HTTP和SSL/TLS一起合作完成的。 
  SSL的全称是Secure Sockets Layer,即安全套接层协议,是为网络通信提供安全及数据完整性的一种安全协议。SSL协议在1994年被Netscape发明,后来各个浏览器均支持SSL,其最新的版本是3.0。 
  TLS的全称是Transport Layer Security,即安全传输层协议。在TLS与SSL3.0之间存在着显著的差别,主要是它们所支持的加密算法不同,所以TLS与SSL3.0不能互操作。虽然TLS与SSL3.0在加密算法上不同,但是在我们理解HTTPS的过程中,我们可以把SSL和TLS看做是同一个协议。

dns是一个域名系统,是万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。

通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。在解析域名时,可以首先采用静态域名解析的方法,如果静态域名解析不成功,再采用动态域名解析的方法,域名是互联网上的身份标识,是不可重复的唯一标识资源; 互联网的全球化使得域名成为标识一国主权的国家战略资源。

应用层常用协议

1 、DNS:域名系统DNS是因特网使用的命名系统,用来把便于人们使用的机器名字转换为IP地址。

现在顶级域名TLD分为三大类:国家顶级域名nTLD;通用顶级域名gTLD;基础结构域名

域名服务器分为四种类型:根域名服务器;顶级域名服务器;本地域名服务器;权限域名服务器。

2、FTP:文件传输协议FTP是因特网上使用得最广泛的文件传送协议。FTP提供交互式的访问,允许客户指明文件类型与格式,并允许文件具有存取权限。FTP其于TCP。

3、 telnet远程终端协议:telnet是一个简单的远程终端协议,它也是因特网的正式标准。又称为终端仿真协议。

4、HTTP:超文本传送协议,是面向事务的应用层协议,它是万维网上能够可靠地交换文件的重要基础。http使用面向连接的TCP作为运输层协议,保证了数据的可靠传输。
5、电子邮件协议SMTP:即简单邮件传送协议。SMTP规定了在两个相互通信的SMTP进程之间应如何交换信息。SMTP通信的三个阶段:建立连接、邮件传送、连接释放。
6 、POP3:邮件读取协议,POP3(Post Office Protocol 3)协议通常被用来接收电子邮件。

4、多线程、多进程、协程

5、Linux常用命令

6、长链接换短连接的技术实现

  用一个递增的数字去维护数据库,只需要把数字转换成字母的编码格式,就能得到相应的key,然后再把value存成长链接,就实现了短链接和长链接的对应关系。

通过发号策略,给每一个过来的长地址,发一个号即可,小型系统直接用mysql的自增索引就搞定了。如果是大型应用,可以考虑各种分布式key-value系统做发号器。不停的自增就行了。第一个使用这个服务的人得到的短地址是 http://xx.xx/0 第二个是 http://xx.xx/1 第11个是 http://xx.xx/a 第依次往后,相当于实现了一个62进制的自增字段即可。

6.1、62进制如何用数据库或者KV存储来做?

其实我们并不需要在存储中用62进制,用10进制就好了。比如第10000个长地址,我们给它的短地址对应的编号是9999,我们通过存储自增拿到9999后,再做一个10进制到62进制的转换,转成62进制数即可。这个10~62进制转换,你完全都可以自己实现。

6.2、如何保证同一个长地址,每次转出来都是一样的短地址

用key-value存储,保存“最近”生成的长对短的一个对应关系。注意是“最近”,也就是说,我并不保存全量的长对短的关系,而只保存最近的。比如采用一小时过期的机制来实现LRU淘汰。

这样的话,长转短的流程变成这样:

  • 在这个“最近”表中查看一下,看长地址有没有对应的短地址
    • 有就直接返回,并且将这个key-value对的过期时间再延长成一小时
    • 如果没有,就通过发号器生成一个短地址,并且将这个“最近”表中,过期时间为1小时

所以当一个地址被频繁使用,那么它会一直在这个key-value表中,总能返回当初生成那个短地址,不会出现重复的问题。如果它使用并不频繁,那么长对短的key会过期,LRU机制自动就会淘汰掉它。

当然,这不能保证100%的同一个长地址一定能转出同一个短地址,比如你拿一个生僻的url,每间隔1小时来转一次,你会得到不同的短地址。但是这真的有关系吗?

6.3、如何保证发号器的大并发高可用

上面设计看起来有一个单点,那就是发号器。如果做成分布式的,那么多节点要保持同步加1,多点同时写入,这个嘛,以CAP理论看,是不可能真正做到的。其实这个问题的解决非常简单,我们可以退一步考虑,我们是否可以实现两个发号器,一个发单号,一个发双号,这样就变单点为多点了?依次类推,我们可以实现1000个逻辑发号器,分别发尾号为0到999的号。每发一个号,每个发号器加1000,而不是加1。这些发号器独立工作,互不干扰即可。而且在实现上,也可以先是逻辑的,真的压力变大了,再拆分成独立的物理机器单元。1000个节点,估计对人类来说应该够用了。如果你真的还想更多,理论上也是可以的。

6.4、跳转用301还是302

301是永久重定向,302是临时重定向。短地址一经生成就不会变化,所以用301是符合http语义的,同时对服务器压力也会有一定减少。

但是如果使用了301,我们就无法统计到短地址被点击的次数了。而这个点击次数是一个非常有意思的大数据分析数据源。能够分析出的东西非常非常多。所以选择302虽然会增加服务器压力,但是我想是一个更好的选择。

7、Redis和Memcached

Memcache 是一个开源、高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个存储键/值对的HashTable,Memcache这个软件项目一般叫Memcache,但项目的主程序文件叫memcached.exe(字母d可以理解为daemon),是靠服务端的这个守护进程管理这些HashTable。由于这个命名问题,所以很多人把这个软件系统叫memcache,想叫成memcached也没什么问题!其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

使用Redis有哪些好处?

(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)

(2) 支持丰富数据类型,支持string,list,set,sorted set,hash,memcached所有的值均是简单的字符串

(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行

(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

Memcache与Redis的区别都有哪些?

1)、存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,这样能保证数据的持久性。

2)、数据支持类型 Memcache对数据类型支持相对简单。 Redis有复杂的数据类型。

3)value大小 redis最大可以达到1GB,而memcache只有1MB

 redis常见性能问题和解决方案:

(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次

(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

(4) 尽量避免在压力很大的主库上增加从库

(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3... 这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

 redis 最适合的场景

(1)、会话缓存(Session Cache)

(2)、全页缓存(FPC)

(3)、队列

(4),排行榜/计数器

(5)、发布/订阅

四、web开发

1、web开发优化上的细节,比如如何处理长时间相应

  分表分库,小图片规整,css/js合并压缩,Redis缓存热点数据,使用浏览器的缓存功能

2、函数new和init的区别

1、继承自object的新式类才有__new__

2、__new__至少要有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别

3、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过super(当前类名, cls))__new__出来的实例,或者直接是object的__new__出来的实例

4、__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

5、如果__new__创建的是当前类的实例,会自动调用__init__函数,通过return语句里面调用的__new__函数的第一个参数是cls来保证是当前类实例,如果是其他类的类名,;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。

3、Python的优缺点

优点:

  • 1.简洁易懂

  • 2.跨平台

  • 3.可扩展性

  • 可移植性

  • 既支持面向过程的函数编程也支持面向对象的抽象编程

  • 丰富的库

缺点:

  • 运行速度慢,和C相差五倍,如果是大规模计算问题,大约能差10倍以上,python的效率问题也不是技术原因导致的,而且python也对这方面有所弥补,那就是对效率敏感的地方可以用C重写,以达到预期的效率需求,但是治标不治本,追求python的高开发效率的同时,就得舍弃一些性能上的追求。

  • 多线程全局锁GIL,导致计算密集型任务效率低下;以至于我现在对高并发计算都采取多进程的模式。多进程模式的通讯效率肯定比多线程低,而且麻烦。

  • python的开源性是的Python语言不能加密;

  • 语法糖太多了点,当然,这是纯粹的个人感觉。语法糖是把双刃剑,用的好,可以简化编写和阅读,但是太多,往往容易引入语法混乱和额外的约束。

  • 语言的自构建特性混乱。虽说不是每门语言都强调自构建特性,但是通常而言,都是使用C实现一个内核,由内核实现一些基础操作。再由基础操作实现更复杂的操作。每层的边界都是比较清晰的。python中几乎所有的库是由C实现的,库与库之间没有层级关系;

  • python的沙盒化也是个问题,如果沙盒做的够好,我完全可以把python作为一个客户级别的平台。用C写一个很简单的类似浏览器的东西,下载一个URL的python包回去运行(或者仅仅检查更新)。从而保证本地效果/跨平台/安全性。现在?一个都保证不了。我连把一个python包转移到另一台同构设备上都很麻烦(如果两者不是严格匹配,例如系统差异,系统版本差异)无论是web开发还是移动终端开发都必须走传统模式。

猜你喜欢

转载自www.cnblogs.com/charliedaifu/p/10555668.html