威尼斯人线上娱乐

教员呕心沥血帮小编收拾出最全Python面试题,拿着那份Python宝典去面试

28 3月 , 2019  

 

python的函数参数字传送递

看五个例证:

a = 1
def fun(a):
    a = 2
fun(a)
print a  # 1

a = []
def fun(a):
    a.append(1)
fun(a)
print a  # [1]

抱有变量都足以理解为内部存款和储蓄器中3个对象的“引用”,只怕,能够看做C中的viod*的感觉

此间记住的是项目是属于对象的,而不是变量。而目的有二种,“可更改”(mutable)与“不可改变”(immutable)对象。在python中,strings,
tuples,
和numbers是不行更改的靶子,而list,dict等则是足以修改的对象。(那就是那几个题材的重中之重)

当四个引用传递给函数的时候,函数自动复制一份引用,这么些函数里的引用和内地的引用没有半毛关系了.所以第一个例子里函数把引用指向了贰个不可变对象,当函数再次回到的时候,外面包车型地铁引用没半毛感觉.而第一个例子就不平等了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内部存款和储蓄器里展开修改.

若果还不知道的话,那里有更好的表明:
http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference

近年来根本介绍的是本身个人收集的python面试的有个别科学普及的须求和应控制的学识,上面只是内部一些,越多的请看我们

Python语言特色

威尼斯人线上娱乐 1

python中的元类(metaclass)

以此特别的不常用,然而像OOdysseyM那种复杂的布局依旧会必要的,详情请看:《长远驾驭Python中的元类(metaclass)》

[PSC开源组GitHub]() 地址 ,里面有详实的python面试应通晓的有着地点的学问(最终是python后台和python服务器相关的)以及个体书籍推荐,能够留邮箱发送

Python语言特色

1
Python的函数参数字传送递

2
Python中的元类(metaclass)

3
@staticmethod和@classmethod

4
类变量和实例变量

5
Python自省

6
字典推导式

7
Python中单下划线和双下划线

8
字符串格式化:%和.format

9
迭代器和生成器

10*argsand**kwargs

11
面向切面编制程序AOP和装饰器

12
鸭子类型

13
Python中重载

14
新式类和旧式类

15__new__和__init__的区别

16
单例情势

1
使用__new__方法

2
共享属性

3
装饰器版本

4
import方法

17
Python中的功效域

18
GIL线程全局锁

19
协程

20
闭包

21
lambda函数

22
Python函数式编制程序

23
Python里的正片

24
Python垃圾回收机制

1
引用计数

2
标记-清除机制

3
分代技术

25
Python的List

26
Python的is

27
read,readline和readlines

28
Python2和3的区别

29
super.init()

30
range-and-xrange

操作系统

1
select,poll和epoll

2
调度算法

3
死锁

4
程序编写翻译与链接

1
预处理

2
编译

3
汇编

4
链接

5
静态链接和动态链接

6
虚拟内部存款和储蓄器技术

7分页和分层

分页与分支的主要差异

8
页面置换算法

9
边缘触发和水准触发

数据库

1
事务

2
数据库索引

3
Redis原理

4
乐观锁和悲观锁

5
MVCC

6
MyISAM和InnoDB

网络

1
三回握手

叁13回挥手

3
ARP协议

4
urllib和urllib2的区别

5
Post和Get

6
Cookie和Session

7
apache和nginx的区别

8
网站用户密码保存

9
HTTP和HTTPS

10
XSRF和XSS

11 幂等
Idempotence

12
RESTful架构(SOAP,RPC)

13
SOAP

14
RPC

15
CGI和WSGI

16
中间人抨击

17
c10k问题

18
socket

19
浏览器缓存

20
HTTP1.0和HTTP1.1

21
Ajax

*NIX

unix进程间通讯格局(IPC)

数据结构

1
红黑树

编程题

1
台阶难题/斐波纳挈

2
变态台阶难题

3
矩形覆盖

4
杨氏矩阵查找

5
去除列表中的重复成分

6
链表成对沟通

7
创设字典的措施

1
直接创建

2
工厂方法

3
fromkeys()方法

8
合并多少个静止列表

9
交叉链表求交点

10
二分查找

11
快排

12
找零难题

13
广度遍历和深度遍历二叉树

14
二叉树节点

15
层次遍历

16
深度遍历

17
前中后序遍历

18
求最大树深

19
求两棵树是或不是同样

20
前序中序求后序

21
单链表逆置

Python语言特征

1
Python的函数参数字传送递

看两个例证:

a=1deffun(a):    a=2fun(a)printa#1

a=[]deffun(a):    a.append(1)fun(a)printa#[1]

富有的变量都能够明白是内部存款和储蓄器中一个目的的“引用”,只怕,也得以看似c中void*的感觉。

通过id来看引用a的内存地址能够比较清楚:

a=1deffun(a):print”func_in”,id(a)#func_in
41322472a=2print”re-point”,id(a),id(2)#re-point 41322448
41322448print”func_out”,id(a),id(1)#func_out 41322472
41322472fun(a)printa#1

注:具体的值在不相同电脑上运维时恐怕区别。

能够见见,在进行完a =
2之后,a引用中保留的值,即内部存款和储蓄器地址发生变化,由原本1对象的内地的地点变成了2那么些实体对象的内部存款和储蓄器地址。

而第二个例证a引用保存的内部存款和储蓄器值就不会产生变化:

a=[]deffun(a):print”func_in”,id(a)#func_in
53629256a.append(1)print”func_out”,id(a)#func_out
53629256fun(a)printa#[1]

此地记住的是项目是属于对象的,而不是变量。而目的有二种,“可更改”(mutable)与“不可变更”(immutable)对象。在python中,strings,
tuples,
和numbers是不足更改的对象,而list,dict等则是足以修改的指标。(这就是其一标题标第②)

当二个引用传递给函数的时候,函数自动复制一份引用,那几个函数里的引用和各省的引用没有半毛关系了.所以第二个例证里函数把引用指向了2个不可变对象,当函数重回的时候,外面包车型客车引用没半毛感觉.而第二个例证就分歧了,函数内的引用指向的是可变对象,对它的操作就和永恒了指针地址一样,在内部存款和储蓄器里实行修改.

倘使还不知晓的话,那里有更好的解释:http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference

2
Python中的元类(metaclass)

本条相当的不常用,但是像OENCOREM那种复杂的结构照旧会需求的,详情请看:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

3
@staticmethod和@classmethod

Python其实有3个主意,即静态方法(staticmethod),类措施(classmethod)和实例方法,如下:

deffoo(x):print”executing
foo(%s)”%(x)classA(object):deffoo(self,x):print”executing
foo(%s,%s)”%(self,x)@classmethoddefclass_foo(cls,x):print”executing
class_foo(%s,%s)”%(cls,x)@staticmethoddefstatic_foo(x):print”executing
static_foo(%s)”%xa=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)

更加多关于那些标题:http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python

4
类变量和实例变量

classPerson:   
name=”aaa”p1=Person()p2=Person()p1.name=”bbb”printp1.name#bbbprintp2.name#aaaprintPerson.name#aaa

类变量就是供类使用的变量,实例变量正是供实例使用的.

那里p1.name=”bbb”是实例调用了类变量,那实质上和方面第贰个难点同样,便是函数字传送参的标题,p1.name一始发是指向的类变量name=”aaa”,不过在实例的效果域里把类变量的引用改变了,就变成了多少个实例变量,self.name不再引用Person的类变量name了.

能够看看下边包车型大巴例证:

classPerson:   
name=[]p1=Person()p2=Person()p1.name.append(1)printp1.name#[1]printp2.name#[1]printPerson.name#[1]

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

5
Python自省

本条也是python彪悍的性子.

反躬自省正是面向对象的言语所写的次第在运作时,所能知道对象的类型.简单一句正是运转时亦可拿走对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().

6
字典推导式

或是您见过列表推导时,却从没见过字典推导式,在2.7中才插足的:

d={key: valuefor(key, value)initerable}

7
Python中单下划线和双下划线

>>>classMyClass():…def__init__(self):…self.__superprivate=”Hello”…self._semiprivate=”,
world!”…>>>mc=MyClass()>>>printmc.__superprivateTraceback
(most recent call last):  File””, line1,inAttributeError: myClass
instance has no
attribute’__superprivate’>>>printmc._semiprivate,
world!>>>printmc.__dict__{‘_MyClass__superprivate’:’Hello’,’_semiprivate’:’,
world!’}

__foo__:一种约定,Python内部的名字,用来分歧别的用户自定义的命名,防止争辨.

_foo:一种约定,用来内定变量私有.程序员用来指定个人变量的一种形式.

__foo:那几个有真正的含义:解析器用_classname__foo来取代这几个名字,以分别和任何类相同的命名.

详情见:http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python

或者:http://www.zhihu.com/question/19754941

8
字符串格式化:%和.format

.format在比比皆是地点看起来更便利.对于%最烦人的是它不能同时传递2个变量和元组.你只怕会想下边包车型客车代码不会有哪些难点:

“hi there %s” % name

而是,假使name恰好是(1,2,3),它将会抛出多少个TypeError十分.为了保险它连接不错的,你不可能不这么做:

“hi there %s” % (name,)  # 提供2个单成分的数组而不是1个参数

然而有些丑..format就平素不这么些难点.你给的首个问题也是如此,.format美观多了.

你为啥不用它?

不知道它(在读那几个前面)

为了和Python2.5协作(譬如logging库提议使用%(issue
#4))

http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format

9
迭代器和生成器

其一是stackoverflow里python排行第3的题材,值得一看:http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python

那是中文版:http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html

10*argsand**kwargs

用*args和**kwargs只是为着便于并不曾强制行使它们.

当您不分明你的函数里即将传递多少参数时你可以用*args.例如,它可以传递任意数量的参数:

>>>defprint_everything(*args):forcount,
thinginenumerate(args):…print'{0}.{1}’.format(count,
thing)…>>>print_everything(‘apple’,’banana’,’cabbage’)0.
apple1. banana2. cabbage

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

>>>deftable_things(**kwargs):…forname,
valueinkwargs.items():…print'{0}={1}’.format(name,
value)…>>>table_things(apple=’fruit’,cabbage=’vegetable’)cabbage=vegetableapple=fruit

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

def table_things(titlestring, **kwargs)

*args和**kwargs能够而且在函数的概念中,不过*args必须在**kwargs前面.

当调用函数时您也得以用*和**语法.例如:

>>>defprint_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和装饰器

以此AOP一听起来有些懵,同学面Ali的时候就被问懵了…

装饰器是一个很闻名的设计形式,日常被用来有切面需要的情景,较为经典的有插入日志、品质测试、事务处理等。装饰器是缓解那类难点的绝佳设计,有了装饰器,大家就能够抽离出大方函数中与函数作用本人无关的一致代码并持续起用。归纳的讲,装饰器的成效就是为已经存在的指标添加额外的效率。

这几个题材相比较大,推荐:http://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python

中文:http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html

12
鸭子类型

“当看到一头鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么那只鸟就足以被号称鸭子。”

我们并不关切对象是哪些品种,到底是还是不是鸭子,只关怀行为。

诸如在python中,有好多file-like的事物,比如StringIO,GzipFile,socket。它们有无数一样的不二法门,大家把它们作为文件使用。

又比如list.extend()方法中,大家并不关心它的参数是或不是list,只要它是可迭代的,所以它的参数能够是list/tuple/dict/字符串/生成器等.

鸭子类型在动态语言中不时使用,非凡灵活,使得python不想java那样专门去弄一大堆的设计格局。

13
Python中重载

引自博客园:http://www.zhihu.com/question/20053359

函数重载主若是为了化解四个难点。

可变参数类型。

可变参数个数。

除此以外,四个主干的设计条件是,仅仅当五个函数除了参数类型和参数个数差别以外,其意义是完全相同的,此时才使用函数重载,假诺五个函数的效能实在不及,那么不应当利用重载,而应该选用一个名字不一致的函数。

好啊,那么对于意况 1 ,函数功能雷同,可是参数类型差异,python
怎么样处理?答案是一贯不需求处理,因为 python
能够承受其余类型的参数,就算函数的效益雷同,那么区别的参数类型在 python
中很恐怕是如出一辙的代码,没有供给做成三个例外函数。

那么对于情形 2 ,函数效率雷同,但参数个数不相同,python
怎么着处理?大家领悟,答案就是缺省参数。对那多少个不够的参数设定为缺省参数即可解决难点。因为你若是函数成效雷同,那么那多少个不够的参数终究是须求用的。

好了,鉴于景况 1 跟 景况 2 都有了缓解方案,python
自然就不须求函数重载了。

14
新式类和旧式类

本条面试官问了,小编说了老半天,不驾驭她问的确实意图是什么.

stackoverflow

那篇作品很好的牵线了新式类的风味:http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html

新颖类很早在2.2就涌出了,所以旧式类完全是同盟的标题,Python3里的类全体都以新式类.那里有3个MRO难题能够了然下(新式类是广度优先,旧式类是深浅优先),里讲的也很多.

15__new__和__init__的区别

这个__new__确实很少见到,先做摸底吧.

__new__是八个静态方法,而__init__是一个实例方法.

__new__方法会再次来到一个创办的实例,而__init__怎么样都不重返.

只有在__new__归来二个cls的实例时前边的__init__才能被调用.

当创立三个新实例时调用__new__,起始化多个实例时用__init__.

stackoverflow

ps:__metaclass__是创办类时起成效.所以大家能够独家选拔__metaclass__,__new__和__init__来分别在类成立,实例创制和实例伊始化的时候做一些小手脚.

16
单例格局

本条相对常考啊.绝对要切记1~一个法子,当时面试官是让手写的.

1
使用__new__方法

classSingleton(object):def__new__(cls,*args,**kw):ifnothasattr(cls,’_instance’): 
         
orig=super(Singleton,cls)cls._instance=orig.__new__(cls,*args,**kw)returncls._instanceclassMyClass(Singleton): 
  a=1

2
共享属性

创造实例时把具备实例的__dict__本着同1个字典,这样它们拥有同等的性质和方法.

classBorg(object):    _state={}def__new__(cls,*args,**kw):     
  ob=super(Borg,cls).__new__(cls,*args,**kw)       
ob.__dict__=cls._statereturnobclassMyClass2(Borg):    a=1

3
装饰器版本

defsingleton(cls,*args,**kw):   
instances={}defgetinstance():ifclsnotininstances:           
instances[cls]=cls(*args,**kw)returninstances[cls]returngetinstance@singletonclassMyClass:…

4
import方法

作为python的模块是天赋的单例情势

#mysingleton.pyclassMy_Singleton(object):deffoo(self):passmy_singleton=My_Singleton()#to
usefrommysingletonimportmy_singletonmy_singleton.foo()

17
Python中的成效域

Python 中,二个变量的成效域总是由在代码中被赋值的地点所决定的。

当 Python 遭受3个变量的话他会根据那样的次第举行查找:

本土成效域(Local)→当前效用域被置于的本土功效域(Enclosing
locals)→全局/模块功效域(Global)→内置功能域(Built-in)

18
GIL线程全局锁

线程全局锁(Global Interpreter
Lock),即Python为了确定保证线程安全而使用的独立线程运转的界定,说白了就是三个核只可以在同一时半刻间运行三个线程.

见Python
最难的题材

解决办法正是多进程和上边包车型地铁协程(协程也只是单CPU,不过能减小切换代价提高质量).

19
协程

新浪被问到了,呵呵哒,跪了

简单的讲点说协程是进度和线程的晋级版,进度和线程都面临着内核态和用户态的切换难题而消耗习以为常切换时间,而协程正是用户本身决定切换的机会,不再须求陷入系统的水源态.

Python里最广大的yield就是协程的思维!能够查看第九个难点.

20
闭包

闭包(closure)是函数式编制程序的根本的语法结构。闭包也是一种集体代码的结构,它同样提升了代码的可重新使用性。

当二个内嵌函数引用其外表作作用域的变量,大家就会获取二个闭包.
总括一下,创造3个闭包必须满意以下几点:

必须有一个内嵌函数

内嵌函数必须引用外部函数中的变量

表面函数的再次回到值必须是内嵌函数

感觉到闭包还是有难度的,几句话是说不了然的,照旧印证相关资料.

主要是函数运营后并不会被收回,就如16题的instance字典一样,当函数运营完后,instance并不被灭绝,而是继续留在内部存款和储蓄器空间里.这么些效应看似类里的类变量,只然而迁移到了函数上.

闭包就如个空心球一样,你明白外面和个中,但你不知晓中间是什么样样.

21
lambda函数

事实上正是一个匿名函数,为何叫lambda?因为和后边的函数式编制程序有关.

推荐:知乎

22
Python函数式编制程序

其一需求相当的问询一下呢,终究函数式编制程序在Python中也做了引用.

推荐:酷壳

python中等校园函授数式编制程序辅助:

filter
函数的成效也就是过滤器。调用三个布尔函数bool_func来迭代遍历各样seq中的成分;重回二个使bool_seq重回值为true的因素的行列。

>>>a=[1,2,3,4,5,6,7]>>>b=filter(lambdax: x>5,
a)>>>printb>>>[6,7]

map函数是对八个连串的每一个项依次执行函数,上边是对1个队列种种项都乘以2:

>>>a=map(lambdax:x*2,[1,2,3])>>>list(a)[2,4,6]

reduce函数是对一个队列的每一种项迭代调用函数,上面是求3的阶乘:

>>>reduce(lambdax,y:x*y,range(1,4))6

23
Python里的正片

引用和copy(),deepcopy()的区别

importcopya=[1,2,3,4,
[‘a’,’b’]]#土生土长对象b=a#赋值,传对象的引用c=copy.copy(a)#对象拷贝,浅拷贝d=copy.deepcopy(a)#对象拷贝,深拷贝a.append(5)#修改对象aa[4].append(‘c’)#修改对象a中的[‘a’,
‘b’]数组对象print’a =’, aprint’b =’, bprint’c =’, cprint’d =’,
d输出结果:a=[1,2,3,4, [‘a’,’b’,’c’],5]b=[1,2,3,4,
[‘a’,’b’,’c’],5]c=[1,2,3,4, [‘a’,’b’,’c’]]d=[1,2,3,4,
[‘a’,’b’]]

24
Python垃圾回收机制

Python GC重要使用引用计数(reference
counting)来跟踪和回收废。在引用计数的基本功上,通过“标记-清除”(mark
and
sweep)消除容器对象大概产生的轮回引用难点,通过“分代回收”(generation
collection)以空间换时间的办法升高垃圾回收效能。

1
引用计数

PyObject是各样对象必有的内容,在那之中ob_refcnt就是做为引用计数。当2个目的有新的引用时,它的ob_refcnt就会追加,当引用它的目的被去除,它的ob_refcnt就会收缩.引用计数为0时,该目的生命就甘休了。

优点:

简单

实时性

缺点:

护卫引用计数消功耗源

巡回引用

2
标记-清除机制

基本思路是先按需分配,等到没有空余内存的时候从寄存器和次序栈上的引用出发,遍历以目的为节点、以引用为边构成的图,把拥有可以访问到的靶子打上标记,然后清扫三遍内部存款和储蓄器空间,把具有没标记的对象释放。

3
分代技术

分代回收的完好思想是:将系统中的全体内部存款和储蓄器块依照其存世时间分开为不一致的集结,各类集合就变成多少个“代”,垃圾收集频率随着“代”的幸存时间的增大而减小,存活时间常常使用经过一遍垃圾回收来衡量。

Python私下认可定义了三代对象集合,索引数越大,对象共处时间越长。

举例来说:当一些内部存款和储蓄器块M经过了二回垃圾收集的洗涤之后还存世时,大家就将内部存款和储蓄器块M划到3个集合A中去,而新分配的内部存款和储蓄器都划分到集合B中去。当垃圾收集起来工作时,大部分境况都只对集合B实行垃圾回收,而对集合A进行垃圾回收要隔相当短一段时间后才进行,那就使得垃圾收集体制亟待处理的内部存款和储蓄器少了,效用自然就增强了。在那几个进程中,集合B中的有些内部存款和储蓄器块由于现有时间长而会被转换成集合A中,当然,集合A中实际上也存在一些杂质,那几个污源的回收会因为那种分代的体制而被推迟。

25
Python的List

推荐:http://www.jianshu.com/p/J4U6rR

26
Python的is

is是比较地址,==是相比值

27
read,readline和readlines

read 读取整个文件

readline 读取下一行,使用生成器方法

readlines 读取整个文件到二个迭代器以供大家遍历

28
Python2和3的区别

推荐:Python 2.7.x 与 Python 3.x
的主要出入

29 super
init

super() lets you avoid referring to the base class explicitly, which can
be nice. But the main advantage comes with multiple inheritance, where
all sorts of fun stuff can happen. See the standard docs on super if you
haven’t already.

Note that the syntax changed in Python 3.0: you can just say
super().init() instead of super(ChildB, self).init() which IMO
is quite a bit nicer.

http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods

30 range and
xrange

都在循环时选拔,xrange内部存款和储蓄器品质更好。for i in range(0, 20):for i in
xrange(0, 20):What is the difference between range and xrange functions
in Python 2.X? range creates a list, so if you do range(1, 一千0000) it
creates a list in memory with 9999999 elements. xrange is a sequence
object that evaluates lazily.

http://stackoverflow.com/questions/94935/what-is-the-difference-between-range-and-xrange-functions-in-python-2-x

操作系统

1
select,poll和epoll

实际上具有的I/O都以轮询的主意,只但是达成的范围差异罢了.

其一题材只怕有点浓密了,但相信能回答出那一个标题是对I/O多路复用有很好的打听了.个中tornado使用的就是epoll的.

selec,poll和epoll差距总括

基本上select有3个缺点:

连接数受限

招来配对进程慢

多少由基础拷贝到用户态

poll改善了第2个毛病

epoll改了几个缺点.

关于epoll的:http://www.cnblogs.com/my\_life/articles/3968782.html

2
调度算法

先来先服务(FCFS, First Come First Serve)

短作业优先(SJF, Shortest Job First)

最高优先权调度(Priority Scheduling)

日子片轮转(途观卡宴, Round 罗布in)

比比皆是反馈队列调度(multilevel feedback queue scheduling)

实时调度算法:

最早甘休时间先行 EDF

低于松弛度优先 LLF

3
死锁

原因:

竞争能源

程序推进各种不当

要求条件:

互斥条件

伸手和维系标准

不剥夺条件

环路等待条件

拍卖死锁基本方法:

谨防死锁(吐弃除1以外的口径)

制止死锁(银行家算法)

检查和测试死锁(能源分配图)

免去死锁

剥夺能源

注销进度

4
程序编写翻译与链接

推荐:http://www.ruanyifeng.com/blog/2014/11/compiler.html

Bulid进程能够分解为陆个步骤:预处理(Prepressing),
编写翻译(Compilation)、汇编(Assembly)、链接(Linking)

以c语言为例:

1
预处理

预编写翻译进程首要处理这多少个源文件中的以“#”起头的预编写翻译指令,首要处理规则有:

将拥有的“#define”删除,并进行所用的宏定义

拍卖全数规则预编写翻译指令,比如“#if”、“#ifdef”、 “#elif”、“#endif”

处理“#include”预编写翻译指令,将被含有的文本插入到该编写翻译指令的岗位,注:此进度是递归进行的

删去全数注释

添加行号和文件名标识,以便于编写翻译时编写翻译器产生调节和测试用的行号消息以及用于编写翻译时发生编写翻译错误或警示时可呈现行反革命号

保存全部的#pragma编写翻译器指令。

2
编译

编写翻译进度就是把预处理完的文书实行一名目繁多的词法分析、语法分析、语义分析及优化后变卦对应的汇编代码文件。那个历程是一切程序营造的为主部分。

3
汇编

汇编器是将汇编代码转化成机器能够推行的命令,每一条汇编语句差不多都以一条机器指令。经过编写翻译、链接、汇编输出的文件成为目的文件(Object
File)

4
链接

链接的要害内容就是把各类模块之间互相引用的一对处理好,使各样模块能够正确的拼接。链接的重点进度包块
地址和空中的分红(Address and Storage Allocation)、符号决议(Symbol
Resolution)和重定位(Relocation)等手续。

5
静态链接和动态链接

静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地方分明下来静态库的链接能够应用静态链接,动态链接库也得以利用那种方法链接导入库

动态链接方法:使用那种办法的先后并不在一起来就完了动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那某个)动态代码的逻辑地址,然后等到某些时候,程序又需求调用此外某块动态代码时,载入程序又去总结那有的代码的逻辑地址,所以,这种艺术使程序开头化时间较短,但运维时期的质量不如静态链接的次序

6
虚拟内部存款和储蓄器技术

虚拟存款和储蓄器是指具有请求调入作用和交流成效,能从逻辑上对内部存款和储蓄器容量加以增加的一种存款和储蓄系统.

玖分页和支行

分页:
用户程序的地点空间被细分成多少稳住大小的区域,称为“页”,相应地,内部存款和储蓄器空间分成若干个物理块,页和块的分寸相等。可将用户程序的任一页放在内部存款和储蓄器的任一块中,达成了离散分配。

分段:
将用户程序地址空间分成若干个大小不等的段,每段能够定义一组绝对完好的逻辑消息。存款和储蓄分配时,以段为单位,段与段在内部存储器中能够不相邻接,也落实了离散分配。

分页与分支的关键差距

页是音信的情理单位,分页是为了贯彻非接二连三分配,以便化解内部存款和储蓄器碎片难点,或然说分页是出于系统一管理理的内需.段是音信的逻辑单位,它包罗一组意义相对完整的音讯,分段的目标是为了更好地贯彻共享,满足用户的要求.

页的深浅固定,由系统明显,将逻辑地址划分为页号和页外省址是由机器硬件达成的.而段的长度却不固定,决定于用户所编纂的先后,经常由编写翻译程序在对源程序开始展览编译时根据音信的习性来划分.

分页的功课地址空间是一维的.分段的地方空间是二维的.

8
页面置换算法

最佳置换算法OPT:非常的小概实现

先进先出FIFO

近日最久未选取算法LRU:方今一段时间里最久没有运用过的页面予以置换.

clock算法

9
边沿触发和水准触发

边缘触发是指每当状态变化时发出1个 io
事件,条件触发是一旦满意条件就发生2个 io 事件

数据库

1
事务

数据库事务(Database Transaction)
,是指作为单个逻辑工作单元执行的一多重操作,要么完全地实践,要么完全地不进行。

2
数据库索引

推荐:http://tech.meituan.com/mysql-index.html

MySQL索引背后的数据结构及算法原理

聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理

3
Redis原理

4
乐观锁和悲观锁

想不开锁:假定会发出并发争执,屏蔽一切恐怕违反数据完整性的操作

开朗锁:要是不会发出并发争辩,只在提交操作时检查是还是不是违反数据完整性。

5
MVCC

6
MyISAM和InnoDB

MyISAM
适合于部分亟待大批量查询的行使,但其对于有恢宏写操作并不是很好。甚至你只是要求update四个字段,整个表都会被锁起来,而其余进度,就到底读进程都爱莫能助操作直到读操作完结。其余,MyISAM
对于 SELECT COUNT(*) 那类的计量是超快无比的。

InnoDB 的主旋律会是二个11分复杂的贮存引擎,对于有个别小的选用,它会比 MyISAM
还慢。他是它援助“行锁”
,于是在写操作相比多的时候,会更不错。并且,他还协理更加多的高等级应用,比如:事务。

网络

11回握手

客户端通过向劳动器端发送一个SYN来创立1个积极性打开,作为三路握手的一有的。客户端把那段连接的序号设定为随机数
A。

劳务器端应当为2个合法的SYN回送3个SYN/ACK。ACK 的确认码应为
A+1,SYN/ACK 包自己又有3个随意序号 B。

最后,客户端再发送三个ACK。当服务端受到这一个ACK的时候,就完事了三路握手,并跻身了连年创制状态。此时包序号被设定为接收的确认号
A+1,而响应则为 B+1。

2
4遍挥手

3
ARP协议

地方解析协议(Address Resolution Protocol):
依据IP地址获取物理地址的贰个TCP/IP协议

4
urllib和urllib2的区别

其一面试官确实问过,当时答的urllib2能够Post而urllib不能.

urllib提供urlencode方法用来GET查询字符串的爆发,而urllib2没有。那是怎么urllib常和urllib2一起行使的原委。

urllib2能够承受一个Request类的实例来安装ULX570L请求的headers,urllib仅能够承受U汉兰达L。那意味,你不得以装作你的User
Agent字符串等。

5
Post和Get

GET和POST有何样界别?及为啥网上的大部答案都以错的网易回答

get:RFC 2616 – Hypertext Transfer Protocol —
HTTP/1.1post:RFC
2616 – Hypertext Transfer Protocol —
HTTP/1.1

6
Cookie和Session

CookieSession

存款和储蓄地方客户端服务器端

目标跟踪会话,也足以保存用户偏好设置可能封存用户名密码等跟踪会话

安全性不安全无恙

session技术是要接纳到cookie的,之所以现身session技术,首倘使为着安全。

7
apache和nginx的区别

nginx 相对 apache 的优点:

轻量级,同样起web 服务,比apache 占用更少的内部存储器及财富

抗并发,nginx 处理请求是异步非阻塞的,帮衬越多的面世连接,而apache
则是阻塞型的,在高并发下nginx 能保持低财富低消耗高品质

安顿简洁

惊人模块化的安排性,编写模块相对简单

社区活泼

apache 相对nginx 的优点:

rewrite ,比nginx 的rewrite 强大

模块超多,基本想到的都足以找到

少bug ,nginx 的bug 相对较多

超稳定

8
网站用户密码保存

公然保存

明文hash后保存,如md5

MD5+Salt情势,这么些salt能够专擅

新浪使用了Bcrypy(好像)加密

9
HTTP和HTTPS

事态码定义

1xx 报告吸收接纳到请求,继续进度

2xx 成功步骤成功接收,被驾驭,并被接受

3xx 重定向为了做到请求,必须运用尤其措施

4xx 客户端出错请求包蕴错的各种或无法一挥而就

5xx 服务器出错服务器不可能形成明显有效的伸手

403: Forbidden404: Not Found

HTTPS握手,对称加密,非对称加密,TLS/SSL,大切诺基SA

10
XSRF和XSS

CSLacrosseF(克罗丝-site request forgery)跨站请求伪造

XSS(克罗丝 Site Scripting)跨站脚本攻击

CSPAJEROF重点在伸手,XSS重点在本子

11 幂等
Idempotence

HTTP方法的幂等性是指一回和反复请求某一个财富应该有着同样的副作用。(注意是副功用)

GET

DELETE方法用于删除能源,有副功效,但它应该满足幂等性。比如:DELETE

POST所对应的U奥迪Q5I并非创立的能源本人,而是财富的收信人。比如:POST

PUT所对应的U哈弗I是要开创或更新的财富本人。比如:PUT

12
RESTful架构(SOAP,RPC)

推荐:http://www.ruanyifeng.com/blog/2011/09/restful.html

13
SOAP

SOAP(原为Simple Object Access
Protocol的首字母缩写,即简单对象访问协议)是换来数据的一种协议正式,使用在处理器互联网Web服务(web
service)中,调换带结构音讯。SOAP为了简化网页服务器(Web
Server)从XML数据库中领到数据时,节省去格式化页面时间,以及不一样应用程序之间依照HTTP通讯协议,服从XML格式执行资料交换,使其抽象于言语落成、平台和硬件。

14
RPC

福睿斯PC(Remote Procedure Call
Protocol)——远程进度调用协议,它是一种通过网络从远程总括机程序上呼吁服务,而不必要领会底层互连网技术的商业事务。福特ExplorerPC商谈假使某个传输协议的存在,如TCP或UDP,为通讯程序之间带领信息数量。在OSI网络通讯模型中,PRADOPC跨越了传输层和应用层。兰德酷路泽PC使得开签发承包合约括网络分布式多程序在内的应用程序特别便于。

小结:服务提供的两大流派.守旧意义以艺术调用为导向通称奇骏PC。为了集团SOA,若干厂商联合推出webservice,制定了wsdl接口定义,传输soap.当网络时期,臃肿SOA被简化为http+xml/json.然而简化出现种种混乱。以财富为导向,任何操作无非是对资源的增加和删除改查,于是统一的REST现身了.

进化的逐一: 帕杰罗PC -> 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)是指攻击者与报纸发表的两岸分别创设独立的牵连,并调换其所接收的数额,使通信的双方认为她们正在通过1个私密的连日与对方直接对话,但实则整个会话都被攻击者完全控制。

17
c10k问题

所谓c10k难点,指的是服务器同时支持广大个客户端的难点,也正是concurrent
10 000
connection(那也是c10k那些名字的缘由)。推荐:http://www.kegel.com/c10k.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),
是与在不重复加载整个页面包车型大巴情事下,与服务器沟通数据并创新部分网页的技巧。

*NIX

unix进程间通讯格局(IPC)

管道(Pipe):管道可用于具有亲缘关系进程间的通讯,允许3个进度和另3个与它有一块祖先的历程之间开始展览通讯。

取名管道(named
pipe):命名管道克制了管道没有名字的界定,由此,除具有管道所具备的效率外,它还同意无亲缘关系进度间的通讯。命名管道在文件系统中有照应的公文名。命名管道通过命令mkfifo或体系调用mkfifo来创设。

信号(Signal):信号是相比复杂的通讯形式,用于文告接受进度有某种事件发生,除了用于进度间通讯外,进度仍是能够发送信号给进度自身;linux除了协理Unix早期信号语义函数sigal外,还辅助语义符合Posix.1标准的信号函数sigaction(实际上,该函数是依据BSD的,BSD为了促成可信赖信号机制,又能够合并对外接口,用sigaction函数重新完成了signal函数)。

音讯(Message)队列:音讯队列是音讯的链接表,包罗Posix新闻队列system
V音信队列。有丰裕权限的长河能够向队列中添加音信,被授予读权限的进程则能够读走队列中的音信。新闻队列克制了信号承载新闻量少,管道只好承载无格式字节流以及缓冲区大小受限等缺

共享内部存款和储蓄器:使得多个经过能够访问同一块内部存款和储蓄器空间,是最快的可用IPC情势。是指向任何通讯机制运作效用较低而规划的。往往与其余通讯机制,如信号量结合使用,来实现进度间的联手及互斥。

内部存款和储蓄器映射(mapped
memory):内部存款和储蓄器映射允许其余多少个进程间通信,每1个用到该机制的经过经过把多少个共享的文件映射到自身的历程地址空间来促成它。

信号量(semaphore):首要作为进度间以及同样进程区别线程之间的一块手段。

套接口(Socket):更为相似的历程间通讯机制,可用来不相同机器之间的长河间通讯。初叶是由Unix系统的BSD分支开发出来的,但今后相似能够移植到别的类Unix系统上:Linux和System
V的变种都援救套接字。

数据结构

1
红黑树

红黑树与AVL的可比:

AVL是严酷平衡树,由此在大增仍旧去除节点的时候,遵照差别意况,旋转的次数比红黑树要多;

红黑是用非严加的平衡来换取增加和删除节点时候转动次数的减退;

据此不难说,若是你的行使中,搜索的次数远远大于插入和删除,那么选用AVL,如若搜索,插入删除次数差不离大约,应该选用RB。

编程题

1
台阶难点/斐波纳挈

三头青蛙三遍能够跳上1级台阶,也能够跳上2级。求该青蛙跳上二个n级的阶梯总共有稍许种跳法。

fib=lambdan: nifn<=2elsefib(n-1)+fib(n-2)

第三种回想方法

defmemo(func):    cache={}defwrap(*args):ifargsnotincache:           
cache[args]=func(*args)returncache[args]returnwrap@memodeffib(i):ifi<2:return1returnfib(i-1)+fib(i-2)

其二种方法

deffib(n):    a, b=0,1for_inxrange(n):        a, b=b, a+breturnb

2
变态台阶难题

3头青蛙一遍能够跳上1级台阶,也足以跳上2级……它也足以跳上n级。求该青蛙跳上三个n级的台阶总共有多少种跳法。

fib=lambdan: nifn<2else2*fib(n-1)

3
矩形覆盖

咱俩得以用2*1的小矩形横着照旧竖着去掩盖更大的矩形。请问用n个2*1的小矩形无重叠地掩盖一个2*n的大矩形,总共有稍许种方法?

第2*n个矩形的遮盖措施等于第3*(n-1)加上第2*(n-2)的方法。

f=lambdan:1ifn<2elsef(n-1)+f(n-2)

4
杨氏矩阵查找

在2个m行n列二维数组中,每一行都依据从左到右递增的依次排序,每一列都遵循从上到下递增的次第排序。请达成三个函数,输入那样的三个二维数组和一个整数,判断数组中是还是不是蕴涵该整数。

行使Step-wise线性搜索。

defget_value(l,r,c):returnl[r][c]deffind(l,x):   
m=len(l)-1n=len(l[0])-1r=0c=nwhilec>=0andr<=m:       
value=get_value(l, r, c)ifvalue==x:returnTrueelifvalue>x:           
c=c-1elifvalue

5
去除列表中的重复成分

用集合

list(set(l))

用字典

l1=[‘b’,’c’,’d’,’b’,’c’,’a’,’a’]l2={}.fromkeys(l1).keys()printl2

用字典并维持顺序

l1=[‘b’,’c’,’d’,’b’,’c’,’a’,’a’]l2=list(set(l1))l2.sort(key=l1.index)printl2

列表推导式

l1=[‘b’,’c’,’d’,’b’,’c’,’a’,’a’]l2=[][l2.append(i)foriinl1ifnotiinl2]

面试官提到的,先排序然后删除.

6
链表成对交换

1->2->3->4转换成2->1->4->3.

classListNode:def__init__(self,x):self.val=xself.next=NoneclassSolution:#@param
a ListNode#@return a
ListNodedefswapPairs(self,head):ifhead!=Noneandhead.next!=None:next=head.next 
         
head.next=self.swapPairs(next.next)next.next=headreturnnextreturnhead

7
制造字典的方式

1
直接创设

dict={‘name’:’earth’,’port’:’80’}

2
工厂方法

items=[(‘name’,’earth’),(‘port’,’80’)]dict2=dict(items)dict1=dict(([‘name’,’earth’],[‘port’,’80’]))

3
fromkeys()方法

dict1={}.fromkeys((‘x’,’y’),-1)dict={‘x’:-1,’y’:-1}dict2={}.fromkeys((‘x’,’y’))dict2={‘x’:None,’y’:None}

8
合并多少个静止列表

天涯论坛远程面试要求编制程序

尾递归

def_recursion_merge_sort2(l1,l2,tmp):iflen(l1)==0orlen(l2)==0:       
tmp.extend(l1)        tmp.extend(l2)returntmpelse:ifl1[0]

循环算法

def loop_merge_sort(l1, l2):

tmp = []

while len(l1) > 0 and len(l2) > 0:

if l1[0] < l2[0]:

tmp.append(l1[0])

del l1[0]

else:

tmp.append(l2[0])

del l2[0]

tmp.extend(l1)

tmp.extend(l2)

return tmp

9
交叉链表求交点

去何方的面试,没做出来.

classListNode:def__init__(self,x):self.val=xself.next=Nonedefnode(l1,l2): 
  length1, lenth2=0,0#求多个链表长度whilel1.next:        l1=l1.next   
    length1+=1whilel2.next:        l2=l2.next       
length2+=1#长的链表先走iflength1>lenth2:for_inrange(length1-length2): 
          l1=l1.nextelse:for_inrange(length2-length1):           
l2=l2.nextwhilel1andl2:ifl1.next==l2.next:returnl1.nextelse:           
l1=l1.next            l2=l2.next

10
二分查找

defbinarySearch(l,t):    low, high=0,len(l)-1whilelowt:           
high=midelifl[mid]

11
快排

defqsort(seq):ifseq==[]:return[]else:        pivot=seq[0]       
lesser=qsort([xforxinseq[1:]ifx=pivot])returnlesser+[pivot]+greaterif__name__==’__main__’: 
  seq=[5,6,78,9,0,-1,2,3,-65,12]print(qsort(seq))

12
找零难题

defcoinChange(values,money,coinsUsed):#values   
T[1:n]数组#valuesCounts  钱币对应的类型数#money 
找出来的总钱数#coinsUsed 
对应于当下钱币总数i所使用的硬币数目forcentsinrange(1, money+1):       
minCoins=cents#从第二个开端到money的兼具景况开始forvalueinvalues:ifvalue<=cents: 
              temp=coinsUsed[cents-value]+1iftemp

13
广度遍历和纵深遍历二叉树

给定一个数组,创设二叉树,并且按层次打字与印刷这些二叉树

## 14
二叉树节点classNode(object):def__init__(self,data,left=None,right=None):self.data=dataself.left=leftself.right=righttree=Node(1,
Node(3, Node(7, Node(0)), Node(6)), Node(2, Node(5), Node(4)))## 15
层次遍历deflookup(root):    stack=[root]whilestack:       
current=stack.pop(0)printcurrent.dataifcurrent.left:           
stack.append(current.left)ifcurrent.right:           
stack.append(current.right)## 16
深度遍历defdeep(root):ifnotroot:returnprintroot.data    deep(root.left) 
  deep(root.right)if__name__==’__main__’:    lookup(tree)   
deep(tree)

17
前中后序遍历

纵深遍历改变各类就OK了

18
求最大树深

defmaxDepth(root):ifnotroot:return0returnmax(maxDepth(root.left),
maxDepth(root.right))+1

19
求两棵树是或不是同样

defisSameTree(p,q):ifp==Noneandq==None:returnTrueelifpandq
:returnp.val==q.valandisSameTree(p.left,q.left)andisSameTree(p.right,q.right)else:returnFalse

20
前序中序求后序

推荐:http://blog.csdn.net/hinyunsin/article/details/6315502

defrebuild(pre,center):ifnotpre:returncur=Node(pre[0])   
index=center.index(pre[0])    cur.left=rebuild(pre[1:index+1],
center[:index])    cur.right=rebuild(pre[index+1:],
center[index+1:])returncurdefdeep(root):ifnotroot:returndeep(root.left) 
  deep(root.right)printroot.data

21
单链表逆置

classNode(object):def__init__(self,data=None,next=None):self.data=dataself.next=nextlink=Node(1,
Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8,
Node(9)))))))))defrev(link):    pre=link    cur=link.next   
pre.next=Nonewhilecur:        tmp=cur.next        cur.next=pre       
pre=cur        cur=tmpreturnpreroot=rev(link)whileroot:printroot.data   
root=root.next

1
Python的函数参数传递

 

@staticmethod和@classmethod

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)

愈来愈多关于那么些题材:http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python

看五个例证:

Python语言特色

1、Python的函数参数字传送递

看多个例子:

a = 1

def fun(a):

a = 2

fun(a)

print a # 1

a = []

def fun(a):

a.append(1)

fun(a)

print a # [1]

有着的变量都得以清楚是内部存储器中一个对象的“引用”,或许,也足以看似c中void*的感觉。

因而id来看引用a的内部存储器地址能够比较清楚:

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引用保存的内部存款和储蓄器值就不会爆发变化:

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
等则是能够修改的指标。(那便是以此难题的首要)

当八个引用传递给函数的时候,函数自动复制一份引用,那些函数里的引用和外边的引用没有半毛关系了.所以第②个例子里函数把引用指向了三个不可变对象,当函数重返的时候,外面的引用没半毛感觉.而第一个例子就差别了,函数内的引用指向的是可变对象,对它的操作就和从来了指针地址一样,在内部存款和储蓄器里开始展览修改.

② 、Python中的元类(metaclass)

本条这2个的不常用,但是像O奥迪Q7M那种复杂的结构依然会必要的,教程就不详细介绍了。

三、 @staticmethod和@classmethod

Python其实有3个措施,即静态方法(staticmethod),类措施(classmethod)和实例方法,如下:

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)

肆 、类变量和实例变量

类变量:

​是可在类的全部实例之间共享的值(也就是说,它们不是单身分配给各样实例的)。例如下例中,num_of_instance
正是类变量,用于跟踪存在着有点个Test 的实例。

实例变量:

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

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

补充的例子

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了.

教员呕心沥血帮小编收拾出最全Python面试题,拿着那份Python宝典去面试。能够看看下边包车型客车例证:

class Person:

name=[]

p1=Person()

p2=Person()

p1.name.append(1)

print p1.name # [1]

print p2.name # [1]

print Person.name # [1]

五、Python自省

那几个也是python彪悍的天性.

反省就是面向对象的语言商讨所写的程序在运作时,所能知道对象的类型.不难一句正是运转时能够得到对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().

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

六 、字典推导式

或者你见过列表推导时,却从未见过字典推导式,在2.7中才加入的:

d = {key: value for (key, value) in iterable}

7 Python中单下划线和双下划线

>>> class MyClass():

… def __init__(self):

… self.__superprivate = “Hello”

… self._semiprivate = “, world!”

>>> mc = MyClass()

>>> print mc.__superprivate

Traceback (most recent call last):

File “<stdin>”, line 1, in <module>

AttributeError: myClass instance has no attribute ‘__superprivate’

>>> print mc._semiprivate

, world!

>>> print mc.__dict__

{‘_MyClass__superprivate’: ‘Hello’, ‘_semiprivate’: ‘, world!’}

__foo__:一种约定,Python内部的名字,用来分别其余用户自定义的命名,以免冲突,便是诸如__init__(),__del__(),__call__()这个新鲜措施

_foo:一种约定,用来钦赐变量私有.程序员用来钦命个人变量的一种方式.不可能用from
module import * 导入,其余方面和国有一样访问;

__foo:那一个有真正的含义:解析器用_classname__foo来代表那一个名字,以界别和别的类相同的命名,它非常小概直接像公有成员一致随便访问,通过对象名._类名__xxx那样的法子得以访问.

柒 、字符串格式化:%和.format

.format在很多方面看起来更便利.对于%最烦人的是它不可能同时传递三个变量和元组.你或许会想下边包车型客车代码不会有何样难点:

“hi there %s” % name

然则,假使name恰好是(1,2,3),它将会抛出1个TypeError万分.为了确定保证它总是不错的,你不能够不这么做:

“hi there %s” % (name,) # 提供四个单成分的数组而不是二个参数

唯独多少丑..format就从未那些难点.你给的第3个难题也是那样,.format好看多了.

您为啥不要它?

  • 不知底它(在读那几个后边)
  • 为了和Python2.5一双两好(譬如logging库建议使用%(issue #4))

捌 、迭代器和生成器

stackoverflow里python排名第叁的题目,能够参照一下,有英文版也有汉语版的。

此间有个关于生成器的创始难题面试官有考: 问: 将列表生成式中[]变动()
之后数据结构是或不是变动? 答案:是,从列表变为生成器

>>> L = [x*x for x in range(10)]

>>> L

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> g = (x*x for x in range(10))

>>> g

<generator object <genexpr> at 0x0000028F8B774200>

由此列表生成式,能够直接创建三个列表。可是,受到内部存款和储蓄器限制,列表容积肯定是个其他。而且,创设四个暗含百万成分的列表,不仅是挤占十分的大的内部存款和储蓄器空间,如:大家只要求拜访前边的多少个因素,前面大部分因素所占的空中都以荒废的。因而,没有须要创造完整的列表(节省大量内部存款和储蓄器空间)。在Python中,大家得以选用生成器:边循环,边总括的体制—>generator

九、*args and **kwargs

用*args和**kwargs只是为着便利并从未强制行使它们.

当您不分明你的函数里即将传递多少参数时你能够用*args.例如,它能够传递任意数量的参数:

>>> def print_everything(*args):

for count, thing in enumerate(args):

… print ‘{0}. {1}’.format(count, thing)

>>> print_everything(‘apple’, ‘banana’, ‘cabbage’)

  1. apple

  2. banana

  3. cabbage

相似的,**kwargs允许你采纳没有先行定义的参数名:

>>> 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.命名参数在列表的最前端.例如:

def table_things(titlestring, **kwargs)

*args和**kwargs能够而且在函数的概念中,可是*args必须在**kwargs前面.

当调用函数时您也足以用*和**语法.例如:

>>> 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

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

⑩ 、面向切面编制程序AOP和装饰器

那些AOP一听起来某些懵,同学面Ali的时候就被问懵了…

装饰器是三个很盛名的设计方式,日常被用于有切面要求的处境,较为经典的有插入日志、质量测试、事务处理等。装饰器是赶尽杀绝那类难题的绝佳设计,有了装饰器,咱们就能够抽离出大批量函数中与函数成效本身无关的一律代码并继承起用。归纳的讲,装饰器的成效便是为早已存在的靶子添加额外的作用。

十① 、鸭子类型

“当见到贰只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么那只鸟就能够被喻为鸭子。”

大家并不尊敬对象是怎样品种,到底是或不是鸭子,只关怀行为。

诸如在python中,有广大file-like的事物,比如StringIO,GzipFile,socket。它们有无数一样的主意,大家把它们当做文件使用。

又比如list.extend()方法中,大家并不关切它的参数是或不是list,只要它是可迭代的,所以它的参数能够是list/tuple/dict/字符串/生成器等.

鸭子类型在动态语言中平日应用,卓殊灵活,使得python不想java那样专门去弄第一次全国代表大会堆的设计方式。

十二、Python中重载

函数重载主若是为了缓解四个问题。

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

别的,2个宗旨的宏图条件是,仅仅当八个函数除了参数类型和参数个数不相同以外,其职能是完全相同的,此时才使用函数重载,假如三个函数的意义实在不及,那么不应该利用重载,而相应采纳一个名字分歧的函数。

行吗,那么对于情状 1 ,函数功用雷同,但是参数类型区别,python
怎么样处理?答案是有史以来不供给处理,因为 python
能够承受任何项目标参数,倘若函数的遵从雷同,那么区别的参数类型在 python
中很恐怕是同样的代码,没有供给做成五个例外函数。

那正是说对于景况 2 ,函数作用雷同,但参数个数分歧,python
如何处理?大家掌握,答案便是缺省参数。对那么些缺少的参数设定为缺省参数即可缓解问题。因为您倘使函数功能雷同,那么那一个贫乏的参数终究是必要用的。

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

十三 、新式类和旧式类

以此面试官问了,笔者说了老半天,不明白他问的实在意图是什么.

stackoverflow

最新类很早在2.2就涌出了,所以旧式类完全是格外的难题,Python3里的类全体都是新式类.那里有三个MRO难点可以精晓下(新式类是广度优先,旧式类是深度优先),<Python大旨编制程序>里讲的也很多.

三个旧式类的深度优先的事例

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()被绕过

十四、__new__和__init__的区别

这个__new__真的很少看到,先做询问吧.

  1. __new__是2个静态方法,而__init__是2个实例方法.
  2. __new__方法会重临二个创办的实例,而__init__怎么都不再次回到.
  3. 只有在__new__再次回到三个cls的实例时前面包车型大巴__init__才能被调用.
  4. 当创设一个新实例时调用__new__,初步化一个实例时用__init__.

stackoverflow

ps:
__metaclass__是创办类时起作用.所以大家得以独家选择__metaclass__,__new__和__init__来分别在类创造,实例创造和实例初叶化的时候做一些小手脚.

十五 、单例形式

​单例方式是一种常用的软件设计情势。在它的基本结构中只包罗八个被誉为单例类的分外类。通过单例情势能够保障系统中1个类只有3个实例而且该实例易于外界访问,从而便利对实例个数的操纵并节约系统能源。如若愿意在系统中有些类的靶子只可以存在2个,单例形式是最佳的消除方案。

__new__()在__init__()此前被调用,用于转移实例对象。利用那一个办法和类的属性的性状能够兑现设计情势的单例情势。单例格局是指创设唯一目的,单例情势设计的类只能实例
那个相对常考啊.相对要切记1~3个措施,当时面试官是让手写的.

1 使用__new__方法

class Singleton(object):

def __new__(cls, *args, **kw):

if not hasattr(cls, ‘_instance’):

orig = super(Singleton, cls)

cls._instance = orig.__new__(cls, *args, **kw)

return cls._instance

class MyClass(Singleton):

a = 1

2 共享属性

开创实例时把全数实例的__dict__针对同二个字典,这样它们有着同样的性质和方法.

class Borg(object):

_state = {}

def __new__(cls, *args, **kw):

ob = super(Borg, cls).__new__(cls, *args, **kw)

ob.__dict__ = cls._state

return ob

class MyClass2(Borg):

a = 1

3 装饰器版本

def singleton(cls):

instances = {}

def getinstance(*args, **kw):

if cls not in instances:

instances[cls] = cls(*args, **kw)

return instances[cls]

return getinstance

@singleton

class MyClass:

4 import方法

用作python的模块是先性格的单例情势

# mysingleton.py

class My_Singleton(object):

def foo(self):

pass

my_singleton = My_Singleton()

# to use

from mysingleton import my_singleton

my_singleton.foo()

十陆 、 Python中的效能域

Python 中,2个变量的成效域总是由在代码中被赋值的地点所控制的。

当 Python 蒙受一个变量的话他会依照那样的逐一进行搜索:

本土作用域(Local)→当前效率域被安置的本地功用域(Enclosing
locals)→全局/模块成效域(Global)→内置功用域(Built-in)

十7、 GIL线程全局锁

线程全局锁(Global Interpreter
Lock),即Python为了确定保证线程安全而利用的独立线程运转的限量,说白了就是八个核只可以在同如今间运营二个线程.对于io密集型职务,python的二十二十四线程起到效益,但对此cpu密集型职务,python的八线程大约占不到其余优势,还有恐怕因为争夺能源而变慢。

见Python 最难的题目

消除办法正是多进度和底下的协程(协程也只是单CPU,但是能减小切换代价提高品质).

十八、协程

天涯论坛被问到了,呵呵哒,跪了

简单的讲点说协程是过程和线程的升级换代版,进度和线程都面临着内核态和用户态的切换难题而消耗比比皆是切换时间,而协程便是用户自个儿决定切换的机遇,不再必要陷入系统的水源态.

Python里最广大的yield正是协程的想想!能够查看第⑨个难题.

十九、闭包

闭包(closure)是函数式编制程序的根本的语法结构。闭包也是一种集体代码的结构,它一样升高了代码的可重新使用性。

当多个内嵌函数引用其外部作成效域的变量,大家就会获取三个闭包.
总计一下,创制叁个闭包必须知足以下几点:

  1. 必须有三个内嵌函数
  2. 内嵌函数必须引用外部函数中的变量
  3. 外表函数的重临值必须是内嵌函数

备感闭包还是有难度的,几句话是说不知情的,还是印证相关资料.

要害是函数运行后并不会被收回,就像是16题的instance字典一样,当函数运维完后,instance并不被灭绝,而是继续留在内部存款和储蓄器空间里.这些功能相近类里的类变量,只可是迁移到了函数上.

闭包就像是个空心球一样,你精晓外面和个中,但你不明了中间是怎么样样.

二十、lambda函数

事实上便是2个匿名函数,为啥叫lambda?因为和前边的函数式编制程序有关.

推荐: 知乎

二十① 、 Python函数式编制程序

其一需求适量的询问一下吧,终归函数式编制程序在Python中也做了引用.

推荐: 酷壳

python中等高校函授数式编制程序辅助:

filter
函数的成效也就是过滤器。调用贰个布尔函数bool_func来迭代遍历每一个seq中的成分;再次来到1个使bool_seq再次来到值为true的要素的体系。

>>>a = [1,2,3,4,5,6,7]

>>>b = filter(lambda x: x > 5, a)

>>>print b

>>>[6,7]

map函数是对1个队列的种种项依次执行函数,上面是对二个行列各类项都乘以2:

>>> a = map(lambda x:x*2,[1,2,3])

>>> list(a)

[2, 4, 6]

reduce函数是对3个行列的各类项迭代调用函数,上面是求3的阶乘:

>>> reduce(lambda x,y:x*y,range(1,4))

6

二十贰 、Python里的正片

引用和copy(),deepcopy()的区别

import copy

a = [1, 2, 3, 4, [‘a’, ‘b’]] #原本对象

b = a #赋值,传对象的引用

c = copy.copy(a) #目标拷贝,浅拷贝

d = copy.deepcopy(a) #对象拷贝,深拷贝

a.append(5) #修改对象a

a[4].append(‘c’) #修改对象a中的[‘a’, ‘b’]数组对象

print ‘a = ‘, a

print ‘b = ‘, b

print ‘c = ‘, c

print ‘d = ‘, d

输出结果:

a = [1, 2, 3, 4, [‘a’, ‘b’, ‘c’], 5]

b = [1, 2, 3, 4, [‘a’, ‘b’, ‘c’], 5]

c = [1, 2, 3, 4, [‘a’, ‘b’, ‘c’]]

d = [1, 2, 3, 4, [‘a’, ‘b’]]

二十③ 、Python垃圾回收机制

Python GC主要采纳引用计数(reference
counting)来跟踪和回收废品料。在引用计数的底蕴上,通过“标记-清除”(mark
and
sweep)化解容器对象或然产生的循环引用难点,通过“分代回收”(generation
collection)以空间换时间的措施进步垃圾回收效用。

1 引用计数

PyObject是各类对象必有的内容,在那之中ob_refcnt正是做为引用计数。当二个指标有新的引用时,它的ob_refcnt就会增多,当引用它的目的被剔除,它的ob_refcnt就会收缩.引用计数为0时,该对象生命就离世了。

优点:

  1. 简单
  2. 实时性

缺点:

  1. 珍贵引用计数消功耗源
  2. 循环引用

2 标记-清除机制

基本思路是先按需分配,等到没有空闲内部存款和储蓄器的时候从寄存器和顺序栈上的引用出发,遍历以目的为节点、以引用为边构成的图,把全部能够访问到的靶子打上标记,然后清扫二次内部存储器空间,把具有没标记的对象释放。

3 分代技术

分代回收的全体构思是:将系统中的全体内部存款和储蓄器块依据其现有时间分开为分裂的聚合,各个集合就改为一个“代”,垃圾收集频率随着“代”的幸存时间的叠加而减小,存活时间平日选用经过一次垃圾回收来衡量。

Python暗中认可定义了三代对象集合,索引数越大,对象共处时间越长。

比喻:
当有些内部存款和储蓄器块M经过了3回垃圾收集的保洁之后还存世时,大家就将内部存款和储蓄器块M划到一个集合A中去,而新分配的内存都分开到集合B中去。当垃圾收集起来工作时,超越50%情况都只对集合B进行垃圾回收,而对集合A实行垃圾回收要隔十分短一段时间后才举行,那就使得垃圾收集体制亟待处理的内部存款和储蓄器少了,功效自然就升高了。在那些进程中,集合B中的有些内部存款和储蓄器块由于现有时间长而会被更换来集合A中,当然,集合A中实际也设有一些废品,那个杂质的回收会因为那种分代的编写制定而被延缓。

二十四、Python的List

详见教程网上海人民广播广播台湾大学的,内容有点多,作者就不一一列出来了。

二十五、Python的is

is是对待地址,==是相比值

二十六、 read,readline和readlines

  • read 读取整个文件
  • readline 读取下一行,使用生成器方法
  • readlines 读取整个文件到3个迭代器以供我们遍历

二十七、 Python2和3的区别

推荐:Python 2.7.x 与 Python 3.x 的要害出入

二十八、super init

super() lets you avoid referring to the base class explicitly, which
can be nice. But the main advantage comes with multiple inheritance,
where all sorts of fun stuff can happen. See the standard docs on
super if you haven’t already.

Note that the syntax changed in Python 3.0: you can just say
super().__init__() instead of super(ChildB, self).__init__()
which IMO is quite a bit nicer.

Python2.7中的super方法浅见

二十九、range and xrange

都在循环时利用,xrange内部存款和储蓄器品质更好。 for i in range(0, 20): for i in
xrange(0, 20): What is the difference between range and xrange functions
in Python 2.X? range creates a list, so if you do range(1, 一千0000) it
creates a list in memory with 9999999 elements. xrange is a sequence
object that evaluates lazily.

类变量和实例变量

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了.

==可以看看下边包车型大巴事例: (need check)==
==python中list是mutable的类变量, 实例化之后也是mutable的,
所以对第二个实例的name操作, 也会滋生类变量以及其余的实例中list的改观==

==怎样防止==

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

a=1deffun(a):    a=2fun(a)printa#1

操作系统

一、select,poll和epoll

实际有着的I/O都是轮询的不二法门,只然则完结的局面分裂罢了.

那几个难点或者有点深切了,但相信能回复出那些题材是对I/O多路复用有很好的问询了.在那之中tornado使用的正是epoll的.

selec,poll和epoll差别计算

基本上select有3个缺点:

  1. 连接数受限
  2. 探寻配对速度慢
  3. 数码由基础拷贝到用户态

poll改革了第一个缺陷

epoll改了多少个缺点.

② 、调度算法

  1. 先来先服务(FCFS, First Come First Serve)
  2. 短作业优先(SJF, Shortest Job First)
  3. 参天优先权调度(Priority Scheduling)
  4. 时刻片轮转(福特Explorer途锐, Round 罗布in)
  • 一种类反馈队列调度(multilevel feedback queue scheduling)

实时调度算法:

  1. 最早停止时间优先 EDF
  2. 最低松弛度优先 LLF

三、死锁

原因:

  1. 竞争财富
  2. 次第推进种种不当

要求条件:

  1. 互斥条件
  2. 呼吁和保全标准
  3. 不剥夺条件
  4. 环路等待条件

处理死锁基本格局:

  1. 严防死锁(放任除1以外的口径)
  2. 防止死锁(银行家算法)
  3. 检查和测试死锁(财富分配图)
  4. 解决死锁
  5. 剥夺财富
  6. 撤除进度

死锁概念处理政策详细介绍的话,能够参照一下网上的。

四 、程序编写翻译与链接

Bulid进程可以解释为5个步骤:预处理(Prepressing),
编写翻译(Compilation)、汇编(Assembly)、链接(Linking)

python自省

其一也是python彪悍的脾气.

反躬自省正是面向对象的言语所写的次序在运营时,所能知道对象的类型.不难一句正是运维时亦可获取对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().

a=[]deffun(a):    a.append(1)fun(a)printa#[1]

以c语言为例:

一、预处理

预编写翻译进度主要处理那个源文件中的以“#”伊始的预编写翻译指令,首要处理规则有:

  1. 将有所的“#define”删除,并举行所用的宏定义
  2. 拍卖全部规则预编写翻译指令,比如“#if”、“#ifdef”、 “#elif”、“#endif”
  3. 处理“#include”预编写翻译指令,将被含有的文本插入到该编译指令的职责,注:此进度是递归举办的
  4. 除去全数注释
  5. 添加行号和文件名标识,以便于编写翻译时编写翻译器发生调节和测试用的行号音信以及用于编译时发生编写翻译错误或警示时可兆示行号
  6. 封存全数的#pragma编写翻译器指令。

二、编译

编写翻译进程正是把预处理完的文本举办一层层的词法分析、语法分析、语义分析及优化后变卦对应的汇编代码文件。这几个进度是整套程序塑造的主导部分。

三、汇编

汇编器是将汇编代码转化成机器能够执行的一声令下,每一条汇编语句大概皆以一条机器指令。经过编写翻译、链接、汇编输出的文件成为指标文件(Object
File)

四、链接

威尼斯人线上娱乐,链接的首要内容正是把种种模块之间交互引用的有的处理好,使种种模块能够正确的拼凑。
链接的显要进度包块 地址和空中的分配(Address and Storage
Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等步骤。

5、静态链接和动态链接

静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地方鲜明下来
静态库的链接能够动用静态链接,动态链接库也足以接纳这种方法链接导入库

动态链接方法:使用那种办法的主次并不在一开首就形成动态链接,而是直到真正调用动态库代码时,载入程序才总结(被调用的那部分)动态代码的逻辑地址,然后等到某些时候,程序又要求调用此外某块动态代码时,载入程序又去总括这一部分代码的逻辑地址,所以,那种艺术使程序初步化时间较短,但运营时期的品质比不上静态链接的程序

6、虚拟内部存款和储蓄器技术

虚拟存款和储蓄器是指装有请求调入功效和交流功用,能从逻辑上对内部存款和储蓄器体积加以扩展的一种存储系统.

7、分页和分支

分页:
用户程序的地址空间被剪切成多少恒定大小的区域,称为“页”,相应地,内存空间分成若干个物理块,页和块的轻重缓急相等。可将用户程序的任一页放在内部存款和储蓄器的任一块中,完结了离散分配。

支行:
将用户程序地址空间分成若干个大小不等的段,每段能够定义一组相对完整的逻辑信息。存款和储蓄分配时,以段为单位,段与段在内部存款和储蓄器中能够不相邻接,也达成了离散分配。

分页与分支的机要差距

  1. 页是新闻的大体单位,分页是为着促成非接二连三分配,以便化解内部存款和储蓄器碎片难题,也许说分页是出于系统一管理理的急需.段是消息的逻辑单位,它含有一组意义相对完好的消息,分段的指标是为着更好地实现共享,满意用户的要求.
  2. 页的尺寸固定,由系统鲜明,将逻辑地址划分为页号和页内地址是由机械硬件完毕的.而段的长度却不固定,决定于用户所编写的次第,经常由编写翻译程序在对源程序实行编译时依据音讯的质量来划分.
  3. 分页的功课地址空间是一维的.分段的地方空间是二维的.

⑧ 、页面置换算法

  1. 最棒置换算法OPT:不大概达成
  2. 先进先出FIFO
  3. 新近最久未使用算法LRU:近期一段时间里最久没有选择过的页面予以置换.
  4. clock算法

玖 、边沿触发和品位触发

边缘触发是指每当状态变化时发生1个 io
事件,条件触发是一旦满足条件就生出四个 io 事件

字典推导式:

d = {key: value for (key, value) in iterable}

你能够用任何方法的迭代器(元组,列表,生成器..),只要可迭代对象的要素中有三个值.

d = {value: foo(value) for value in sequence if bar(value)}

def key_value_gen(k):
   yield chr(k+65)
   yield chr((k+13)%26+65)
d = dict(map(key_value_gen, range(26)))

抱有的变量都足以领悟是内存中三个对象的“引用”,可能,也能够看似c中void*的感觉。

数据库

一、事务

数据库事务(Database Transaction)
,是指作为单个逻辑工作单元执行的一文山会海操作,要么完全地履行,要么完全地不实施。

干净通晓数据库事务详细教程一搜第一次全国代表大会把,能够活动物检疫索一下。

贰 、数据库索引

MySQL索引背后的数据结构及算法原理

聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理

三、Redis原理

Redis是什么?

  1. 是3个通通开源免费的key-value内部存款和储蓄器数据库
  2. 一般被认为是二个数据结构服务器,重假若因为其全数丰硕的数据结构
    strings、map、 list、sets、 sorted sets

Redis数据库

​经常局限点来说,Redis也以新闻队列的款式存在,作为内嵌的List存在,满意实时的高并发须要。在选择缓存的时候,redis比memcached具有越多的优势,并且援助越来越多的数据类型,把redis当作2个在那之中存款和储蓄系统,用来拍卖高并发的数据库操作

  • 进程快:使用标准C写,全部数据都在内部存款和储蓄器中做到,读写速度分别高达10万/20万
  • 持久化:对数码的更新选取Copy-on-write技术,能够异步地保留到磁盘上,首要有三种政策,一是依据时间,更新次数的快速照相(save
    300 10 )二是基于语句追加格局(Append-only file,aof)
  • 自行操作:对两样数据类型的操作都是自动的,很安全
  • 迅猛的主–从复制,官方提供了2个多少,Slave在21秒即完结了对亚马逊(Amazon)网站10G
    key set的复制。
  • Sharding技术:
    很不难将数据分布到七个Redis实例中,数据库的扩展是个稳定的话题,在关系型数据库中,首要是以增进硬件、以分区为机要技术格局的纵向扩充化解了好多的选择场景,但随着web2.0、移动网络、云总结等利用的勃兴,这种扩充格局已经不太符合了,所以近期,像采取主从配置、数据库复制方式的,Sharding那种技能把负载分布到多少个特理节点上去的横向增加格局用处越来越多。

Redis缺点

  • 是数据水库蓄水体积量受到物理内部存储器的限量,无法用作海量数据的高质量读写,因而Redis适合的景观重要局限在较小数据量的高品质操作和平运动算上。
  • Redis较难支撑在线扩大体量,在集群体积达到上限时在线扩大体积会变得很复杂。为幸免这一难点,运维职员在系统上线时必须保障有丰富的上空,那对能源造成了十分的大的荒废。

④ 、乐观锁和悲观锁

想不开锁:假定会发出并发争辩,屏蔽一切大概违反数据完整性的操作

开朗锁:假如不会发生并发冲突,只在付给操作时检查是还是不是违反数据完整性。

五、MVCC

​全称是Multi-Version Concurrent
Control,即多版本出现控制,在MVCC协议下,每个读操作会看到2个一致性的snapshot,并且能够达成非阻塞的读。MVCC允许数据有所五个本子,这么些本子能够是时间戳可能是全局递增的事情ID,在同1个时间点,分裂的事情看到的多寡是见仁见智的。

MySQL的innodb引擎是哪些兑现MVCC的

innodb会为每一行添加多少个字段,分别表示该行创制的版本和删除的本子,填入的是业务的本子号,这几个版本号随着事情的创制不断递增。在repeated
read的割裂级别(事务的割裂级别请看那篇小说)下,具体种种数据库操作的落到实处:

  • select:满意以下四个标准innodb会再次回到该行数据:
  • 该行的创设版本号小于等于当前版本号,用于保障在select操作在此之前全部的操作已经推行落地。
  • 该行的去除版本号大于当前版本大概为空。删除版本号大于当前版本意味着有二个并发事务将该行删除了。
  • insert:将新插入的行的制造版本号设置为如今系统的版本号。
  • delete:将要删除的行的去除版本号设置为当下系统的版本号。
  • update:不执行原地update,而是转换来insert +
    delete。将旧行的删减版本号设置为近年来版本号,并将新行insert同时安装成立版本号为近年来版本号。

里面,写操作(insert、delete和update)执行时,须要将系统版本号递增。

​由于旧数据并不确实的去除,所以必须对这一个多少开始展览清理,innodb会开启四个后台线程执行清理工科作,具体的规则是将去除版本号小于当前系统版本的行删除,那个历程叫做purge。

经过MVCC很好的兑现了事情的隔断性,能够直达repeated
read级别,要促成serializable还非得加锁。

参考:MVCC浅析

六、MyISAM和InnoDB

MyISAM
适合于一些内需大批量查询的使用,但其对于有大气写操作并不是很好。甚至你只是亟需update多少个字段,整个表都会被锁起来,而别的进度,就终于读进程都没办法儿操作直到读操作完成。此外,MyISAM
对于 SELECT COUNT(*) 那类的一个钱打二15个结是超快无比的。

InnoDB 的可行性会是二个格外复杂的囤积引擎,对于某些小的行使,它会比 MyISAM
还慢。他是它补助“行锁”
,于是在写操作相比多的时候,会更精良。并且,他还扶助越多的高档应用,比如:事务。

python中单下划线和双下划线

那篇小说研商Python中下划线_的使用。跟Python山西中国广播集团大用法类似,下划线_的不等用法绝大多数(不全是)都是一种规矩约定。

由此id来看引用a的内部存储器地址可以相比较清楚:

网络

一 、 三遍握手

  1. 客户端通过向服务器端发送三个SYN来创制一个百尺竿头更进一步打开,作为一次握手的一片段。客户端把那段连接的序号设定为专断数
    A。
  2. 服务器端应当为二个官方的SYN回送三个SYN/ACK。ACK 的确认码应为
    A+1,SYN/ACK 包自己又有一个自由序号 B。
  3. 终极,客户端再发送贰个ACK。当服务端受到这几个ACK的时候,就成功了三路握手,并进入了连续创立状态。此时包序号被设定为接受的确认号
    A+1,而响应则为 B+1。

二 、五遍挥手

在意: 中断连接端能够是客户端,也足以是服务器端.
上边仅以客户端断开连接举例, 反之亦然.

  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 状态.
    服务器收到到报文后关闭连接. 客户端等待 2MSL 后未接到回复,
    则认为服务器成功关闭, 客户端关闭连接.

三、ARP协议

地方解析协议(Address Resolution
Protocol),其基本成效为通过目的设备的IP地址,查询指标的MAC地址,以管教通讯的顺遂举办。它是IPv4互联网层必不可少的协商,可是在IPv6中已不复适用,并被街坊发现协议(NDP)所替代。

四、urllib和urllib2的区别

其一面试官确实问过,当时答的urllib2能够Post而urllib无法.

  1. urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。那是干什么urllib常和urllib2一起行使的原委。
  2. urllib2还可以多个Request类的实例来设置UXC90L请求的headers,urllib仅尚可U奥迪Q5L。那象征,你不能伪装你的User
    Agent字符串等。

五、Post和Get

GET和POST有怎样界别?及为何网上的超越百分之五十答案都是错的 今日头条回答

get: RFC 2616 – Hypertext Transfer Protocol — HTTP/1.1 post: RFC 2616 –
Hypertext Transfer Protocol — HTTP/1.1

六、Cookie和Session

CookieSession储存地点客户端服务器端指标跟踪会话,也得以保留用户偏好设置恐怕封存用户名密码等跟踪会话安全性不安全无恙

session技术是要使用到cookie的,之所以出现session技术,主假诺为了安全。

七、apache和nginx的区别

nginx 相对 apache 的优点:

  • 轻量级,同样起web 服务,比apache 占用更少的内部存款和储蓄器及能源
  • 抗并发,nginx 处理请求是异步非阻塞的,帮衬更加多的面世连接,而apache
    则是阻塞型的,在高并发下nginx 能保持低能源低消耗高性能
  • 布置简洁
  • 惊人模块化的统一筹划,编写模块相对简单
  • 社区活泼

apache 相对nginx 的优点:

  • rewrite ,比nginx 的rewrite 强大
  • 模块超多,基本想到的都能够找到
  • 少bug ,nginx 的bug 相对较多
  • 超稳定

八 、 网站用户密码保存

  1. 当着保存
  2. 明文hash后保存,如md5
  3. MD5+Salt格局,那几个salt能够肆意
  4. 乐乎使用了Bcrypy(好像)加密

九、 HTTP和HTTPS

动静码定义1xx 报告吸收接纳到请求,继续进度2xx
得逞步骤成功接收,被精晓,并被接受3xx
重定向为了完结请求,必须使用进一步措施4xx
客户端出错请求包含错的次第或不可能一鼓作气5xx
服务器出错服务器不只怕到位显著有效的呼吁

403: Forbidden 404: Not Found

HTTPS握手,对称加密,非对称加密,TLS/SSL,本田UR-VSA

十、 XSRF和XSS

  • CS瑞虎F(克罗斯-site request forgery)跨站请求伪造
  • XSS(克罗斯 Site Scripting)跨站脚本攻击

CS汉兰达F重点在伸手,XSS重点在本子

十一、幂等 Idempotence

HTTP方法的幂等性是指2次和多次伸手某二个能源应该有着相同的副功能。(注意是副成效)

不会变动能源的事态,不论调用贰遍依旧N次都尚未副成效。请留意,那里强调的是2次和N次具有同样的副功用,而不是历次GET的结果一致。

那些HTTP请求或许会每回获得分歧的结果,但它自个儿并不曾发出别的副成效,由此是满意幂等性的。

DELETE方法用于删除能源,有副成效,但它应有满足幂等性。

调用1回和N次对系统发生的副成效是同等的,即删掉id为4231的帖子;因而,调用者能够频繁调用或刷新页面而毋庸担心引起错误。

POST所对应的URubiconI并非创造的资源本人,而是财富的收信人。

HTTP响应中应涵盖帖子的创办状态以及帖子的ULacrosseI。五次相同的POST请求会在劳务器端创立两份能源,它们具有分裂的U福睿斯I;所以,POST方法不享有幂等性。

PUT所对应的ULX570I是要开创或更新的资源自己。比如:PUT

十二、RESTful架构(SOAP,RPC)

详细教程能够在网上搜索一下

十三、 SOAP

SOAP(原为Simple Object Access
Protocol的首字母缩写,即不难对象访问协议)是换到数据的一种协议正式,使用在计算机互连网Web服务(web
service)中,交流带结构新闻。SOAP为了简化网页服务器(Web
Server)从XML数据库中提取数额时,节省去格式化页面时间,以及区别应用程序之间依据HTTP通讯协议,遵从XML格式执行资料交换,使其抽象于言语达成、平台和硬件。

十四、RPC

奥迪Q5PC(Remote Procedure Call
Protocol)——远程进程调用协议,它是一种通过网络从远程总结机程序上呼吁服务,而不要求掌握底层互联网技术的商业事务。OdysseyPC协和式飞机要是某个传输协议的存在,如TCP或UDP,为通信程序之间辅导新闻数据。在OSI网络通讯模型中,锐界PC跨越了传输层和应用层。奥迪Q5PC使得开发包括网络分布式多程序在内的应用程序尤其便于。

小结:服务提供的两大流派.古板意义以艺术调用为导向通称PAJEROPC。为了公司SOA,若干厂商联合推出webservice,制定了wsdl接口定义,传输soap.当互连网时代,臃肿SOA被简化为http+xml/json.不过简化现身种种混乱。以财富为导向,任何操作无非是对财富的增删改查,于是统一的REST出现了.

发展的顺序: OdysseyPC -> SOAP -> RESTful

十五、CGI和WSGI

CGI是通用网关接口,是连连web服务器和应用程序的接口,用户通过CGI来得到动态数据或文件等。
CGI程序是一个独门的次序,它能够用差不多全数语言来写,包含perl,c,lua,python等等。

WSGI, Web Server Gateway
Interface,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的内部三个目标就是让用户能够用统一的言语(Python)编写前后端。

官方证实:PEP-3333

十6、中间人抨击

在GFW里不以为奇的,呵呵.

中等人抨击(Man-in-the-middle
attack,经常缩写为MITM)是指攻击者与报纸发表的互相分别创造独立的牵连,并调换其所收取的数额,使通信的两岸认为他俩正在通过2个私密的连日与对方间接对话,但其实整个会话都被攻击者完全控制。

十七、 c10k问题

所谓c10k难点,指的是服务器同时援救广大个客户端的题材,也正是concurrent
10 000 connection(那也是c10k以此名字的原由)。

十八、socket

详细教程小编就不一一列举了,大家能够活动检索一下。

十⑨ 、浏览器缓存

详细教程作者就不一一列举了,我们能够活动物检疫索一下。

304 Not Modified

二十、 HTTP1.0和HTTP1.1

  1. 请求头Host字段,八个服务器多少个网站
  2. 长链接
  3. 文本断点续传
  4. 身价验证,状态管理,Cache缓存

HTTP请求8种形式介绍
HTTP/1.1商谈中国共产党定义了8种HTTP请求方法,HTTP请求方法也被称呼“请求动作”,分歧的主意规定了差别的操作钦赐的能源格局。服务端也会遵照区别的伸手方法做差别的响应。

GET

GET请求会呈现请求内定的能源。一般的话GET方法应该只用于数据的读取,而不应有用于会发出副作用的非幂等的操作中。

GET会办法请求内定的页面新闻,并回到响应中心,GET被认为是不安全的不二法门,因为GET方法会被网络蜘蛛等任意的走访。

HEAD

HEAD方法与GET方法一致,都以向服务器发出钦赐能源的请求。可是,服务器在响应HEAD请求时不会回传财富的内容部分,即:响应大旨。那样,大家得以不传输全体内容的气象下,就足以取得服务器的响应头新闻。HEAD方法常被用来客户端查看服务器的性质。

POST

POST请求会
向内定能源提交数据,请求服务器举行处理,如:表单数据交到、文件上传等,请求数据会被含有在请求体中。POST方法是非幂等的措施,因为那么些请求或者会创建新的财富或/和改动现有能源。

PUT

PUT请求会身向钦赐能源任务上传其最新内容,PUT方法是幂等的主意。通过该办法客户端能够将点名财富的新型数据传送给服务器代替内定的能源的内容。

DELETE

DELETE请求用于请求服务器删除所请求UPRADOI(统一能源标识符,Uniform Resource
Identifier)所标识的能源。DELETE请求后钦定财富会被剔除,DELETE方法也是幂等的。

CONNECT

CONNECT方法是HTTP/1.1研讨预留的,能够将一连改为管Doug局的代理服务器。经常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通讯。

OPTIONS

OPTIONS请求与HEAD类似,一般也是用以客户端查看服务器的习性。
那一个方法会请求服务器重回该财富所支撑的装有HTTP请求方法,该措施会用’*’来代表财富名称,向服务器发送OPTIONS请求,能够测试服务器功效是还是不是健康。JavaScript的XMLHttpRequest对象开始展览CO大切诺基S跨域能源共享时,正是应用OPTIONS方法发送嗅探请求,以判断是还是不是有对点名财富的拜访权限。
允许

TRACE

TRACE请求服务器回显其接收的请求新闻,该方法重要用于HTTP请求的测试或确诊。

HTTP/1.1从此扩展的不二法门

在HTTP/1.1正规制订之后,又陆续扩充了有的办法。在那之中使用中较多的是 PATCH
方法:

PATCH

PATCH方法现身的较晚,它在二〇一〇年的锐界FC
5789行业内部中被定义。PATCH请求与PUT请求类似,同样用于财富的翻新。二者有以下两点区别:

但PATCH一般用于能源的一对更新,而PUT一般用来财富的一体化创新。
当能源不存在时,PATCH会成立三个新的财富,而PUT只会对已在财富举行更新。

二十一、Ajax

AJAX,Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),
是与在不重复加载整个页面包车型客车状态下,与服务器交流数据并立异部分网页的技术。

单下划线(_)

器重有两种状态:

  1. 解释器中

_标记是指相互解释器中最终一回实施语句的回来结果。那种用法最初出未来CPython解释器中,其余解释器后来也都跟进了。

>>> _
Traceback (most recent call last):
  File "", line 1, in 
NameError: name '_' is not defined
>>> 42
>>> _
42
>>> 'alright!' if _ else ':('
'alright!'
>>> _
'alright!'
  1. 用作名称使用

以此跟上边有点类似。_作为被丢掉的称呼。遵照常规,那样做能够让阅读你代码的人通晓,这是个不会被使用的特定称谓。举个例子,你或然无所谓1个循环计数的值:

n = 42
for _ in range(n):
    do_something()
  1. i18n

_还足以被用作函数名。那种处境,单下划线平日被作为国际化和本土壤化学字符串翻译查询的函数名。那种惯例好像源点于C语言。举个例子,在
Django documentation for translation 中您或者汇合到:

from django.utils.translation import ugettext as _
from django.http import HttpResponse

def my_view(request):
    output = _("Welcome to my site.")
    return HttpResponse(output)

第一种和第两种用法会引起争持,所以在肆意代码块中,就算应用了_作i18n翻译查询函数,就应该制止再用作被撇下的变量名。

a=1deffun(a):print”func_in”,id(a)#func_in
41322472a=2print”re-point”,id(a),id(2)#re-point 41322448
41322448print”func_out”,id(a),id(1)#func_out 41322472
41322472fun(a)printa#1

*NIX

unix进程间通讯情势(IPC)

  1. 管道(Pipe):管道可用于具有亲缘关系进度间的通讯,允许1个进度和另二个与它有协同祖先的长河之间展开通讯。
  2. 命名管道(named
    pipe):命名管道征服了管道没盛名字的限量,由此,除具备管道所持有的职能外,它还同意无亲缘关系进度间的通讯。命名管道在文件系统中有照应的文本名。命名管道通过命令mkfifo或种类调用mkfifo来创立。
  3. 信号(Signal):信号是比较复杂的通讯格局,用于公告接受进度有某种事件发生,除了用于进度间通讯外,进度还是能发送信号给进度本人;linux除了扶助Unix早期信号语义函数sigal外,还扶助语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了兑现可信赖信号机制,又可以合并对外接口,用sigaction函数重新实现了signal函数)。
  4. 音讯(Message)队列:音讯队列是音讯的链接表,包含Posix新闻队列system
    V音信队列。有丰盛权限的进度能够向队列中添加音信,被赋予读权限的经过则能够读走队列中的新闻。消息队列制伏了信号承载消息量少,管道只好承载无格式字节流以及缓冲区大小受限等缺
  5. 共享内部存款和储蓄器:使得多个进度能够访问同一块内部存款和储蓄器空间,是最快的可用IPC方式。是本着别的通讯机制运维成效较低而布署的。往往与其它通讯机制,如信号量结合使用,来达到进度间的联手及互斥。
  6. 内部存款和储蓄器映射(mapped
    memory):内部存款和储蓄器映射允许别的八个进度间通讯,每二个应用该机制的进度经过把一个共享的文书映射到自身的经过地址空间来贯彻它。
  7. 信号量(semaphore):首要作为进程间以及同样进程分歧线程之间的一块手段。
  8. 套接口(Socket):更为相似的进度间通讯机制,可用来分化机器之间的经过间通讯。开首是由Unix系统的BSD分支开发出来的,但后日貌似能够移植到其余类Unix系统上:Linux和System
    V的变种都辅助套接字。

单下划线前缀的称呼(例如_shahriar)

以单下划线做前缀的名目钦赐了那几个称号是“私有的”。在 有个别 导入import *
的场景中,下四个使用你代码的人(或许您自笔者)会精通那几个称号仅内部使用。Python
documentation里面写道:

a name prefixed with an underscore (e.g. _spam) should be treated as
a non-public part of the API (whether it is a function, a method or a
data member). It should be considered an implementation detail and
subject to change without notice.

据此说在在 有个别 import *
的场地,是因为导入时解释器确实对单下划线开头的名号做了处理。就算您那样写from <module/package> import *,任何以单下划线发轫的名称都不会被导入,除非模块/包的__all__列表显然涵盖了那个名称。越多相关音讯见““Importing * in Python”

注:具体的值在差别电脑上运维时可能两样。

数据结构

红黑树

红黑树与AVL的相比较:

AVL是从严平衡树,由此在扩张只怕去除节点的时候,依照区别境况,旋转的次数比红黑树要多;

红黑是用非严加的平衡来换取增加和删除节点时候转动次数的回落;

故此简单说,若是你的运用中,搜索的次数远远胜出插入和删除,那么选择AVL,倘若搜索,插入删除次数大概大致,应该选用RB。

双下划线前缀的称呼(例如__shahriar

以双下划线做前缀的名号(特别是方法名)并不是一种规矩;它对解释器有一定含义。Python会改写这么些名称,防止与子类中定义的称呼发生顶牛。Python
documentation中关系,任何__spam那种方式(至少以两个下划线做始发,绝超越5/10都还有一个下划线做最终)的标识符,都会文件上被沟通为_classname__spam,在那之中classname是当下类名,并带上贰个下划线做前缀。
看下边那么些事例:

>>> class A(object):
...     def _internal_use(self):
...         pass
...     def __method_name(self):
...         pass
... 
>>> dir(A())
['_A__method_name', ..., '_internal_use']

正如所料,_internal_use没有生成,但__method_name被改写成了_ClassName__method_name。现在创建二个A的子类B(那可不是个好名字),就不会随随便便的掩盖掉A中的__method_name了:

>>> class B(A):
...     def __method_name(self):
...         pass
... 
>>> dir(B())
['_A__method_name', '_B__method_name', ..., '_internal_use']

那种特定的一言一动大多等价于Java中的final方法和C++中的平常格局(非虚方法)。

能够看出,在执行完a =
2之后,a引用中保存的值,即内部存款和储蓄器地址产生变化,由原本1对象的中国人民解放军第伍野战军的地点变成了2以此实体对象的内部存款和储蓄器地址。

编程题

一 、台阶难题/斐波那契

1只青蛙贰次可以跳上1级台阶,也得以跳上2级。求该青蛙跳上3个n级的阶梯总共有稍许种跳法。

fib = lambda n: n if n <= 2 else fib(n – 1) + fib(n – 2)

其次种回忆方法

def memo(func):

cache = {}

def wrap(*args):

if args not in cache:

cache[args] = func(*args)

return cache[args]

return wrap

@memo

def fib(i):

if i < 2:

return 1

return fib(i-1) + fib(i-2)

其三种方法

def fib(n):

a, b = 0, 1

for _ in xrange(n):

a, b = b, a + b

return b

贰 、变态台阶难题

3只青蛙二回能够跳上1级台阶,也能够跳上2级……它也可以跳上n级。求该青蛙跳上三个n级的台阶总共有稍许种跳法。

fib = lambda n: n if n < 2 else 2 * fib(n – 1)

三 、矩形覆盖

咱俩能够用2*1的小矩形横着可能竖着去掩盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖贰个2*n的大矩形,总共有稍许种方法?

第2*n个矩形的掩盖措施等于第1*(n-1)加上第2*(n-2)的方法。

f = lambda n: 1 if n < 2 else f(n – 1) + f(n – 2)

四 、杨氏矩阵查找

在三个m行n列二维数组中,每一行都依据从左到右递增的依次排序,每一列都遵循从上到下递增的次第排序。请实现三个函数,输入那样的贰个二维数组和三个平头,判断数组中是或不是带有该整数。

动用Step-wise线性搜索。

def get_value(l, r, c):

return l[r][c]

def find(l, x):

m = len(l) – 1

n = len(l[0]) – 1

r = 0

c = n

while c >= 0 and r <= m:

value = get_value(l, r, c)

if value == x:

return True

elif value > x:

c = c – 1

elif value < x:

r = r + 1

return False

五 、去除列表中的重复成分

用集合

list(set(l))

用字典

l1 = [‘b’,’c’,’d’,’b’,’c’,’a’,’a’]

l2 = {}.fromkeys(l1).keys()

print l2

用字典并保证顺序

l1 = [‘b’,’c’,’d’,’b’,’c’,’a’,’a’]

l2 = list(set(l1))

l2.sort(key=l1.index)

print l2

列表推导式

l1 = [‘b’,’c’,’d’,’b’,’c’,’a’,’a’]

l2 = []

[l2.append(i) for i in l1 if not i in l2]

sorted排序并且用列表推导式.

l = [‘b’,’c’,’d’,’b’,’c’,’a’,’a’] [single.append(i) for i in
sorted(l) if i not in single] print single

⑦ 、链表成对调换

1->2->3->4转换成2->1->4->3.

class ListNode:

def __init__(self, x):

self.val = x

self.next = None

class Solution:

# @param a ListNode

# @return a ListNode

def swapPairs(self, head):

if head != None and head.next != None:

next = head.next

head.next = self.swapPairs(next.next)

next.next = head

return next

return head

柒 、创设字典的法门

1 直接创造

dict = {‘name’:’earth’, ‘port’:’80’}

2 工厂方法

items=[(‘name’,’earth’),(‘port’,’80’)]

dict2=dict(items)

dict1=dict(([‘name’,’earth’],[‘port’,’80’]))

3 fromkeys()方法

dict1={}.fromkeys((‘x’,’y’),-1)

dict={‘x’:-1,’y’:-1}

dict2={}.fromkeys((‘x’,’y’))

dict2={‘x’:None, ‘y’:None}

八 、合并几个静止列表

天涯论坛远程面试需求编制程序

尾递归

def _recursion_merge_sort2(l1, l2, tmp):

if len(l1) == 0 or len(l2) == 0:

tmp.extend(l1)

tmp.extend(l2)

return tmp

else:

if l1[0] < l2[0]:

tmp.append(l1[0])

del l1[0]

else:

tmp.append(l2[0])

del l2[0]

return _recursion_merge_sort2(l1, l2, tmp)

def recursion_merge_sort2(l1, l2):

return _recursion_merge_sort2(l1, l2, [])

循环算法

思路:

概念一个新的空驶列车表

相比较多少个列表的第多个成分

小的就插入到新列表里

把已经插入新列表的要素从旧列表删除

以至于多少个旧列表有一个为空

再把旧列表加到新列表前面

def loop_merge_sort(l1, l2):

tmp = []

while len(l1) > 0 and len(l2) > 0:

if l1[0] < l2[0]:

tmp.append(l1[0])

del l1[0]

else:

tmp.append(l2[0])

del l2[0]

tmp.extend(l1)

tmp.extend(l2)

return tmp

pop弹出

a = [1,2,3,7]

b = [3,4,5]

def merge_sortedlist(a,b):

c = []

while a and b:

if a[0] >= b[0]:

c.append(b.pop(0))

else:

c.append(a.pop(0))

while a:

c.append(a.pop(0))

while b:

c.append(b.pop(0))

return c

print merge_sortedlist(a,b)

玖 、交叉链表求交点

实在想想能够依据从尾初始比较五个链表,假设相交,则从尾发轫必然一致,只要从尾开始比较,直至分裂等的地点即为交叉点,如图所示

威尼斯人线上娱乐 2

 

# 使用a,b四个list来效仿链表,能够看到交叉点是 7那些节点

a = [1,2,3,7,9,1,5]

b = [4,5,7,9,1,5]

for i in range(1,min(len(a),len(b))):

if i==1 and (a[-1] != b[-1]):

print “No”

break

else:

if a[-i] != b[-i]:

print “交叉节点:”,a[-i+1]

break

else:

pass

其它一种对比规范的不二法门,构造链表类

class ListNode:

def __init__(self, x):

self.val = x

self.next = None

def node(l1, l2):

length1, lenth2 = 0, 0

# 求五个链表长度

while l1.next:

l1 = l1.next

length1 += 1

while l2.next:

l2 = l2.next

length2 += 1

# 长的链表先走

if length1 > lenth2:

for _ in range(length1 – length2):

l1 = l1.next

else:

for _ in range(length2 – length1):

l2 = l2.next

while l1 and l2:

if l1.next == l2.next:

return l1.next

else:

l1 = l1.next

l2 = l2.next

修改了一下:

#coding:utf-8

class ListNode:

def __init__(self, x):

self.val = x

self.next = None

def node(l1, l2):

length1, length2 = 0, 0

# 求七个链表长度

while l1.next:

l1 = l1.next#尾节点

length1 += 1

while l2.next:

l2 = l2.next#尾节点

length2 += 1

#即便相交

if l1.next == l2.next:

# 长的链表先走

if length1 > length2:

for _ in range(length1 – length2):

l1 = l1.next

return l1#回到交点

else:

for _ in range(length2 – length1):

l2 = l2.next

return l2#再次回到交点

# 要是不相交

else:

return

⑩ 、二分查找

#coding:utf-8

def binary_search(list,item):

low = 0

high = len(list)-1

while low<=high:

mid = (low+high)/2

guess = list[mid]

if guess>item:

high = mid-1

elif guess<item:

low = mid+1

else:

return mid

return None

mylist = [1,3,5,7,9]

print binary_search(mylist,3)

十一、快排

#coding:utf-8

def quicksort(list):

if len(list)<2:

return list

else:

midpivot = list[0]

lessbeforemidpivot = [i for i in list[1:] if i<=midpivot]

biggerafterpivot = [i for i in list[1:] if i > midpivot]

finallylist =
quicksort(lessbeforemidpivot)+[midpivot]+quicksort(biggerafterpivot)

return finallylist

print quicksort([2,4,6,7,1,2,5])

更加多排序难题凸现:数据结构与算法-排序篇-Python描述

十贰 、找零难题

#coding:utf-8

#values是硬币的面值values = [ 25, 21, 10, 5, 1]

#valuesCounts 钱币对应的品种数

#money 找出来的总钱数

#coinsUsed 对应于当下钱币总数i所使用的硬币数目

def coinChange(values,valuesCounts,money,coinsUsed):

#遍历出从1到money全体的钱数也许

for cents in range(1,money+1):

minCoins = cents

#把装有的硬币面值遍历出来和钱数做相比

for kind in range(0,valuesCounts):

if (values[kind] <= cents):

temp = coinsUsed[cents – values[kind]] +1

if (temp < minCoins):

minCoins = temp

coinsUsed[cents] = minCoins

print (‘面值:{0}的起码硬币使用数为:{1}’.format(cents,
coinsUsed[cents]))

十叁 、广度遍历和纵深遍历二叉树

给定三个数组,营造二叉树,并且按层次打印这些二叉树

十④ 、二叉树节点

class Node(object):

def __init__(self, data, left=None, right=None):

self.data = data

self.left = left

self.right = right

tree = Node(1, Node(3, Node(7, Node(0)), Node(6)), Node(2, Node(5),
Node(4)))

十伍 、 层次遍历

def lookup(root):

row = [root]

while row:

print(row)

row = [kid for item in row for kid in (item.left, item.right) if
kid]

十⑥ 、深度遍历

def deep(root):

if not root:

return

print root.data

deep(root.left)

deep(root.right)

if __name__ == ‘__main__’:

lookup(tree)

deep(tree)

十七 、 前中后序遍历

深度遍历改变各样就OK了

#coding:utf-8

#二叉树的遍历

#简短的二叉树节点类

class Node(object):

def __init__(self,value,left,right):

self.value = value

self.left = left

self.right = right

#中序遍历:遍历左子树,访问当前节点,遍历右子树

def mid_travelsal(root):

if root.left is None:

mid_travelsal(root.left)

#走访当前节点

print(root.value)

if root.right is not None:

mid_travelsal(root.right)

#前序遍历:访问当前节点,遍历左子树,遍历右子树

def pre_travelsal(root):

print (root.value)

if root.left is not None:

pre_travelsal(root.left)

if root.right is not None:

pre_travelsal(root.right)

#此起彼伏遍历:遍历左子树,遍历右子树,访问当前节点

def post_trvelsal(root):

if root.left is not None:

post_trvelsal(root.left)

if root.right is not None:

post_trvelsal(root.right)

print (root.value)

十八 、求最大树深

def maxDepth(root):

if not root:

return 0

return max(maxDepth(root.left), maxDepth(root.right)) + 1

十九 、求两棵树是不是同样

def isSameTree(p, q):

if p == None and q == None:

return True

elif p and q :

return p.val == q.val and isSameTree(p.left,q.left) and
isSameTree(p.right,q.right)

else :

return False

二10、前序中序求后序

def rebuild(pre, center):

if not pre:

return

cur = Node(pre[0])

index = center.index(pre[0])

cur.left = rebuild(pre[1:index + 1], center[:index])

cur.right = rebuild(pre[index + 1:], center[index + 1:])

return cur

def deep(root):

if not root:

return

deep(root.left)

deep(root.right)

print root.data

二十壹 、单链表逆置

class Node(object):

def __init__(self, data=None, next=None):

self.data = data

self.next = next

link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8,
Node(9)))))))))

def rev(link):

pre = link

cur = link.next

pre.next = None

while cur:

tmp = cur.next

cur.next = pre

pre = cur

cur = tmp

return pre

root = rev(link)

while root:

print root.data

root = root.next

二十二 、 五个字符串是或不是是变位词

class Anagram:

“””

@:param s1: The first string

@:param s2: The second string

@:return true or false

“””

def Solution1(s1,s2):

alist = list(s2)

pos1 = 0

stillOK = True

while pos1 < len(s1) and stillOK:

pos2 = 0

found = False

while pos2 < len(alist) and not found:

if s1[pos1] == alist[pos2]:

found = True

else:

pos2 = pos2 + 1

if found:

alist[pos2] = None

else:

stillOK = False

pos1 = pos1 + 1

return stillOK

print(Solution1(‘abcd’,’dcba’))

def Solution2(s1,s2):

alist1 = list(s1)

alist2 = list(s2)

alist1.sort()

alist2.sort()

pos = 0

matches = True

while pos < len(s1) and matches:

if alist1[pos] == alist2[pos]:

pos = pos + 1

else:

matches = False

return matches

print(Solution2(‘abcde’,’edcbg’))

def Solution3(s1,s2):

c1 = [0]*26

c2 = [0]*26

for i in range(len(s1)):

pos = ord(s1[i])-ord(‘a’)

c1[pos] = c1[pos] + 1

for i in range(len(s2)):

pos = ord(s2[i])-ord(‘a’)

c2[pos] = c2[pos] + 1

j = 0

stillOK = True

while j<26 and stillOK:

if c1[j] == c2[j]:

j = j + 1

else:

stillOK = False

return stillOK

print(Solution3(‘apple’,’pleap’))

二十三 、动态规划难点

可参考:动态规划(DP)的重新整建-Python描述

 

上下都包蕴双下划线的称谓(例如__init__

这个是Python的出格措施名,这只有是一种规矩,一种保障Python系统中的名称不会跟用户自定义的名称发生争论的措施。常常你可以覆写这一个措施,在Python调用它们时,发生你想得到的行事。例如,当写2个类的时候常常会覆写__init__方法。
你也得以写出自个儿的“特殊格局”名(不过别那样做):

>>> class C(object):
...     def __mine__(self):
...         pass
...
>>> dir(C)
... [..., '__mine__', ...]

照旧不要这么写方法名,只让Python定义的独特格局名使用那种惯例吧。

详情见:http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python

或者:
http://www.zhihu.com/question/19754941

而第①个例子a引用保存的内部存款和储蓄器值就不会爆发变化:

字符串格式化:%和.format

.format在不少地方看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你大概会想上边包车型大巴代码不会有啥难题:

hi there %s" % name

然而,假设name恰好是(1,2,3),它将会抛出贰个TypeError非凡.为了有限支撑它连接不错的,你无法不这么做:

hi there %s" % (name,) # 提供一个单元素的数组而不是一个参数

可是有个别丑..format就从不这一个难点.你给的第③个难点也是如此,.format雅观多了.

你为什么不用它?

不知晓它(在读那么些后面)
为了和Python2.5配合(譬如logging库提出使用%(issue #4))

http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format

a=[]deffun(a):print”func_in”,id(a)#func_in
53629256a.append(1)print”func_out”,id(a)#func_out
53629256fun(a)printa#[1]

迭代器和生成器

那么些是stackoverflow里python排行第叁的题材,值得一看:
http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python

那是普通话版:
http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html

那里记住的是种类是属于对象的,而不是变量。而目的有三种,“可更改”(mutable)与“不可改变”(immutable)对象。在python中,strings,
tuples, 和numbers是不行变更的目的,而 list, dict, set
等则是可以修改的靶子。(这正是那个题材的要紧)

Iterables

当你创建了一个列表,你能够二个二个的读取它的每一项,那称之为iteration:

>>> mylist = [1, 2, 3]
>>> for i in mylist:
...    print(i)
1
2
3

Mylist是可迭代的.当你用列表推导式的时候,你就创办了二个列表,而以此列表也是可迭代的:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4

持有你能够用在for…in…语句中的都以可迭代的:比如lists,strings,files…因为那些可迭代的目的你能够无限制的读取所以十一分有利易用,然则你不能够不把它们的值放到内部存款和储蓄器里,当它们有成都百货上千值时就会消耗太多的内部存款和储蓄器.

当一个引用传递给函数的时候,函数自动复制一份引用,这些函数里的引用和各市的引用没有半毛关系了.所以第3个例证里函数把引用指向了八个不可变对象,当函数再次回到的时候,外面包车型大巴引用没半毛感觉.而第二个例证就不等同了,函数内的引用指向的是可变对象,对它的操作就和固化了指针地址一样,在内部存款和储蓄器里进行修改.

Generators

生成器也是迭代器的一种,然则你不得不迭代它们3次.原因很简单,因为它们不是一体留存内部存款和储蓄器里,它们只在要调用的时候在内部存款和储蓄器里转变:

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4

生成器和迭代器的区分正是用()代替[],还有你无法用for i in
mygenerator第一遍调用生成器:首先计算0,然后会在内部存储器里丢掉0去计算1,直到总括完4.

假如还不晓得的话,那里有更好的表达: http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference

Yield

Yield的用法和关键字return大致,上边的函数将会再次来到3个生成器:

>>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() # 创建生成器
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

在那里那几个事例好像没什么用,不过当您的函数要回来一个不小的集聚并且你指望只读1次的话,那么它就卓殊的便民了.

要精通Yield你不能够不先明了当您调用函数的时候,函数里的代码并不曾运维.函数仅仅重回生成器对象,那正是它最神秘的地点:-)

接下来呢,每当for语句迭代生成器的时候你的代码才会运行.

近来,到了最难的一些:

当for语句第四回调用函数里重临的生成器对象,函数里的代码就起来运转,直到遭遇yield,然后会重回此次巡回的第③个再次回到值.所以下2遍调用也将运维3遍循环然后再次回到下3个值,直到没有值能够重临.

假诺函数运营并从未遭逢yeild语句就觉着生成器已经为空了.原因有大概是循环停止只怕尚未满意if/else之类的.

2
Python中的元类(metaclass)

Itertools你的好基友

itertools模块包涵了有些特有的函数能够操作可迭代对象.有没有想过复制多少个生成器?链接几个生成器?把嵌套列表里的值社团成3个列表?Map/Zip还不用创立另多个列表?

来吧import itertools

来三个事例?让大家看看4匹马竞赛有稍许个名次结果:

>>> horses = [1, 2, 3, 4]
>>> races = itertools.permutations(horses)
>>> print(races)
<itertools.permutations object at 0xb754f1dc>
>>> print(list(itertools.permutations(horses)))
[(1, 2, 3, 4),
 (1, 2, 4, 3),
 (1, 3, 2, 4),
 (1, 3, 4, 2),
 (1, 4, 2, 3),
 (1, 4, 3, 2),
 (2, 1, 3, 4),
 (2, 1, 4, 3),
 (2, 3, 1, 4),
 (2, 3, 4, 1),
 (2, 4, 1, 3),
 (2, 4, 3, 1),
 (3, 1, 2, 4),
 (3, 1, 4, 2),
 (3, 2, 1, 4),
 (3, 2, 4, 1),
 (3, 4, 1, 2),
 (3, 4, 2, 1),
 (4, 1, 2, 3),
 (4, 1, 3, 2),
 (4, 2, 1, 3),
 (4, 2, 3, 1),
 (4, 3, 1, 2),
 (4, 3, 2, 1)]

明亮迭代的里边机制

迭代是可迭代对象(对应iter()方法)和迭代器(对应next()方法)的二个进度.可迭代对象正是任何你能够迭代的靶子(废话啊).迭代器正是足以让您迭代可迭代对象的指标(有点绕口,意思即是其一意思)

本条可怜的不常用,可是像OSportageM那种复杂的结构仍旧会要求的,详情请看:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

*args and **kwargs

用*args和**kwargs只是为了有利于并没有强制行使它们.

当你不明确你的函数里即将传递多少参数时你能够用*args.例如,它能够传递任意数量的参数:

>>> 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允许你使用没有先行定义的参数名:

>>> 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 必须放在参数列表的后面。

3
@staticmethod和@classmethod

面向切面编制程序AOP和装饰器

这些AOP一听起来有点懵,同学面Ali的时候就被问懵了…

  • 装饰器正是把任何函数当参数的函数。
    装饰器是贰个很盛名的设计形式,平常被用来有切面须要的光景,较为经典的有插入日志、品质测试、事务处理等。装饰器是缓解那类难题的绝佳设计,有了装饰器,大家就能够抽离出大方函数中与函数效率本人非亲非故的一致代码并继续起用。归纳的讲,装饰器的法力正是为曾经存在的指标添加额外的效能。

本条难点相比大,推荐:
http://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python

中文:
http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html

  • 看2个简约的例子

# 字体变粗装饰器
def makebold(fn):
    # 装饰器将返回新的函数
    def wrapper():
        # 在之前或者之后插入新的代码
        return "<b>" + fn() + "</b>"
    return wrapper

# 斜体装饰器

def makeitalic(fn):
# 装饰器将回到新的函数
def wrapper():
# 在头里依然今后插入新的代码
return “<i>” + fn() + “</i>”
return wrapper

@makebold
@makeitalic
def say():
return “hello”

print say()

Python其实有1个章程,即静态方法(staticmethod),类形式(classmethod)和实例方法,如下:

输出: <b><i>hello</i></b>

deffoo(x):print”executing
foo(%s)”%(x)classA(object):deffoo(self,x):print”executing
foo(%s,%s)”%(self,x)@classmethoddefclass_foo(cls,x):print”executing
class_foo(%s,%s)”%(cls,x)@staticmethoddefstatic_foo(x):print”executing
static_foo(%s)”%xa=A()

这一定于

def say():
return “hello”
say = makebold(makeitalic(say))

print say()

此间先清楚下函数参数里面包车型客车self和cls.那几个self和cls是对类可能实例的绑定,对于一般的函数来说大家得以那样调用foo(x),那么些函数正是最常用的,它的劳作跟其他事物(类,实例)非亲非故.对于实例方法,大家领悟在类里每一次定义方法的时候都须要绑定这么些实例,正是foo(self,
x),为何要这么做呢?因为实例方法的调用离不开实例,大家必要把实例本身传给函数,调用的时候是那般的a.foo(x)(其实是foo(a,
x)).类方法同样,只可是它传递的是类而不是实例,A.class_foo(x).注意那里的self和cls能够轮换其余参数,但是python的预订是那俩,还是不要改的好.

输出: <b><i>hello</i></b>

- 用法:
    1. 传统用法是给外部的不可更改的库做扩展
    2. Django用装饰器管理缓存和试图的权限.
    3. Twisted用来修改异步函数的调用.
    4. etc.

# 鸭子类型
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。

又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.

鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。

# Python中重载
引自知乎:http://www.zhihu.com/question/20053359

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

  - 可变参数类型
  - 可变参数个数

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

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

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

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

# 新式类与旧式类
这个面试官问了,我说了老半天,不知道他问的真正意图是什么.

stackoverflow(http://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python)

这篇文章很好的介绍了新式类的特性: http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html

简单的说,新式类是在创建的时候继承内置object对象(或者是从内置类型,如list,dict等),而经典类是直
接声明的。使用dir()方法也可以看出新式类中定义很多新的属性和方法,而经典类好像就2个:

新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类是广度优先,旧式类是深度优先),<Python核心编程>里讲的也很多.

对于静态方法其实和日常的艺术一致,不须要对什么人举办绑定,唯一的区分是调用的时候须求动用a.static_foo(x)或者A.static_foo(x)来调用.

新式类

class C(object):
pass

\实例方法类措施静态方法

经典类

class B:
pass

# `__new__`和`__init__`的区别
这个`__new__`确实很少见到,先做了解吧.

`__new__`是一个静态方法,而`__init__`是一个实例方法.

`__new__`方法会返回一个创建的实例,而`__init__`什么都不返回.

只有在`__new__`返回一个cls的实例时后面的`__init__`才能被调用.

当创建一个新实例时调用`__new__`,初始化一个实例时用`__init__`.

stackoverflow(http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init)

ps: `__metaclass__`是创建类时起作用.所以我们可以分别使用`__metaclass__`,`__new__`和`__init__`来分别在类创建,实例创建和实例初始化的时候做一些小手脚.

# 单例模式
==这个绝对长考, 绝对要记住1~2个方法.==

所谓单例,是指一个类的实例从始至终只能被创建一次。

## 使用`__new__`方法

class Singleton(object):
def new(cls,args,kwargs):
if not hasattr(cls,’_inst’):
cls._inst=super(Singleton,cls).new(cls,
args,**kwargs)
return cls._inst
if name==’main‘:
class A(Singleton):
def init(self,s):
self.s=s
a=A(‘apple’)
b=A(‘banana’)
print id(a),a.s
print id(b),b.s

结果:

29922256 banana
29922256 banana

通过`__new__`方法,将类的实例在创建的时候绑定到类属性`_inst`上。如果`cls._inst`为None,说明类还未实例化,实例化并将实例绑定到`cls._inst`,以后每次实例化的时候都返回第一次实例化创建的实例。注意从Singleton派生子类的时候,不要重载`__new__`。
## 共享属性
有时候我们并不关心生成的实例是否具有同一id,而只关心其状态和行为方式。我们可以允许许多个实例被创建,但所有的实例都共享状态和行为方式:

class Borg(object):
_shared_state={}
def new(cls,args,kwargs):
obj=super(Borg,cls).new(cls,
args,**kwargs)
obj.dict=cls._shared_state
return obj

将所有实例的__dict__指向同一个字典,这样实例就共享相同的方法和属性。对任何实例的名字属性的设置,无论是在__init__中修改还是直接修改,所有的实例都会受到影响。不过实例的id是不同的。要保证类实例能共享属性,但不和子类共享,注意使用cls._shared_state,而不是Borg._shared_state。

因为实例是不同的id,所以每个实例都可以做字典的key:

if name==’main‘:
class Example(Borg):
pass
a=Example()
b=Example()
c=Example()
adict={}
j=0
for i in a,b,c:
adict[i]=j
j+=1
for i in a,b,c:
print adict[i]
结果:
0
1
2

如果这种行为不是你想要的,可以为Borg类添加__eq__和__hash__方法,使其更接近于单例模式的行为:

class Borg(object):
_shared_state={}
def new(cls,args,kwargs):
obj=super(Borg,cls).new(cls,
args,**kwargs)
obj.dict=cls._shared_state
return obj
def hash(self):
return 1
def eq(self,other):
try:
return self.dict is other.dict
except:
return False
if name==’main‘:
class Example(Borg):
pass
a=Example()
b=Example()
c=Example()
adict={}
j=0
for i in a,b,c:
adict[i]=j
j+=1
for i in a,b,c:
print adict[i]
结果:
2
2
2

所有的实例都能当一个key使用了。
## 装饰器版本

def singleton(cls, *args, *kw):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(
args, **kw)
return instances[cls]
return getinstance

@singleton
class MyClass:

## 基于元组
当你编写一个类的时候,某种机制会使用类名字,基类元组,类字典来创建一个类对象。新型类中这种机制默认为type,而且这种机制是可编程的,称为元类__metaclass__ 。

class Singleton(type):
def init(self,name,bases,class_dict):
super(Singleton,self).init(name,bases,class_dict)
self._instance=None
def call(self,args,kwargs):
if self._instance is None:
self._instance=super(Singleton,self).call(
args,**kwargs)
return self._instance
if name==’main‘:
class A(object):
metaclass=Singleton
a=A()
b=A()
print id(a),id(b)
结果:

34248016 34248016

id是相同的。

例子中我们构造了一个Singleton元类,并使用`__call__`方法使其能够模拟函数的行为。构造类A时,将其元类设为Singleton,那么创建类对象A时,行为发生如下:

`A=Singleton(name,bases,class_dict)`,A其实为Singleton类的一个实例。

创建A的实例时,`A()=Singleton(name,bases,class_dict)()=Singleton(name,bases,class_dict).__call__()`,这样就将A的所有实例都指向了A的属性`_instance`上,这种方法与方法1其实是相同的。
## import方法
作为python的模块是天然的单例模式

a = A()a.foo(x)a.class_foo(x)a.static_foo(x)

mysingleton.py

class My_Singleton(object):
def foo(self):
pass

my_singleton = My_Singleton()

A不可用A.class_foo(x)A.static_foo(x)

to use

from mysingleton import my_singleton

my_singleton.foo()

## python中的作用域
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。

当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:

本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)
## GIL线程全局锁

线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.

见Python 最难的问题http://www.oschina.net/translate/pythons-hardest-problem

==解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).==
## 协程
知乎被问到了,呵呵哒,跪了

简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.

Python里最常见的yield就是协程的思想!可以查看第九个问题.
## 闭包
闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。

当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点:

必须有一个内嵌函数
内嵌函数必须引用外部函数中的变量
外部函数的返回值必须是内嵌函数

感觉闭包还是有难度的,几句话是说不明白的,还是查查相关资料.

重点是函数运行后并不会被撤销,就像16题的instance字典一样,当函数运行完后,instance并不被销毁,而是继续留在内存空间里.这个功能类似类里的类变量,只不过迁移到了函数上.

闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样.
## lambda函数
其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关.

推荐: 知乎(http://www.zhihu.com/question/20125256 )
## python函数式编程
这个需要适当的了解一下吧,毕竟函数式编程在Python中也做了引用.

推荐: 酷壳(http://coolshell.cn/articles/10822.html )

python中函数式编程支持:

filter 函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。

a = [1,2,3,4,5,6,7]
b = filter(lambda x: x > 5, a)
print b
[6,7]

map函数是对一个序列的每个项依次执行函数,下面是对一个序列每个项都乘以2:

a = map(lambda x:x*2,[1,2,3])
list(a)
[2, 4, 6]

reduce函数是对一个序列的每个项迭代调用函数,下面是求3的阶乘:

reduce(lambda x,y:x*y,range(1,4))
6

## python里的拷贝
引用和copy(),deepcopy()的区别:
1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
2. copy.deepcopy 深拷贝 拷贝对象及其子对象
3. copy拷贝一个对象,但是对象的属性还是引用原来的,deepcopy拷贝一个对象,把对象里面的属性也做了拷贝,deepcopy之后完全是另一个对象了

import copy
a = [1, 2, 3, 4, [‘a’, ‘b’]] #固有对象

b = a #赋值,传对象的引用
c = copy.copy(a) #指标拷贝,浅拷贝,里面包车型大巴[]抑或引用原来的
d = copy.deepcopy(a) #指标拷贝,深拷贝, 全部的性子引用全体是新的

a.append(5) #修改对象a
a[4].append(‘c’) #修改对象a中的[‘a’, ‘b’]数组对象

print ‘a = ‘, a
print ‘b = ‘, b
print ‘c = ‘, c
print ‘d = ‘, d

输出结果:
a = [1, 2, 3, 4, [‘a’, ‘b’, ‘c’], 5]
b = [1, 2, 3, 4, [‘a’, ‘b’, ‘c’], 5]
c = [1, 2, 3, 4, [‘a’, ‘b’, ‘c’]]
d = [1, 2, 3, 4, [‘a’, ‘b’]]

## python 垃圾回收机制
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
### 引用计数
PyObject是每个对象必有的内容,其中`ob_refcnt`就是做为引用计数。当一个对象有新的引用时,它的`ob_refcnt`就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。

- 优点:

  - 简单
  - 实时性

- 缺点:

  - 维护引用计数消耗资源
  - 循环引用

## 标记\-清楚机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
## 分代技术
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。

Python默认定义了三代对象集合,索引数越大,对象存活时间越长。

举例:
  当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
# python的list
推荐: http://www.jianshu.com/p/J4U6rR (c语言的实现)
- 基本列表操作:
    - 删除  
    `del list[2]`
    - 分片赋值  
    `name[2:] = list('ar')`
- append

list.append(2)

- count

x = [[1,2],1,1,[2,1,[1,2]]]
x.count([1,2])
1
x.count(1)
2

- append
用于在列表末尾追加新的对象

lst = [1,2,3,4]
lst.append[4]
lst
[1,2,3,4]

- extend
可以在列表末尾一次性追加另一个序列的多个值

a = [1,2,3]
b = [4,5,6]
a.extend(b)
a
[1,2,3,4,5,6]

看起来与`a+b`操作很像, 但是extend方法修改了被扩展序列,而`a+b`则是返回新的序列

a = [1,2,3]
b = [4,5,6]
a+b
[1,2,3,4,5,6]
a
[1,2,3]

- index方法
查找元素在列表中的位置

L= [1,2,3,3]
[1,2,3,3]
L.index(3)
2

- insert方法

L= [1,2,3]
[1,2,3]
L.insert(0,10)
[10,1,2,3]

- pop方法

L= [1,2,3]
[1,2,3]
L.pop(0)
1
L
[2,3]

Perl的列表array里面pop只能弹出右侧的一个元素, 而这个可以弹出指定的index元素
有返回值, 返回值是弹出的元素, 并且修改了原列表
- remove方法
移除列表中某个值的第一个匹配项

L= [1,2,3,3,4]
[1,2,3,3,4]
L.remove(3)
L
[1,2,3,4]

没有返回值,原位修改
- sort方法
sort方法用于在原位置对列表进行排序。

L= [1,2,3,5,4]
L.sort()
L
[1,2,3,4,5]

- reverse方法

L= [1,2,3,3,4]
[1,2,3,3,4]
L.reverse()
L
[4,3,3,2,1]

- sort 与sorted()的关系
- 相同:
    - 都是排序
    - 都支持key, reverse参数, 其中key的话可以实现高级排序
- 不同
    -  sort只对list起作用, 而sorted是全局函数,对任何可迭代的序列均可以使用
    -  sort是原位修改,而sorted()会返回新的列表

详情请看( https://github.com/qiwsir/algorithm/blob/master/python_sort.md )

# python的is
is是对比地址,==是对比值
# read, readline和readlines
- read 读取整个文件
- readline 读取下一行,使用生成器方法
- readlines 读取整个文件到一个迭代器以供我们遍历

# python2和3的区别
推荐:《Python 2.7.x 和 3.x 版本的重要区别》http://python.jobbole.com/80006/
# 操作系统
## select,poll和epoll
其实所有的I/O都是轮询的方法,只不过实现的层面不同罢了.

这个问题可能有点深入了,但相信能回答出这个问题是对I/O多路复用有很好的了解了.其中tornado使用的就是epoll的.

selec,poll和epoll区别总结(http://www.cnblogs.com/Anker/p/3265058.html )

基本上select有3个缺点:

  - 连接数受限
  - 查找配对速度慢
  - 数据由内核拷贝到用户态

poll改善了第一个缺点

epoll改了三个缺点.

关于epoll的: http://www.cnblogs.com/my_life/articles/3968782.html
## 调度算法
1. 先来先服务(FCFS, First Come First Serve)
2. 短作业优先(SJF, Shortest Job First)
3. 最高优先权调度(Priority Scheduling)
4. 时间片轮转(RR, Round Robin)
5. 多级反馈队列调度(multilevel feedback queue
6. scheduling)

- 实时调度算法:

1. 最早截至时间优先 EDF
2. 最低松弛度优先 LLF

## 死锁
- 原因:

1. 竞争资源
2. 程序推进顺序不当

- 必要条件:

1. 互斥条件
2. 请求和保持条件
3. 不剥夺条件
4. 环路等待条件

- 处理死锁基本方法:

1. 预防死锁(摒弃除1以外的条件)
2. 避免死锁(银行家算法)
3. 检测死锁(资源分配图)
4. 解除死锁
    1. 剥夺资源
    2. 撤销进程

## 程序编译与链接
推荐: http://www.ruanyifeng.com/blog/2014/11/compiler.html

Bulid过程可以分解为4个步骤:预处理(Prepressing), 编译(Compilation)、汇编(Assembly)、链接(Linking)

以c语言为例:

- 预处理

预编译过程主要处理那些源文件中的以“#”开始的预编译指令,主要处理规则有:

将所有的“#define”删除,并展开所用的宏定义
处理所有条件预编译指令,比如“#if”、“#ifdef”、 “#elif”、“#endif”
处理“#include”预编译指令,将被包含的文件插入到该编译指令的位置,注:此过程是递归进行的
删除所有注释
添加行号和文件名标识,以便于编译时编译器产生调试用的行号信息以及用于编译时产生编译错误或警告时可显示行号
保留所有的#pragma编译器指令。

- 编译

编译过程就是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生成相应的汇编代码文件。这个过程是整个程序构建的核心部分。

- 汇编

汇编器是将汇编代码转化成机器可以执行的指令,每一条汇编语句几乎都是一条机器指令。经过编译、链接、汇编输出的文件成为目标文件(Object File)

- 链接

链接的主要内容就是把各个模块之间相互引用的部分处理好,使各个模块可以正确的拼接。
链接的主要过程包块 地址和空间的分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等步骤。

- 静态链接和动态链接

静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来
静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库

动态链接方法:使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这种方式使程序初始化时间较短,但运行期间的性能比不上静态链接的程序

- 虚拟内存技术

虚拟存储器是值具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储系统.

- 分页和分段

分页: 用户程序的地址空间被划分成若干固定大小的区域,称为“页”,相应地,内存空间分成若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配。

分段: 将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息。存储分配时,以段为单位,段与段在内存中可以不相邻接,也实现了离散分配。

分页与分段的主要区别

页是信息的物理单位,分页是为了实现非连续分配,以便解决内存碎片问题,或者说分页是由于系统管理的需要.段是信息的逻辑单位,它含有一组意义相对完整的信息,分段的目的是为了更好地实现共享,满足用户的需要.
页的大小固定,由系统确定,将逻辑地址划分为页号和页内地址是由机器硬件实现的.而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时根据信息的性质来划分.
分页的作业地址空间是一维的.分段的地址空间是二维的.

- 页面置换算法

最佳置换算法OPT:不可能实现
先进先出FIFO
最近最久未使用算法LRU:最近一段时间里最久没有使用过的页面予以置换.
clock算法

- 边沿触发和水平触发

边缘触发是指每当状态变化时发生一个 io 事件,条件触发是只要满足条件就发生一个 io 事件

# 数据库
## 事物
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
## 数据库索引
推荐: http://tech.meituan.com/mysql-index.html

MySQL索引背后的数据结构及算法原理(http://blog.jobbole.com/24006/)

聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理
## Redis原理
## 乐观锁和悲观锁
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作

乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
## MVCC
## MyISAM和InnoDB
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。

InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。

更加多关于那个题材:

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 的实例。

实例变量:

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

classTest(object):     
num_of_instance=0def__init__(self,name):self.name=name         
Test.num_of_instance+=1if__name__==’__main__’:printTest.num_of_instance#0t1=Test(‘jack’)printTest.num_of_instance#1t2=Test(‘lucy’)printt1.name
, t1.num_of_instance#jack 2printt2.name , t2.num_of_instance#lucy
2

补给的事例

classPerson:   
name=”aaa”p1=Person()p2=Person()p1.name=”bbb”printp1.name#bbbprintp2.name#aaaprintPerson.name#aaa

此地p1.name=”bbb”是实例调用了类变量,那实则和地点第一个难题同样,就是函数字传送参的标题,p1.name一初阶是指向的类变量name=”aaa”,可是在实例的功能域里把类变量的引用改变了,就改为了3个实例变量,self.name不再引用Person的类变量name了.

能够看看下边包车型大巴例证:

classPerson:   
name=[]p1=Person()p2=Person()p1.name.append(1)printp1.name#[1]printp2.name#[1]printPerson.name#[1]

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

5
Python自省

其一也是python彪悍的性情.

扪心自问正是面向对象的言语所写的程序在运作时,所能知道对象的类型.简单一句便是运营时亦可赢得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().

a=[1,2,3]b={‘a’:1,’b’:2,’c’:3}c=Trueprinttype(a),type(b),type(c)#
printisinstance(a,list)#True

6
字典推导式

想必您见过列表推导时,却并未见过字典推导式,在2.7中才进入的:

d={key: valuefor(key, value)initerable}

7
Python中单下划线和双下划线

>>>classMyClass():…def__init__(self):…self.__superprivate=”Hello”…self._semiprivate=”,
world!”…>>>mc=MyClass()>>>printmc.__superprivateTraceback
(most recent call last):  File””, line1,inAttributeError: myClass
instance has no
attribute’__superprivate’>>>printmc._semiprivate,
world!>>>printmc.__dict__{‘_MyClass__superprivate’:’Hello’,’_semiprivate’:’,
world!’}

__foo__:一种约定,Python内部的名字,用来分化其余用户自定义的命名,以免争辨,就是比如说__init__(),__del__(),__call__()这么些特种形式

_foo:一种约定,用来钦定变量私有.程序员用来钦命个人变量的一种方式.无法用from
module import * 导入,别的方面和国有一样访问;

__foo:那一个有确实的意思:解析器用_classname__foo来替代这些名字,以分别和其它类相同的命名,它不恐怕直接像公有成员平等随便访问,通过对象名._类名__xxx那样的点子能够访问.

详情见:http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python

或者: http://www.zhihu.com/question/19754941

8
字符串格式化:%和.format

.format在不少地点看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你或然会想上边包车型地铁代码不会有如何难题:

“hi there %s” % name

唯独,要是name恰好是(1,2,3),它将会抛出1个TypeError分外.为了保险它总是不错的,你必须那样做:

“hi there %s” % (name,)  # 提供1个单成分的数组而不是3个参数

而是有个别丑..format就从不那几个难题.你给的第3个难点也是这么,.format赏心悦目多了.

您为啥不要它?

不知底它(在读这几个从前)

为了和Python2.5匹配(譬如logging库提出使用%(issue
#4))

http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format

9
迭代器和生成器

本条是stackoverflow里python排行第1的难点,值得一看: http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python

那是中文版: http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html

此间有个有关生成器的创办问题面试官有考: 问: 将列表生成式中[]变动()
之后数据结构是不是变动? 答案:是,从列表变为生成器

>>>L=[x*xforxinrange(10)]>>>L[0,1,4,9,16,25,36,49,64,81]>>>g=(x*xforxinrange(10))>>>gat0x0000028F8B774200>

因此列表生成式,能够直接创建叁个列表。可是,受到内部存款和储蓄器限制,列表容积肯定是个其他。而且,成立1个涵盖百万成分的列表,不仅是挤占一点都不小的内部存储器空间,如:大家只需求拜访前面包车型地铁多少个要素,前面大部分要素所占的空中都以荒废的。因而,没有须求创制完整的列表(节省大量内存空间)。在Python中,大家得以接纳生成器:边循环,边总计的体制—>generator

10 *args and **kwargs

用*args和**kwargs只是为着便利并不曾强制行使它们.

当您不鲜明你的函数里即将传递多少参数时您能够用*args.例如,它能够传递任意数量的参数:

>>>defprint_everything(*args):forcount,
thinginenumerate(args):…print'{0}.{1}’.format(count,
thing)…>>>print_everything(‘apple’,’banana’,’cabbage’)0.
apple1. banana2. cabbage

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

>>>deftable_things(**kwargs):…forname,
valueinkwargs.items():…print'{0}={1}’.format(name,
value)…>>>table_things(apple=’fruit’,cabbage=’vegetable’)cabbage=vegetableapple=fruit

您也得以混着用.命名参数首先得到参数值然后具有的别的参数都传送给*args和**kwargs.命名参数在列表的最前端.例如:

def table_things(titlestring, **kwargs)

*args和**kwargs能够同时在函数的概念中,不过*args必须在**kwargs前面.

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

>>>defprint_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和装饰器

其一AOP一听起来有点懵,同学面Ali的时候就被问懵了…

装饰器是叁个很盛名的设计格局,常常被用于有切面须要的情景,较为经典的有插入日志、品质测试、事务处理等。装饰器是解决那类难题的绝佳设计,有了装饰器,大家就足以抽离出大方函数中与函数功用本人非亲非故的平等代码并连续起用。归纳的讲,装饰器的职能正是为已经存在的指标添加额外的功能。

本条题材相比较大,推荐: http://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python

中文: http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html

12
鸭子类型

“当见到1头鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么那只鸟就能够被称呼鸭子。”

大家并不关切对象是什么样品种,到底是或不是鸭子,只关心行为。

例如在python中,有成千上万file-like的事物,比如StringIO,GzipFile,socket。它们有很多同等的格局,大家把它们当做文件使用。

又比如list.extend()方法中,我们并不关切它的参数是或不是list,只要它是可迭代的,所以它的参数能够是list/tuple/dict/字符串/生成器等.

鸭子类型在动态语言中平时利用,十一分灵活,使得python不想java那样专门去弄第一次全国代表大会堆的设计方式。

13
Python中重载

引自网易:http://www.zhihu.com/question/20053359

函数重载首即使为了消除四个难点。

可变参数类型。

可变参数个数。

此外,二个主导的安顿性原则是,仅仅当三个函数除了参数类型和参数个数分裂以外,其功能是完全相同的,此时才使用函数重载,假若五个函数的职能实在不如,那么不应该利用重载,而应当利用贰个名字不相同的函数。

好啊,那么对于情状 1 ,函数功效雷同,可是参数类型不一致,python
怎么样处理?答案是素有不需求处理,因为 python
能够承受任何项目的参数,假若函数的功效雷同,那么差异的参数类型在 python
中很恐怕是同样的代码,没有供给做成多少个例外函数。

那正是说对于情形 2 ,函数功用雷同,但参数个数不一样,python
怎么着处理?大家精晓,答案就是缺省参数。对那几个不够的参数设定为缺省参数即可化解难题。因为你要是函数成效雷同,那么那一个不够的参数毕竟是须要用的。

好了,鉴于境况 1 跟 情形 2 都有了消除方案,python
自然就不需求函数重载了。

14
新式类和旧式类

本条面试官问了,笔者说了老半天,不明了她问的实在意图是什么.

stackoverflow

那篇作品很好的牵线了新式类的特点: http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html

风行类很早在2.2就应运而生了,所以旧式类完全是匹配的题材,Python3里的类全部都是新式类.这里有两个MRO难题能够通晓下(新式类是广度优先,旧式类是深浅优先),里讲的也很多.

二个旧式类的纵深优先的事例

classA():deffoo1(self):print”A”classB(A):deffoo2(self):passclassC(A):deffoo1(self):print”C”classD(B,C):passd=D()d.foo1()#A

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

15 __new__和__init__的区别

这个__new__真正很少见到,先做询问吧.

__new__是多个静态方法,而__init__是八个实例方法.

__new__方法会再次来到贰个创办的实例,而__init__什么都不再次来到.

只有在__new__归来3个cls的实例时后边的__init__才能被调用.

当创设一个新实例时调用__new__,早先化3个实例时用__init__.

stackoverflow

ps: __metaclass__是创造类时起功用.所以大家得以分别选用__metaclass__,__new__和__init__来分别在类创造,实例创制和实例开首化的时候做一些小手脚.

16
单例方式


单例方式是一种常用的软件设计形式。在它的为主结构中只含有3个被叫做单例类的万分类。通过单例方式能够保障系统中1个类唯有3个实例而且该实例易于外界访问,从而有利于对实例个数的操纵并节约系统能源。如若希望在系统中某些类的指标只能存在五个,单例方式是最佳的缓解方案。

__new__()在__init__()此前被调用,用于转移实例对象。利用这些主意和类的属性的特色能够兑现设计方式的单例形式。单例情势是指创造唯一目的,单例形式设计的类只好实例 其一绝对常考啊.相对要铭记1~二个法子,当时面试官是让手写的.

1
使用__new__方法

classSingleton(object):def__new__(cls,*args,**kw):ifnothasattr(cls,’_instance’): 
         
orig=super(Singleton,cls)cls._instance=orig.__new__(cls,*args,**kw)returncls._instanceclassMyClass(Singleton): 
  a=1

2
共享属性

成立实例时把拥有实例的__dict__针对同二个字典,这样它们有着同等的本性和方法.

classBorg(object):    _state={}def__new__(cls,*args,**kw):     
  ob=super(Borg,cls).__new__(cls,*args,**kw)       
ob.__dict__=cls._statereturnobclassMyClass2(Borg):    a=1

3
装饰器版本

defsingleton(cls,*args,**kw):   
instances={}defgetinstance():ifclsnotininstances:           
instances[cls]=cls(*args,**kw)returninstances[cls]returngetinstance@singletonclassMyClass:…

4
import方法

用作python的模块是天赋的单例格局

#mysingleton.pyclassMy_Singleton(object):deffoo(self):passmy_singleton=My_Singleton()#to
usefrommysingletonimportmy_singletonmy_singleton.foo()

单例方式伯乐在线详细表达

17
Python中的功效域

Python 中,三个变量的作用域总是由在代码中被赋值的地点所主宰的。

当 Python 境遇3个变量的话他会遵照那样的顺序实行查找:

本地成效域(Local)→当前功用域被安放的本地功效域(Enclosing
locals)→全局/模块作用域(Global)→内置成效域(Built-in)

18
GIL线程全局锁

线程全局锁(Global Interpreter
Lock),即Python为了保证线程安全而利用的独立线程运营的范围,说白了正是二个核只辛亏同暂且间运转一个线程.对此io密集型职责,python的四线程起到功用,但对于cpu密集型职责,python的十二线程大约占不到任何优势,还有恐怕因为争夺能源而变慢。

见Python
最难的难点

解决办法正是多进度和下部的协程(协程也只是单CPU,但是能减小切换代价升高质量).

19
协程

新浪被问到了,呵呵哒,跪了

粗略点说协程是经过和线程的晋升版,进度和线程都面临着内核态和用户态的切换难题而消耗不可胜举切换时间,而协程正是用户自身决定切换的机会,不再供给陷入系统的木本态.

Python里最广泛的yield就是协程的思考!能够查阅第⑩个难点.

20
闭包

闭包(closure)是函数式编制程序的最主要的语法结构。闭包也是一种集体代码的组织,它一律拉长了代码的可另行使用性。

当2个内嵌函数引用其表面作成效域的变量,大家就会赢得3个闭包.
总括一下,创造三个闭包必须满意以下几点:

必须有3个内嵌函数

内嵌函数必须引用外部函数中的变量

外部函数的重临值必须是内嵌函数

感觉闭包依旧有难度的,几句话是说不亮堂的,还是印证相关资料.

重中之重是函数运转后并不会被撤回,如同16题的instance字典一样,当函数运营完后,instance并不被灭绝,而是继续留在内部存款和储蓄器空间里.这些功用看似类里的类变量,只可是迁移到了函数上.

闭包就像个空心球一样,你驾驭外面和当中,但你不亮堂中间是哪些样.

21
lambda函数

事实上就是三个匿名函数,为啥叫lambda?因为和前面包车型客车函数式编制程序有关.

推荐: 知乎

22
Python函数式编制程序

那么些必要杰出的摸底一下呢,究竟函数式编制程序在Python中也做了引用.

推荐: 酷壳

python中等高校函授数式编制程序帮助:

filter
函数的功能也就是过滤器。调用一个布尔函数bool_func来迭代遍历各样seq中的成分;重回二个使bool_seq重返值为true的成分的行列。

>>>a=[1,2,3,4,5,6,7]>>>b=filter(lambdax: x>5,
a)>>>printb>>>[6,7]

map函数是对三个系列的每一种项依次执行函数,下边是对一个行列各种项都乘以2:

>>>a=map(lambdax:x*2,[1,2,3])>>>list(a)[2,4,6]

reduce函数是对2个行列的每种项迭代调用函数,上面是求3的阶乘:

>>>reduce(lambdax,y:x*y,range(1,4))6

23
Python里的正片

引用和copy(),deepcopy()的区别

importcopya=[1,2,3,4,
[‘a’,’b’]]#固有对象b=a#赋值,传对象的引用c=copy.copy(a)#指标拷贝,浅拷贝d=copy.deepcopy(a)#目的拷贝,深拷贝a.append(5)#修改对象aa[4].append(‘c’)#修改对象a中的[‘a’,
‘b’]数组对象print’a =’, aprint’b =’, bprint’c =’, cprint’d =’,
d输出结果:a=[1,2,3,4, [‘a’,’b’,’c’],5]b=[1,2,3,4,
[‘a’,’b’,’c’],5]c=[1,2,3,4, [‘a’,’b’,’c’]]d=[1,2,3,4,
[‘a’,’b’]]

24
Python垃圾回收机制

Python GC首要使用引用计数(reference
counting)来跟踪和回收废。在引用计数的功底上,通过“标记-清除”(mark
and
sweep)消除容器对象恐怕产生的轮回引用难题,通过“分代回收”(generation
collection)以空间换时间的主意进步垃圾回收效能。

1
引用计数

PyObject是每一个对象必有的内容,当中ob_refcnt正是做为引用计数。当二个指标有新的引用时,它的ob_refcnt就会追加,当引用它的目的被删去,它的ob_refcnt就会减弱.引用计数为0时,该对象生命就终止了。

优点:

简单

实时性

缺点:

保证引用计数消功耗源

循环引用

2
标记-清除机制

基本思路是先按需分配,等到没有空闲内部存款和储蓄器的时候从寄存器和程序栈上的引用出发,遍历以目标为节点、以引用为边构成的图,把拥有可以访问到的对象打上标记,然后清扫二次内部存款和储蓄器空间,把全部没标记的靶子释放。

3
分代技术

分代回收的完全构思是:将系统中的全体内部存款和储蓄器块遵照其现有时间分开为分化的成团,每一个集合就改成三个“代”,垃圾收集频率随着“代”的现有时间的附加而减小,存活时间一般选择经过四遍垃圾回收来衡量。

Python暗中认可定义了三代对象集合,索引数越大,对象共处时间越长。

比方:
当有个别内部存款和储蓄器块M经过了三回垃圾收集的涤荡之后还存世时,大家就将内部存款和储蓄器块M划到1个集合A中去,而新分配的内部存款和储蓄器都分开到集合B中去。当废品收集起来工作时,超过50%状态都只对集合B实行垃圾回收,而对集合A进行垃圾回收要隔不短一段时间后才开展,那就使得垃圾收集体制亟待处理的内部存款和储蓄器少了,功能自然就做实了。在那么些进程中,集合B中的有些内部存款和储蓄器块由于现有时间长而会被撤换来集合A中,当然,集合A中其实也设有部分垃圾,那么些废品的回收会因为那种分代的建制而被延迟。

25
Python的List

推荐: http://www.jianshu.com/p/J4U6rR

26
Python的is

is是对照地址,==是对比值

27
read,readline和readlines

read 读取整个文件

readline 读取下一行,使用生成器方法

readlines 读取整个文件到2个迭代器以供大家遍历

28
Python2和3的区别

推荐:Python 2.7.x 与 Python 3.x
的根本差异

29 super
init

super() lets you avoid referring to the base class explicitly, which can
be nice. But the main advantage comes with multiple inheritance, where
all sorts of fun stuff can happen. See the standard docs on super if you
haven’t already.

Note that the syntax changed in Python 3.0: you can just say
super().__init__() instead of super(ChildB, self).__init__()
which IMO is quite a bit nicer.

http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods

Python2.7中的super方法浅见

30 range and
xrange

都在循环时利用,xrange内部存款和储蓄器性能更好。 for i in range(0, 20): for i in
xrange(0, 20): What is the difference between range and xrange functions
in Python 2.X? range creates a list, so if you do range(1, 10000000) it
creates a list in memory with 9999999 elements. xrange is a sequence
object that evaluates lazily.

http://stackoverflow.com/questions/94935/what-is-the-difference-between-range-and-xrange-functions-in-python-2-x

操作系统

1
select,poll和epoll

事实上有着的I/O都以轮询的不二法门,只不超过实际现的规模分歧罢了.

那么些题材恐怕有点长远了,但相信能回应出这几个难题是对I/O多路复用有很好的询问了.当中tornado使用的正是epoll的.

selec,poll和epoll区别计算

基本上select有3个缺点:

连接数受限

查找配对进程慢

多少由基本拷贝到用户态

poll革新了第二个缺陷

epoll改了多个缺点.

关于epoll的: http://www.cnblogs.com/my\_life/articles/3968782.html

2
调度算法

先来先服务(FCFS, First Come First Serve)

短作业优先(SJF, Shortest Job First)

参天优先权调度(Priority Scheduling)

岁月片轮转(中华VTucson, Round 罗布in)

洋洋洒洒反馈队列调度(multilevel feedback queue scheduling)

大规模的调度算法总结:http://www.jianshu.com/p/6edf8174c1eb

实时调度算法:

最早停止时间优先 EDF

最低松弛度优先 LLF

3
死锁

原因:

竞争能源

次第推进各样不当

供给条件:

互斥条件

请求和保全标准

不剥夺条件

环路等待条件

拍卖死锁基本措施:

提防死锁(屏弃除1以外的准绳)

防止死锁(银行家算法)

检查和测试死锁(财富分配图)

破除死锁

剥夺财富

裁撤进度

死锁概念处理政策详细介绍:https://wizardforcel.gitbooks.io/wangdaokaoyan-os/content/10.html

4
程序编写翻译与链接

推荐: http://www.ruanyifeng.com/blog/2014/11/compiler.html

Bulid进度可以解释为陆个步骤:预处理(Prepressing),
编写翻译(Compilation)、汇编(Assembly)、链接(Linking)

以c语言为例:

1
预处理

预编写翻译进度主要处理那个源文件中的以“#”起始的预编写翻译指令,主要处理规则有:

将兼具的“#define”删除,并举办所用的宏定义

拍卖全体标准预编写翻译指令,比如“#if”、“#ifdef”、 “#elif”、“#endif”

处理“#include”预编写翻译指令,将被含有的文本插入到该编写翻译指令的职分,注:此进程是递归进行的

除去全数注释

添加行号和文件名标识,以便于编写翻译时编写翻译器产生调节和测试用的行号新闻以及用于编写翻译时爆发编写翻译错误或警示时可展示行反革命号

保存全数的#pragma编写翻译器指令。

2
编译

编写翻译进度正是把预处理完的文本进行一多级的词法分析、语法分析、语义分析及优化后变卦对应的汇编代码文件。这一个进程是百分百程序营造的为主部分。

3
汇编

汇编器是将汇编代码转化成机器能够执行的下令,每一条汇编语句大约都是一条机器指令。经过编写翻译、链接、汇编输出的文件成为指标文件(Object
File)

4
链接

链接的显要内容正是把各类模块之间相互引用的一对处理好,使各样模块能够正确的拼接。
链接的第③进程包块 地址和空中的分红(Address and Storage
Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等手续。

5
静态链接和动态链接

静态链接方法:静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地点明确下来
静态库的链接能够采取静态链接,动态链接库也得以运用这种方法链接导入库

动态链接方法:使用那种措施的程序并不在一伊始就成功动态链接,而是直到真正调用动态库代码时,载入程序才总括(被调用的那有些)动态代码的逻辑地址,然后等到有个别时候,程序又须要调用此外某块动态代码时,载入程序又去总结这部分代码的逻辑地址,所以,这种格局使程序开头化时间较短,但运维时期的习性比不上静态链接的主次

6
虚拟内存技术

虚拟存款和储蓄器是指装有请求调入效用和交流作用,能从逻辑上对内部存款和储蓄器容积加以扩大的一种存款和储蓄系统.

柒分页和分支

分页:
用户程序的地址空间被划分成多少永恒大小的区域,称为“页”,相应地,内部存储器空间分成若干个物理块,页和块的大小相当于。可将用户程序的任一页放在内部存款和储蓄器的任一块中,达成了离散分配。

分层:
将用户程序地址空间分成若干个大小不等的段,每段能够定义一组相对完好的逻辑音讯。存款和储蓄分配时,以段为单位,段与段在内部存款和储蓄器中能够不相邻接,也促成了离散分配。

分页与分支的最首要分裂

页是新闻的物理单位,分页是为了贯彻非延续分配,以便化解内存碎片难题,或许说分页是由于系统一管理理的急需.段是消息的逻辑单位,它涵盖一组意义相对完整的音讯,分段的目标是为了更好地促成共享,满意用户的需求.

页的分寸固定,由系统鲜明,将逻辑地址划分为页号和页内地址是由机器硬件完结的.而段的尺寸却不定点,决定于用户所编写的主次,经常由编写翻译程序在对源程序实行编写翻译时根据音信的习性来划分.

分页的学业地址空间是一维的.分段的地点空间是二维的.

8
页面置换算法

最棒置换算法OPT:不恐怕完结

先进先出FIFO

近年来最久未利用算法LRU:近年来一段时间里最久没有利用过的页面予以置换.

clock算法

9
两旁触发和水准触发

边缘触发是指每当状态变化时发生三个 io
事件,条件触发是假诺满意条件就爆发2个 io 事件

数据库

1
事务

数据库事务(Database Transaction)
,是指作为单个逻辑工作单元执行的一多重操作,要么完全地履行,要么完全地不实施。
彻底领略数据库事务: http://www.hollischuang.com/archives/898

2
数据库索引

推荐: http://tech.meituan.com/mysql-index.html

MySQL索引背后的数据结构及算法原理

聚集索引,非聚集索引,B-Tree,B+Tree,最左前缀原理

3
Redis原理

Redis是什么?

是3个全然开源免费的key-value内部存款和储蓄器数据库

一般性被认为是1个数据结构服务器,首如果因为其负有充分的数据结构
strings、map、 list、sets、 sorted sets

Redis数据库


平时局限点来说,Redis也以消息队列的格局存在,作为内嵌的List存在,满意实时的高并发要求。在接纳缓存的时候,redis比memcached具有越多的优势,并且支持越来越多的数据类型,把redis当作2个中档存储系统,用来拍卖高并发的数据库操作

进程快:使用标准C写,全数数据都在内部存款和储蓄器中达成,读写速度分别完毕10万/20万

持久化:对数据的换代采纳Copy-on-write技术,可以异步地保存到磁盘上,首要有三种政策,一是依照时间,更新次数的快速照相(save
300 10 )二是依照语句追加情势(Append-only file,aof)

自动操作:对两样数据类型的操作都以全自动的,很安全

急忙的主–从复制,官方提供了3个数据,Slave在21秒即成功了对亚马逊(Amazon)网站10G
key set的复制。

Sharding技术:
很不难将数据分布到两个Redis实例中,数据库的恢弘是个固定的话题,在关系型数据库中,首假使以丰富硬件、以分区为主要技术情势的纵向扩充消除了成千成万的选取场景,但随着web2.0、移动网络、云计算等选择的兴起,那种扩展情势已经不太适合了,所以近来,像选拔主从配置、数据库复制格局的,Sharding那种技能把负载分布到几个特理节点上去的横向扩充格局用处更加多。

Redis缺点

是数据水库蓄水容量量受到物理内部存款和储蓄器的限制,无法用作海量数据的高品质读写,因而Redis适合的风貌首要局限在较小数据量的高品质操作和运算上。

Redis较难支撑在线扩大体积,在集群体积高达上限时在线扩大体积会变得很复杂。为防止这一难题,运转人士在系统上线时务必确定保证有丰富的空中,那对财富造成了极大的浪费。

4
乐观锁和悲观锁

想不开锁:假定会发出并发争辨,屏蔽一切大概违反数据完整性的操作

开朗锁:要是不会爆发并发争论,只在交付操作时检查是不是违背数据完整性。

乐观锁与悲观锁的求实不相同: http://www.cnblogs.com/Bob-FD/p/3352216.html

5
MVCC

​ 全称是Multi-Version Concurrent
Control,即多版本出现控制,在MVCC协议下,每一个读操作会看到三个一致性的snapshot,并且能够完结非阻塞的读。MVCC允许数据有所三个本子,这一个版本能够是时刻戳恐怕是大局递增的事体ID,在同一个时间点,分裂的政工看到的数量是例外的。

MySQL的innodb引擎是什么样促成MVCC的

innodb会为每一行添加五个字段,分别代表该行开创的本子删除的本子,填入的是事情的本子号,那几个版本号随着工作的成立不断递增。在repeated
read的隔开分离级别(事务的割裂级别请看那篇小说)下,具体各样数据库操作的贯彻:

select:满意以下多少个标准innodb会重临该行数据:

该行的创始版本号小于等于当前版本号,用于保险在select操作此前全体的操作已经推行落地。

该行的去除版本号大于当前版本大概为空。删除版本号大于当前版本意味着有3个并发事务将该行删除了。

insert:将新插入的行的创办版本号设置为当前系统的版本号。

delete:将要删除的行的去除版本号设置为方今系统的版本号。

update:不履行原地update,而是转换到insert +
delete。将旧行的删除版本号设置为当下版本号,并将新行insert同时设置创设版本号为近来版本号。

内部,写操作(insert、delete和update)执行时,供给将系统版本号递增。


由于旧数据并不着实的去除,所以必须对那几个数据开始展览清理,innodb会开启一个后台线程执行清理工科作,具体的平整是将去除版本号小于当前系统版本的行删除,那个历程叫做purge。

由此MVCC很好的落到实处了业务的隔断性,可以达到规定的标准repeated
read级别,要落实serializable还非得加锁。

参考:MVCC浅析

6
MyISAM和InnoDB

MyISAM
适合于部分必要大量查询的利用,但其对于有恢宏写操作并不是很好。甚至你只是要求update四个字段,整个表都会被锁起来,而其他进度,就终于读进程都爱莫能助操作直到读操作完毕。其它,MyISAM
对于 SELECT COUNT(*) 那类的乘除是超快无比的。

InnoDB 的趋势会是3个十分复杂的积存引擎,对于某个小的采用,它会比 MyISAM
还慢。他是它援救“行锁”
,于是在写操作比较多的时候,会更雅观。并且,他还支持越多的高等级应用,比如:事务。

mysql
数据库引擎: http://www.cnblogs.com/0201zcr/p/5296843.html MySQL存款和储蓄引擎--MyISAM与InnoDB差距: https://segmentfault.com/a/1190000008227211

网络

11遍握手

客户端通过向劳动器端发送三个SYN来创立1个积极性打开,作为一次握手的一有个别。客户端把那段连接的序号设定为随机数
A。

劳务器端应当为2个合法的SYN回送三个SYN/ACK。ACK 的确认码应为
A+1,SYN/ACK 包自己又有1个即兴序号 B。

末尾,客户端再发送2个ACK。当服务端受到那几个ACK的时候,就完事了三路握手,并跻身了连年创立状态。此时包序号被设定为接收的确认号
A+1,而响应则为 B+1。

三十二遍挥手

留意: 中断连接端能够是客户端,也能够是服务器端.
上边仅以客户端断开连接举例, 反之亦然.

客户端发送八个多少分段, 在这之中的 FIN 标记设置为1. 客户端进入 FIN-WAIT
状态. 该景况下客户端只接收数据, 不再发送数据.

服务器收到到含有 FIN = 1 的数据分段, 发送带有 ACK = 1 的盈余数量分段,
确认收到客户端发来的 FIN 消息.

服务器等到持有数据传输截至, 向客户端发送三个含有 FIN = 1 的数据分段,
并进入 CLOSE-WAIT 状态, 等待客户端发来含有 ACK = 1 的承认报文.

客户端收到服务器发来含有 FIN = 1 的报文, 重返 ACK = 1 的报文确认,
为了防备服务器端未收取必要重发, 进入 TIME-WAIT 状态.
服务器收到到报文后关门连接. 客户端等待 2MSL 后未收到回复,
则认为服务器成功关闭, 客户端关闭连接.

图解: http://blog.csdn.net/whuslei/article/details/6667471

3
ARP协议

地址解析协议(Address Resolution
Protocol),其基本功用为经过目的设备的IP地址,查询目的的MAC地址,以保险通讯的顺遂实行。它是IPv4网络层必不可少的商议,但是在IPv6中已不再适用,并被乡邻发现协议(NDP)所代表。

4
urllib和urllib2的区别

那个面试官确实问过,当时答的urllib2能够Post而urllib不能.

urllib提供urlencode方法用来GET查询字符串的发出,而urllib2没有。那是怎么urllib常和urllib2一起使用的缘由。

urllib2还行1个Request类的实例来安装U帕杰罗L请求的headers,urllib仅能够承受U本田UR-VL。那意味,你不可能假装你的User
Agent字符串等。

5
Post和Get

GET和POST有如何分歧?及为啥网上的半数以上答案都以错的 今日头条回答

get: RFC 2616 – Hypertext Transfer Protocol —
HTTP/1.1 post: RFC
2616 – Hypertext Transfer Protocol —
HTTP/1.1

6
Cookie和Session

CookieSession

仓库储存地方客户端服务器端

目标跟踪会话,也得以保留用户偏好设置恐怕封存用户名密码等跟踪会话

安全性不安全无恙

session技术是要利用到cookie的,之所以出现session技术,主假如为着安全。

7
apache和nginx的区别

nginx 相对 apache 的优点:

轻量级,同样起web 服务,比apache 占用更少的内部存款和储蓄器及能源

抗并发,nginx 处理请求是异步非阻塞的,帮助越来越多的出现连接,而apache
则是阻塞型的,在高并发下nginx 能保持低财富低消耗高品质

布局简洁

中度模块化的安排性,编写模块绝对不难

社区活泼

apache 相对nginx 的优点:

rewrite ,比nginx 的rewrite 强大

模块超多,基本想到的都足以找到

少bug ,nginx 的bug 相对较多

超稳定

8
网站用户密码保存

领悟保存

明文hash后保存,如md5

MD5+Salt格局,这几个salt能够自由

新浪使用了Bcrypy(好像)加密

9
HTTP和HTTPS

动静码定义

1xx 报告吸收接纳到请求,继续进程

2xx 打响步骤成功接到,被清楚,并被接受

3xx 重定向为了实现请求,必须利用尤其措施

4xx 客户端出错请求包罗错的相继或无法完结

5xx 服务器出错服务器不或许到位显明有效的呼吁

403: Forbidden 404: Not Found

HTTPS握手,对称加密,非对称加密,TLS/SSL,宝马X5SA

10
XSRF和XSS

CS奥迪Q3F(克罗丝-site request forgery)跨站请求伪造

XSS(克罗丝 Site Scripting)跨站脚本攻击

CS奇骏F重点在央求,XSS重点在本子

11 幂等
Idempotence

HTTP方法的幂等性是指叁回和多次呼吁某3个财富应该具有同等的副作用。(注意是副成效)

GET

DELETE方法用于删除能源,有副效用,但它应当满意幂等性。比如:DELETE

POST所对应的URAV4I并非成立的能源本身,而是财富的收信人。比如:POST

PUT所对应的U汉兰达I是要创设或更新的财富本身。比如:PUT

12
RESTful架构(SOAP,RPC)

推荐: http://www.ruanyifeng.com/blog/2011/09/restful.html

13
SOAP

SOAP(原为Simple Object Access
Protocol的首字母缩写,即简单对象访问协议)是换来数据的一种协议正式,使用在电脑网络Web服务(web
service)中,沟通带结构音信。SOAP为了简化网页服务器(Web
Server)从XML数据库中领取数据时,节省去格式化页面时间,以及分裂应用程序之间依据HTTP通讯协议,遵守XML格式执行资料调换,使其抽象于言语完结、平台和硬件。

14
RPC

GL450PC(Remote Procedure Call
Protocol)——远程进程调用协议,它是一种通过互连网从远程总括机程序上呼吁服务,而不需求驾驭底层互联网技术的说道。RAV4PC商谈如若有些传输协议的留存,如TCP或UDP,为通讯程序之间指点消息数量。在OSI互联网通讯模型中,奥德赛PC跨越了传输层和应用层。卡宴PC使得开发包括网络分布式多程序在内的应用程序特别简单。

总计:服务提供的两大流派.古板意义以艺术调用为导向通称大切诺基PC。为了集团SOA,若干厂商联合推出webservice,制定了wsdl接口定义,传输soap.当互连网时期,臃肿SOA被简化为http+xml/json.不过简化出现各类混乱。以财富为导向,任何操作无非是对能源的增删改查,于是统一的REST出现了.

前进的相继: 凯雷德PC -> SOAP -> RESTful

15
CGI和WSGI

CGI是通用网关接口,是连接web服务器和应用程序的接口,用户通过CGI来博取动态数据或文件等。
CGI程序是二个单身的次序,它可以用差不离拥有语言来写,包蕴perl,c,lua,python等等。

WSGI, Web Server Gateway
Interface,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的个中3个指标就是让用户能够用联合的言语(Python)编写前后端。

法定认证:PEP-3333

16
中间人攻击

在GFW里无独有偶的,呵呵.

中间人攻击(Man-in-the-middle
attack,平时缩写为MITM)是指攻击者与报纸发表的相互分别创立独立的沟通,并调换其所接收的数据,使通信的两端认为她们正在通过多少个私密的接连与对方间接对话,但实则整个会话都被攻击者完全控制。

17
c10k问题

所谓c10k难点,指的是服务器同时补助广大个客户端的难点,也便是concurrent
10 000 connection(那也是c10k这几个名字的原故)。
推荐: https://my.oschina.net/xianggao/blog/664275

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字段,3个服务器七个网站

长链接

文件断点续传

身份认证,状态管理,Cache缓存

HTTP请求8种方法介绍
HTTP/1.1协议中国共产党定义了8种HTTP请求方法,HTTP请求方法也被称呼“请求动作”,不一致的章程规定了分裂的操作钦点的能源格局。服务端也会依据不一样的伸手方法做差异的响应。

GET

GET请求会显示请求内定的能源。一般的话GET方法应该只用于数据的读取,而不应有用于会发生副作用的非幂等的操作中。

GET会办法请求钦命的页面音讯,并赶回响应中央,GET被认为是不安全的不二法门,因为GET方法会被互联网蜘蛛等任意的造访。

HEAD

HEAD方法与GET方法一致,都以向服务器发出钦命财富的伸手。不过,服务器在响应HEAD请求时不会回传能源的故事情节部分,即:响应中心。那样,我们能够不传输全体内容的意况下,就足以拿走服务器的响应头新闻。HEAD方法常被用于客户端查看服务器的质量。

POST

POST请求会
向钦命能源提交数据,请求服务器进行处理,如:表单数据交由、文件上传等,请求数据会被含有在请求体中。POST方法是非幂等的措施,因为这一个请求或然会创设新的能源或/和修改现有财富。

PUT

PUT请求会身向钦定能源职分上传其最新内容,PUT方法是幂等的点子。通过该方法客户端能够将钦赐财富的流行数据传送给服务器代替内定的能源的剧情。

DELETE

DELETE请求用于请求服务器删除所请求UQX56I(统一能源标识符,Uniform Resource
Identifier)所标识的能源。DELETE请求后钦定财富会被删除,DELETE方法也是幂等的。

CONNECT

CONNECT方法是HTTP/1.1协议预留的,能够将接连改为管道格局的代理服务器。常常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通讯。

OPTIONS

OPTIONS请求与HEAD类似,一般也是用于客户端查看服务器的属性。
那些方法会请求服务器重临该能源所帮助的富有HTTP请求方法,该办法会用’*’来取代财富名称,向服务器发送OPTIONS请求,能够测试服务器成效是或不是正规。JavaScript的XMLHttpRequest对象开始展览CO福特ExplorerS跨域财富共享时,正是应用OPTIONS方法发送嗅探请求,以咬定是不是有对点名能源的造访权限。
允许

TRACE

TRACE请求服务器回显其接到的伏乞音讯,该措施紧要用于HTTP请求的测试或确诊。

HTTP/1.1事后扩展的措施

在HTTP/1.1业内制订之后,又陆续扩大了部分办法。当中使用中较多的是 PATCH
方法:

PATCH

PATCH方法出现的较晚,它在二〇〇九年的奥德赛FC
5789专业中被定义。PATCH请求与PUT请求类似,同样用于能源的更新。二者有以下两点差异:

但PATCH一般用来财富的一部分更新,而PUT一般用于财富的一体化创新。
当财富不设有时,PATCH会创设多个新的财富,而PUT只会对已在财富开始展览翻新。

21
Ajax

AJAX,Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),
是与在不另行加载整个页面包车型大巴境况下,与服务器交流数据并立异部分网页的技艺。

*NIX

unix进度间通信格局(IPC)

管道(Pipe):管道可用于拥有亲缘关系进度间的通讯,允许3个历程和另多个与它有伙同祖先的进程之间展开通讯。

取名管道(named
pipe):命名管道战胜了管道没盛名字的限定,因而,除拥有管道所享有的功力外,它还同意无亲缘关系进度间的通讯。命名管道在文件系统中有对应的文书名。命名管道通过命令mkfifo或系统调用mkfifo来创设。

信号(Signal):信号是相比复杂的通讯方式,用于文告接受进度有某种事件时有产生,除了用于进程间通讯外,进度还足以发送信号给进度本身;linux除了协理Unix早期信号语义函数sigal外,还接济语义符合Posix.1标准的信号函数sigaction(实际上,该函数是依照BSD的,BSD为了落到实处可相信信号机制,又能够联合对外接口,用sigaction函数重新完成了signal函数)。

音信(Message)队列:音信队列是音信的链接表,包涵Posix音信队列system
V音讯队列。有充足权限的历程能够向队列中添加音信,被授予读权限的长河则足以读走队列中的新闻。新闻队列克服了信号承载音讯量少,管道只好承载无格式字节流以及缓冲区大大小小受限等缺

共享内部存款和储蓄器:使得八个经过能够访问同一块内存空间,是最快的可用IPC形式。是针对性任何通讯机制运作功用较低而布署的。往往与其余通讯机制,如信号量结合使用,来实现进程间的联合及互斥。

内部存款和储蓄器映射(mapped
memory):内部存款和储蓄器映射允许别的七个经过间通讯,每八个用到该机制的历程经过把叁个共享的文件映射到温馨的长河地址空间来促成它。

信号量(semaphore):重要用作进度间以及同样进度不一致线程之间的联合手段。

套接口(Socket):更为相似的长河间通讯机制,可用以分裂机器之间的进程间通讯。起首是由Unix系统的BSD分支开发出来的,但近来相像能够移植到其它类Unix系统上:Linux和System
V的变种都援救套接字。

数据结构

1
红黑树

红黑树与AVL的可比:

AVL是严刻平衡树,因而在扩大依旧去除节点的时候,依据区别情状,旋转的次数比红黑树要多;

红黑是用非严加的平衡来换取增加和删除节点时候转动次数的暴跌;

故而简单说,倘诺你的施用中,搜索的次数远远超乎插入和删除,那么采纳AVL,如若搜索,插入删除次数差不多差不离,应该采取RB。

红黑树详解: https://xieguanglei.github.io/blog/post/red-black-tree.html

教您透彻掌握红黑树: https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.01.md

编程题

1
台阶难点/斐波那契

一头青蛙一遍可以跳上1级台阶,也能够跳上2级。求该青蛙跳上三个n级的阶梯总共有多少种跳法。

fib=lambdan: nifn<=2elsefib(n-1)+fib(n-2)

其次种回忆方法

defmemo(func):    cache={}defwrap(*args):ifargsnotincache:           
cache[args]=func(*args)returncache[args]returnwrap@memodeffib(i):ifi<2:return1returnfib(i-1)+fib(i-2)

其三种方式

deffib(n):    a, b=0,1for_inxrange(n):        a, b=b, a+breturnb

2
变态台阶难点

1头青蛙二回能够跳上1级台阶,也足以跳上2级……它也能够跳上n级。求该青蛙跳上2个n级的阶梯总共某些许种跳法。

fib=lambdan: nifn<2else2*fib(n-1)

3
矩形覆盖

作者们能够用2*1的小矩形横着恐怕竖着去掩盖更大的矩形。请问用n个2*1的小矩形无重叠地掩盖一个2*n的大矩形,总共有个别许种艺术?

第2*n个矩形的遮盖措施等于第1*(n-1)加上第2*(n-2)的方法。

f=lambdan:1ifn<2elsef(n-1)+f(n-2)

4
杨氏矩阵查找

在1个m行n列二维数组中,每一行都根据从左到右递增的顺序排序,每一列都遵循从上到下递增的相继排序。请完毕2个函数,输入这样的三个二维数组和3个平头,判断数组中是或不是包括该整数。

使用Step-wise线性搜索。

defget_value(l,r,c):returnl[r][c]deffind(l,x):   
m=len(l)-1n=len(l[0])-1r=0c=nwhilec>=0andr<=m:       
value=get_value(l, r, c)ifvalue==x:returnTrueelifvalue>x:           
c=c-1elifvalue

5
去除列表中的重复元素

用集合

list(set(l))

用字典

l1=[‘b’,’c’,’d’,’b’,’c’,’a’,’a’]l2={}.fromkeys(l1).keys()printl2

用字典并维持顺序

l1=[‘b’,’c’,’d’,’b’,’c’,’a’,’a’]l2=list(set(l1))l2.sort(key=l1.index)printl2

列表推导式

l1=[‘b’,’c’,’d’,’b’,’c’,’a’,’a’]l2=[][l2.append(i)foriinl1ifnotiinl2]

sorted排序并且用列表推导式.

l = [‘b’,’c’,’d’,’b’,’c’,’a’,’a’] [single.append(i) for i in
sorted(l) if i not in single] print single

6
链表成对沟通

1->2->3->4转换成2->1->4->3.

classListNode:def__init__(self,x):self.val=xself.next=NoneclassSolution:#@param
a ListNode#@return a
ListNodedefswapPairs(self,head):ifhead!=Noneandhead.next!=None:next=head.next 
         
head.next=self.swapPairs(next.next)next.next=headreturnnextreturnhead

7
创制字典的法子

1
直接创立

dict={‘name’:’earth’,’port’:’80’}

2
工厂方法

items=[(‘name’,’earth’),(‘port’,’80’)]dict2=dict(items)dict1=dict(([‘name’,’earth’],[‘port’,’80’]))

3
fromkeys()方法

dict1={}.fromkeys((‘x’,’y’),-1)dict={‘x’:-1,’y’:-1}dict2={}.fromkeys((‘x’,’y’))dict2={‘x’:None,’y’:None}

8
合并四个静止列表

腾讯网远程面试供给编制程序

尾递归

def_recursion_merge_sort2(l1,l2,tmp):iflen(l1)==0orlen(l2)==0:       
tmp.extend(l1)        tmp.extend(l2)returntmpelse:ifl1[0]

循环算法

思路:

概念一个新的空驶列车表

正如多个列表的第三个要素

小的就插入到新列表里

把曾经插入新列表的成分从旧列表删除

以至八个旧列表有2个为空

再把旧列表加到新列表后边

def loop_merge_sort(l1, l2):

    tmp = []

    while len(l1) > 0 and len(l2) > 0:

        if l1[0] < l2[0]:

            tmp.append(l1[0])

            del l1[0]

        else:

            tmp.append(l2[0])

            del l2[0]

    tmp.extend(l1)

    tmp.extend(l2)

    return tmp

pop弹出

a=[1,2,3,7]b=[3,4,5]defmerge_sortedlist(a,b):   
c=[]whileaandb:ifa[0]>=b[0]:           
c.append(b.pop(0))else:            c.append(a.pop(0))whilea:       
c.append(a.pop(0))whileb:       
c.append(b.pop(0))returncprintmerge_sortedlist(a,b)

9
交叉链表求交点

实际想想可以遵从从尾开端相比八个链表,假若相交,则从尾初叶必然一致,只要从尾开端相比,直至不均等的地方即为交叉点,如图所示

威尼斯人线上娱乐 3

#使用a,b三个list来效仿链表,能够看出交叉点是
7那么些节点a=[1,2,3,7,9,1,5]b=[4,5,7,9,1,5]foriinrange(1,min(len(a),len(b))):ifi==1and(a[-1]!=b[-1]):print”No”breakelse:ifa[-i]!=b[-i]:print”交叉节点:”,a[-i+1]breakelse:pass

其它一种相比较专业的形式,构造链表类

classListNode:def__init__(self,x):self.val=xself.next=Nonedefnode(l1,l2): 
  length1, lenth2=0,0#求多少个链表长度whilel1.next:        l1=l1.next   
    length1+=1whilel2.next:        l2=l2.next       
length2+=1#长的链表先走iflength1>lenth2:for_inrange(length1-length2): 
          l1=l1.nextelse:for_inrange(length2-length1):           
l2=l2.nextwhilel1andl2:ifl1.next==l2.next:returnl1.nextelse:           
l1=l1.next            l2=l2.next

修改了弹指间:

#coding:utf-8classListNode:def__init__(self,x):self.val=xself.next=Nonedefnode(l1,l2): 
  length1, length2=0,0#求四个链表长度whilel1.next:       
l1=l1.next#尾节点length1+=1whilel2.next:       
l2=l2.next#尾节点length2+=1#万一相交ifl1.next==l2.next:#长的链表先走iflength1>length2:for_inrange(length1-length2): 
             
l1=l1.nextreturnl1#归来交点else:for_inrange(length2-length1):         
      l2=l2.nextreturnl2#回来交点#即使不相交else:return

思路: http://humaoli.blog.163.com/blog/static/13346651820141125102125995/

10
二分查找

#coding:utf-8defbinary_search(list,item):   
low=0high=len(list)-1whilelow<=high:       
mid=(low+high)/2guess=list[mid]ifguess>item:           
high=mid-1elifguess

参考: http://blog.csdn.net/u013205877/article/details/76411718

11
快排

#coding:utf-8defquicksort(list):iflen(list)<2:returnlistelse:       
midpivot=list[0]       
lessbeforemidpivot=[iforiinlist[1:]ifi<=midpivot]       
biggerafterpivot=[iforiinlist[1:]ifi>midpivot]       
finallylist=quicksort(lessbeforemidpivot)+[midpivot]+quicksort(biggerafterpivot)returnfinallylistprintquicksort([2,4,6,7,1,2,5])

更加多排序难点凸现:数据结构与算法-排序篇-Python描述

12
找零难题

#coding:utf-8#values是硬币的面值values = [ 25, 21, 10, 5,
1]#valuesCounts  钱币对应的项目数#money  找出来的总钱数#coinsUsed 
对应于近日货币总数i所使用的硬币数目defcoinChange(values,valuesCounts,money,coinsUsed):#遍历出从1到money全数的钱数只怕forcentsinrange(1,money+1): 
     
minCoins=cents#把富有的硬币面值遍历出来和钱数做比较forkindinrange(0,valuesCounts):if(values[kind]<=cents): 
              temp=coinsUsed[cents-values[kind]]+1if(temp

思路: http://blog.csdn.net/wdxin1322/article/details/9501163

方法: http://www.cnblogs.com/ChenxofHit/archive/2011/03/18/1988431.html

13
广度遍历和纵深遍历二叉树

给定一个数组,营造二叉树,并且按层次打字与印刷这一个二叉树

14
二叉树节点

classNode(object):def__init__(self,data,left=None,right=None):self.data=dataself.left=leftself.right=righttree=Node(1,
Node(3, Node(7, Node(0)), Node(6)), Node(2, Node(5), Node(4)))

15
层次遍历

deflookup(root):    stack=[root]whilestack:       
current=stack.pop(0)printcurrent.dataifcurrent.left:           
stack.append(current.left)ifcurrent.right:           
stack.append(current.right)

16
深度遍历

defdeep(root):ifnotroot:returnprintroot.data    deep(root.left)   
deep(root.right)if__name__==’__main__’:    lookup(tree)   
deep(tree)

17
前中后序遍历

深度遍历改变各类就OK了

#coding:utf-8#二叉树的遍历#大约的二叉树节点类classNode(object):def__init__(self,value,left,right):self.value=valueself.left=leftself.right=right#中序遍历:遍历左子树,访问当前节点,遍历右子树defmid_travelsal(root):ifroot.leftisNone: 
     
mid_travelsal(root.left)#做客当前节点print(root.value)ifroot.rightisnotNone: 
     
mid_travelsal(root.right)#前序遍历:访问当前节点,遍历左子树,遍历右子树defpre_travelsal(root):print(root.value)ifroot.leftisnotNone: 
      pre_travelsal(root.left)ifroot.rightisnotNone:       
pre_travelsal(root.right)#持续遍历:遍历左子树,遍历右子树,访问当前节点defpost_trvelsal(root):ifroot.leftisnotNone: 
      post_trvelsal(root.left)ifroot.rightisnotNone:       
post_trvelsal(root.right)print(root.value)

18
求最大树深

defmaxDepth(root):ifnotroot:return0returnmax(maxDepth(root.left),
maxDepth(root.right))+1

19
求两棵树是或不是同样

defisSameTree(p,q):ifp==Noneandq==None:returnTrueelifpandq
:returnp.val==q.valandisSameTree(p.left,q.left)andisSameTree(p.right,q.right)else:returnFalse

20
前序中序求后序

推荐: http://blog.csdn.net/hinyunsin/article/details/6315502

defrebuild(pre,center):ifnotpre:returncur=Node(pre[0])   
index=center.index(pre[0])    cur.left=rebuild(pre[1:index+1],
center[:index])    cur.right=rebuild(pre[index+1:],
center[index+1:])returncurdefdeep(root):ifnotroot:returndeep(root.left) 
  deep(root.right)printroot.data

21
单链表逆置

classNode(object):def__init__(self,data=None,next=None):self.data=dataself.next=nextlink=Node(1,
Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8,
Node(9)))))))))defrev(link):    pre=link    cur=link.next   
pre.next=Nonewhilecur:        tmp=cur.next        cur.next=pre       
pre=cur        cur=tmpreturnpreroot=rev(link)whileroot:printroot.data   
root=root.next

思路: http://blog.csdn.net/feliciafay/article/details/6841115

方法: http://www.xuebuyuan.com/2066385.html?mobile=1

22
多个字符串是或不是是变位词

classAnagram:”””    @:param s1: The first string    @:param s2: The
second string    @:return true or false”””defSolution1(s1,s2):       
alist=list(s2)        pos1=0stillOK=Truewhilepos1

23
动态规划难点

可参考:动态规划(DP)的盘整-Python描述


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图