一、Python相关

1、Python的函数参数传递

看两个例子:

1
2
3
4
5
a = 1
def fun(a):
a = 2
fun(a)
print a # 1
1
2
3
4
5
a = []
def fun(a):
a.append(1)
fun(a)
print a # [1]

所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。

通过id来看引用a的内存地址可以比较理解:

1
2
3
4
5
6
7
8
a = 1
def fun(a):
print "func_in",id(a) # func_in 41322472
a = 2
print "re-point",id(a), id(2) # re-point 41322448 41322448
print "func_out",id(a), id(1) # func_out 41322472 41322472
fun(a)
print a # 1

注:具体的值在不同电脑上运行时可能不同。

可以看到,在执行完a = 2之后,a引用中保存的值,即内存地址发生变化,由原来1对象的所在的地址变成了2这个实体对象的内存地址。

而第2个例子a引用保存的内存值就不会发生变化:

1
2
3
4
5
6
7
a = []
def fun(a):
print "func_in",id(a) # func_in 53629256
a.append(1)
print "func_out",id(a) # func_out 53629256
fun(a)
print a # [1]

这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def foo(x):
print "executing foo(%s)"%(x)

class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)

@classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)

@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x

a=A()

这里先理解下函数参数里面的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)

更多关于这个问题:

  1. http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
  2. https://realpython.com/blog/python/instance-class-and-static-methods-demystified/
4、类变量和实例变量

类变量:

是可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。例如下例中,num_of_instance 就是类变量,用于跟踪存在着多少个Test 的实例。

实例变量:

实例化之后,每个实例单独拥有的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Test(object):  
num_of_instance = 0
def __init__(self, name):
self.name = name
Test.num_of_instance += 1

if __name__ == '__main__':
print Test.num_of_instance # 0
t1 = Test('jack')
print Test.num_of_instance # 1
t2 = Test('lucy')
print t1.name , t1.num_of_instance # jack 2
print t2.name , t2.num_of_instance # lucy 2

补充的例子

1
2
3
4
5
6
7
8
9
class Person:
name="aaa"

p1=Person()
p2=Person()
p1.name="bbb"
print p1.name # bbb
print p2.name # aaa
print Person.name # aaa

这里p1.name="bbb"是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name="aaa",但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.

可以看看下面的例子:

1
2
3
4
5
6
7
8
9
class Person:
name=[]

p1=Person()
p2=Person()
p1.name.append(1)
print p1.name # [1]
print p2.name # [1]
print Person.name # [1]

参考:http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block

5、Python自省

这个也是python彪悍的特性.

自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().

1
2
3
4
5
a = [1,2,3]
b = {'a':1,'b':2,'c':3}
c = True
print type(a),type(b),type(c) # <type 'list'> <type 'dict'> <type 'bool'>
print isinstance(a,list) # True
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
2
3
4
5
6
7
8
>>> def print_everything(*args):
for count, thing in enumerate(args):
... print '{0}. {1}'.format(count, thing)
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage

相似的,**kwargs允许你使用没有事先定义的参数名:

1
2
3
4
5
6
7
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print '{0} = {1}'.format(name, value)
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit

你也可以混着用.命名参数首先获得参数值然后所有的其他参数都传递给*args**kwargs.命名参数在列表的最前端.例如:

1
def table_things(titlestring, **kwargs)

*args**kwargs可以同时在函数的定义中,但是*args必须在**kwargs前面.

当调用函数时你也可以用***语法.例如:

1
2
3
4
5
6
7
>>> def print_three_things(a, b, c):
... print 'a = {0}, b = {1}, c = {2}'.format(a,b,c)
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)

a = aardvark, b = baboon, c = cat

就像你看到的一样,它可以传递列表(或者元组)的每一项并把它们解包.注意必须与它们在函数里的参数相吻合.当然,你也可以在函数定义或者函数调用时用*.

http://stackoverflow.com/questions/3394835/args-and-kwargs

11、面向切面编程AOP和装饰器

​ 装饰器的作用就是为了已经存在的函数添加额外的功能

12、鸭子类型

​ 当一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子时,那么这只鸟就可以被称为鸭子。

13、Python中重载(不支持)

http://www.zhihu.com/question/20053359

函数重载主要是为了解决两个问题。

  1. 可变参数类型。
  2. 可变参数个数。

另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。

好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。

那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。

好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。

14、新式类和旧式类

​ 新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.

深度优先

一个旧式类的深度优先的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A():
def foo1(self):
print "A"
class B(A):
def foo2(self):
pass
class C(A):
def foo1(self):
print "C"
class D(B, C):
pass

d = D()
d.foo1()

# A

按照经典类的查找顺序从左到右深度优先的规则,在访问d.foo1()的时候,D这个类是没有的..那么往上查找,先找到B,里面没有,深度优先,访问A,找到了foo1(),所以这时候调用的是A的foo1(),从而导致C重写的foo1()被绕过

15、__new____init__的区别
  1. __new__是一个静态方法,而__init__是一个实例方法.
  2. __new__方法会返回一个创建的实例,而__init__什么都不返回.
  3. 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
  4. 当创建一个新实例时调用__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
2
3
4
5
6
7
8
a = filter(lambda x: x < 5, [4, 5, 6, 7, 8, 9])
print(list(a))

b = map(lambda x: x > 5, [4, 5, 6, 7, 8, 9])
print(list(b))

c = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
print(c)
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、三次握手
  1. 客户端通过向服务器发送一个SYN来创建一个主动打开,作为三次握手的一部分。客户端把这段链接的序号设定为随机数A
  2. 服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK的确认码应为A+1,SYN/ACK包本身又有一个随机序号B。
  3. 最后客户端再发送一个ACK。当服务端接收到这个ACK的时候,就完成了三次握手,并进入链接创建状态。此时包序号被设定为收到的确认号A+1,二响应则为B+1。
2、四次挥手
  1. 客户端发送一个数据分段, 其中的 FIN 标记设置为1. 客户端进入 FIN-WAIT 状态. 该状态下客户端只接收数据, 不再发送数据.
  2. 服务器接收到带有 FIN = 1 的数据分段, 发送带有 ACK = 1 的剩余数据分段, 确认收到客户端发来的 FIN 信息.
  3. 服务器等到所有数据传输结束, 向客户端发送一个带有 FIN = 1 的数据分段, 并进入 CLOSE-WAIT 状态, 等待客户端发来带有 ACK = 1 的确认报文.
  4. 客户端收到服务器发来带有 FIN = 1 的报文, 返回 ACK = 1 的报文确认, 为了防止服务器端未收到需要重发, 进入 TIME-WAIT 状态. 服务器接收到报文后关闭连接. 客户端等待 2ms 后未收到回复, 则认为服务器成功关闭, 客户端关闭连接.
3、ARP协议

​ 地址解析协议(Address Resolution Protocol),其基本功能为透过目标设备的IP地址,查询目标的MAC地址,以保证通信的顺利进行。它是IPv4网络层必不可少的协议,不过在IPv6中已不再适用,并被邻居发现协议(NDP)所替代。

4、urllib和urllib2的区别
  1. urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。
  2. urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。这意味着,你不可以伪装你的User Agent字符串等。
5、Post和Get的区别
  1. Post比Get安全一点点,因为post请求之后的信息不会被浏览器记录
  2. 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架构

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

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

  1. 请求头Host字段,一个服务器多个网站
  2. 长链接
  3. 文件断点续传
  4. 身份认证,状态管理,Cache缓存
21、Ajax

AJAX,Asynchronous JavaScript and XML(异步的 JavaScript 和 XML), 是与在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。