面试总结(1)
一、Python相关
1、Python的函数参数传递
看两个例子:
1 | a = 1 |
1 | a = [] |
所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。
通过id
来看引用a
的内存地址可以比较理解:
1 | a = 1 |
注:具体的值在不同电脑上运行时可能不同。
可以看到,在执行完a = 2
之后,a
引用中保存的值,即内存地址发生变化,由原来1
对象的所在的地址变成了2
这个实体对象的内存地址。
而第2个例子a
引用保存的内存值就不会发生变化:
1 | a = [] |
这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而 list, dict, set 等则是可以修改的对象。(这就是这个问题的重点)
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
如果还不明白的话,这里有更好的解释: http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference
2、Python中的元类
这个非常的不常用,但是像ORM这种复杂的结构还是会需要的,详情请看:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python
3、@staticmethod和@classmethod
Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:
1 | def foo(x): |
这里先理解下函数参数里面的self和cls.这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x)
,这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self, x)
,为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)
(其实是foo(a, x)
).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x)
.注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.
对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)
或者A.static_foo(x)
来调用.
\ | 实例方法 | 类方法 | 静态方法 |
---|---|---|---|
a = A() | a.foo(x) | a.class_foo(x) | a.static_foo(x) |
A | 不可用 | A.class_foo(x) | A.static_foo(x) |
更多关于这个问题:
- http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
- https://realpython.com/blog/python/instance-class-and-static-methods-demystified/
4、类变量和实例变量
类变量:
是可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。例如下例中,num_of_instance 就是类变量,用于跟踪存在着多少个Test 的实例。
实例变量:
实例化之后,每个实例单独拥有的变量。
1 | class Test(object): |
补充的例子
1 | class Person: |
这里p1.name="bbb"
是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name
一开始是指向的类变量name="aaa"
,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.
可以看看下面的例子:
1 | class Person: |
参考:http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block
5、Python自省
这个也是python彪悍的特性.
自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
1 | a = [1,2,3] |
6、字典推导式
1 | d = {key: value for (key, value) in iterable} |
7、Python中单下划线和双下划线
变量私有,魔法方法,名字改编 (Name Mangling)
8、字符串格式化:%、.format 、f”{}”
New in version 3.6.
9、迭代器和生成器
列表推导式、生成器、yield
10、*args和**kwargs 缺省参数
用*args
和**kwargs
只是为了方便并没有强制使用它们.
当你不确定你的函数里将要传递多少参数时你可以用*args
.例如,它可以传递任意数量的参数:
1 | def print_everything(*args): |
相似的,**kwargs
允许你使用没有事先定义的参数名:
1 | def table_things(**kwargs): |
你也可以混着用.命名参数首先获得参数值然后所有的其他参数都传递给*args
和**kwargs
.命名参数在列表的最前端.例如:
1 | def table_things(titlestring, **kwargs) |
*args
和**kwargs
可以同时在函数的定义中,但是*args
必须在**kwargs
前面.
当调用函数时你也可以用*
和**
语法.例如:
1 | def print_three_things(a, b, c): |
就像你看到的一样,它可以传递列表(或者元组)的每一项并把它们解包.注意必须与它们在函数里的参数相吻合.当然,你也可以在函数定义或者函数调用时用*.
http://stackoverflow.com/questions/3394835/args-and-kwargs
11、面向切面编程AOP和装饰器
装饰器的作用就是为了已经存在的函数添加额外的功能
12、鸭子类型
当一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子时,那么这只鸟就可以被称为鸭子。
13、Python中重载(不支持)
http://www.zhihu.com/question/20053359
函数重载主要是为了解决两个问题。
- 可变参数类型。
- 可变参数个数。
另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。
好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。
那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。
好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。
14、新式类和旧式类
新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.
深度优先
一个旧式类的深度优先的例子
1 | class A(): |
按照经典类的查找顺序从左到右深度优先
的规则,在访问d.foo1()
的时候,D这个类是没有的..那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过
15、__new__
和__init__
的区别
__new__
是一个静态方法,而__init__
是一个实例方法.__new__
方法会返回一个创建的实例,而__init__
什么都不返回.- 只有在
__new__
返回一个cls的实例时后面的__init__
才能被调用. - 当创建一个新实例时调用
__new__
,初始化一个实例时用__init__
.
16、单例模式
1 使用__new__
方法
2 使用装饰器
3 import
可以使用super函数来调用父类的相同方法。这样可以在不破坏继承关系的前提下,扩展或修改父类的行为。
17、Python中的作用域
本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)
18、GIL线程全局锁
一个核在同一时间只能运行一个线程。对于io密集型任务,多线程起到作用,而对于cpu密集型任务,多线程几乎占不到任何优势。反而可能因为争夺资源而变慢。
https://www.oschina.net/translate/pythons-hardest-problem
“free threading”补丁移除了GIL,但是当用单线程执行时,速度大约降低了40%。
19、协程
Coroutine是一个可以暂停执行将执行权让给其他Coroutine或者Awaitables obj的函数,等待执行完成后继续执行,并可以多次进行这样的暂停与继续。功能有点像cpu任务调度的时间片的概念,并发执行任务时,cpu调用给每一个任务分配了一定的时间片,时间片到了之后挂起当前的线程转给其他线程使用。
https://blog.csdn.net/rhx_qiuzhi/article/details/127452923
20、闭包
闭包(closure)是一个函数对象,它与它的环境变量(包括自由变量)的引用组合而成的实体。闭包可以保留函数定义时所在的环境变量,即使这些变量在定义时不在该函数的作用域内也可以使用。闭包可以让函数像对象一样被传递、赋值、作为参数传递,甚至在函数内部定义函数。
21、lambda函数
匿名函数
1 | map( lambda x: x*x, [y for y in range(10)] ) |
https://www.zhihu.com/question/20125256
22、函数式编程
filter、map、reduce
1 | a = filter(lambda x: x < 5, [4, 5, 6, 7, 8, 9]) |
23、拷贝
引用、浅拷贝、深拷贝
24、垃圾回收
引用计数、标记清除、分代技术
25、List
https://www.jianshu.com/p/J4U6rR
26、Python中的is
is是对比地址,== 是对比值
27、read、readline和redlines
- read读取整个文件
- readline读取下一行,使用生成器方法
- readlines读取整个文件到一个迭代器一共我们遍历
28、super和init
super可以调用父类的函数,同时在不破坏继承关系的情况下,拓展或者修改父类的行为
29、range和xrange
pyhton3的range相当于python2的xrange
二、网络相关
1、三次握手
- 客户端通过向服务器发送一个SYN来创建一个主动打开,作为三次握手的一部分。客户端把这段链接的序号设定为随机数A
- 服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK的确认码应为A+1,SYN/ACK包本身又有一个随机序号B。
- 最后客户端再发送一个ACK。当服务端接收到这个ACK的时候,就完成了三次握手,并进入链接创建状态。此时包序号被设定为收到的确认号A+1,二响应则为B+1。
2、四次挥手
- 客户端发送一个数据分段, 其中的 FIN 标记设置为1. 客户端进入 FIN-WAIT 状态. 该状态下客户端只接收数据, 不再发送数据.
- 服务器接收到带有 FIN = 1 的数据分段, 发送带有 ACK = 1 的剩余数据分段, 确认收到客户端发来的 FIN 信息.
- 服务器等到所有数据传输结束, 向客户端发送一个带有 FIN = 1 的数据分段, 并进入 CLOSE-WAIT 状态, 等待客户端发来带有 ACK = 1 的确认报文.
- 客户端收到服务器发来带有 FIN = 1 的报文, 返回 ACK = 1 的报文确认, 为了防止服务器端未收到需要重发, 进入 TIME-WAIT 状态. 服务器接收到报文后关闭连接. 客户端等待 2ms 后未收到回复, 则认为服务器成功关闭, 客户端关闭连接.
3、ARP协议
地址解析协议(Address Resolution Protocol),其基本功能为透过目标设备的IP地址,查询目标的MAC地址,以保证通信的顺利进行。它是IPv4网络层必不可少的协议,不过在IPv6中已不再适用,并被邻居发现协议(NDP)所替代。
4、urllib和urllib2的区别
- urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。
- urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。这意味着,你不可以伪装你的User Agent字符串等。
5、Post和Get的区别
- Post比Get安全一点点,因为post请求之后的信息不会被浏览器记录
- post是向服务器新增一条数据,而get则是向服务器请求获取一条数据
6、Cookie和Session
存储位置 | 客户端 | 服务器端 |
---|---|---|
Cookie | Session | |
目的 | 跟踪会话,也可以保存用户偏好设置或者保存用户名密码等 | 跟踪会话 |
安全性 | 不安全 | 安全 |
7、apache和nginx的区别
nginx 相对 apache 的优点:
- 轻量级,同样起web 服务,比apache 占用更少的内存及资源
- 抗并发,nginx 处理请求是异步非阻塞的,支持更多的并发连接,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能
- 配置简洁
- 高度模块化的设计,编写模块相对简单
- 社区活跃
apache 相对nginx 的优点:
- rewrite ,比nginx 的rewrite 强大
- 模块超多,基本想到的都可以找到
- 少bug ,nginx 的bug 相对较多
- 超稳定
8、网站用户密码保存
1.明文保存
2.明文hash后保存,如md5
3.MD5+Salt方式,随机加Salt
9、HTTP和HTTPS
10、CSRF和XSS
- CSRF(Cross-site request forgery)跨站请求伪造
- XSS(Cross Site Scripting)跨站脚本攻击
CSRF重点在请求,XSS重点在脚本
11、幂等性
- HTTP方法的幂等性是指一次或者多次请求他们应该具有同样的副作用。
- GET 请求符合,不会改变资源的状态,不论调用一次还是N次都没有副作用。
- POST 请求不符合,两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;
- DELETE 请求符合,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子
- PUT 请求符合 对同一URI进行多次PUT的副作用和一次PUT是相同的;
12、RESTful架构
13、SOAP
14、RPC
RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
总结:服务提供的两大流派.传统意义以方法调用为导向通称RPC。为了企业SOA,若干厂商联合推出webservice,制定了wsdl接口定义,传输soap.当互联网时代,臃肿SOA被简化为http+xml/json.但是简化出现各种混乱。以资源为导向,任何操作无非是对资源的增删改查,于是统一的REST出现了.
进化的顺序: RPC -> SOAP -> RESTful
15、CGI和WSGI
CGI是通用网关接口,是连接web服务器和应用程序的接口,用户通过CGI来获取动态数据或文件等。 CGI程序是一个独立的程序,它可以用几乎所有语言来写,包括perl,c,lua,python等等。
WSGI, Web Server Gateway Interface,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的其中一个目的就是让用户可以用统一的语言(Python)编写前后端。
官方说明:PEP-3333
16、中间人攻击
在GFW里屡见不鲜的,呵呵.
中间人攻击(Man-in-the-middle attack,通常缩写为MITM)是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。、
17、c10k问题
所谓c10k问题,指的是服务器同时支持成千上万个客户端的问题,也就是concurrent 10 000 connection(这也是c10k这个名字的由来)。 推荐: https://www.cnblogs.com/lnlvinso/p/14433300.html
18、socket
推荐: http://www.360doc.com/content/11/0609/15/5482098_122692444.shtml
Socket=Ip address+ TCP/UDP + port
19、浏览器缓存
推荐: http://www.cnblogs.com/skynet/archive/2012/11/28/2792503.html
304 Not Modified
20、HTTP1.0和HTTP1.1
推荐: http://blog.csdn.net/elifefly/article/details/3964766
- 请求头Host字段,一个服务器多个网站
- 长链接
- 文件断点续传
- 身份认证,状态管理,Cache缓存
21、Ajax
AJAX,Asynchronous JavaScript and XML(异步的 JavaScript 和 XML), 是与在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。