Python語(yǔ)言特性
1 Python的函數(shù)參數(shù)傳遞
看兩個(gè)如下例子赋荆,分析運(yùn)行結(jié)果:
代碼一:
a = 1
def fun(a):
a = 2
fun(a)
print(a) # 1
代碼二:
a = []
def fun(a):
a.append(1)
fun(a)
print(a) # [1]
所有的變量都可以理解是內(nèi)存中一個(gè)對(duì)象的“引用”,或者摄职,也可以看似c中void*的感覺(jué)。
這里記住的是類(lèi)型是屬于對(duì)象的幼苛,而不是變量秦效。而對(duì)象有兩種,“可更改”(mutable)與“不可更改”(immutable)對(duì)象铝条。在python中,strings, tuples, 和numbers是不可更改的對(duì)象杉辙,而list,dict等則是可以修改的對(duì)象模捂。(這就是這個(gè)問(wèn)題的重點(diǎn))
當(dāng)一個(gè)引用傳遞給函數(shù)的時(shí)候,函數(shù)自動(dòng)復(fù)制一份引用,這個(gè)函數(shù)里的引用和外邊的引用沒(méi)有半毛關(guān)系了.所以第一個(gè)例子里函數(shù)把引用指向了一個(gè)不可變對(duì)象,當(dāng)函數(shù)返回的時(shí)候,外面的引用沒(méi)半毛感覺(jué).而第二個(gè)例子就不一樣了,函數(shù)內(nèi)的引用指向的是可變對(duì)象,對(duì)它的操作就和定位了指針地址一樣,在內(nèi)存里進(jìn)行修改.
2 Python中的元類(lèi)(metaclass)
元類(lèi)就是用來(lái)創(chuàng)建類(lèi)的“東西”。你創(chuàng)建類(lèi)就是為了創(chuàng)建類(lèi)的實(shí)例對(duì)象,但是我們已經(jīng)學(xué)習(xí)到了Python中的類(lèi)也是對(duì)象狂男。好吧综看,元類(lèi)就是用來(lái)創(chuàng)建這些類(lèi)(對(duì)象)的,元類(lèi)就是類(lèi)的類(lèi)
這個(gè)非常的不常用,詳情請(qǐng)看:《深刻理解Python中的元類(lèi)(metaclass)》
3 @staticmethod和@classmethod
Python其實(shí)有3個(gè)方法,即靜態(tài)方法(staticmethod),類(lèi)方法(classmethod)和實(shí)例方法,如下:
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()
這里先理解下函數(shù)參數(shù)里面的self和cls.這個(gè)self和cls是對(duì)類(lèi)或者實(shí)例的綁定.對(duì)于實(shí)例方法,我們知道在類(lèi)里每次定義方法的時(shí)候都需要綁定這個(gè)實(shí)例,就是foo(self, x),為什么要這么做呢?因?yàn)閷?shí)例方法的調(diào)用離不開(kāi)實(shí)例,我們需要把實(shí)例自己傳給函數(shù),調(diào)用的時(shí)候是這樣的a.foo(x)(其實(shí)是foo(a, x)).類(lèi)方法一樣,只不過(guò)它傳遞的是類(lèi)而不是實(shí)例,A.class_foo(x).注意這里的self和cls可以替換別的參數(shù),但是python的約定是這倆,還是不要改的好.
對(duì)于靜態(tài)方法其實(shí)和普通的方法一樣,不需要對(duì)誰(shuí)進(jìn)行綁定,唯一的區(qū)別是調(diào)用的時(shí)候需要使用a.static_foo(x)或者A.static_foo(x)來(lái)調(diào)用.
\
實(shí)例方法
類(lèi)方法
靜態(tài)方法
a = A()
a.foo(x)
a.class_foo(x)
a.static_foo(x)
A
不可用
A.class_foo(x)
A.static_foo(x)
4 類(lèi)變量和實(shí)例變量
class Person:
name="aaa"
p1=Person()
p2=Person()
p1.name="bbb"
print(p1.name)# bbb
print(p2.name)# aaa
print(Person.name)# aaa
類(lèi)變量就是供類(lèi)使用的變量,實(shí)例變量就是供實(shí)例使用的.
這里p1.name="bbb"是實(shí)例調(diào)用了類(lèi)變量,這其實(shí)和上面第一個(gè)問(wèn)題一樣,就是函數(shù)傳參的問(wèn)題,p1.name一開(kāi)始是指向的類(lèi)變量name="aaa",但是在實(shí)例的作用域里把類(lèi)變量的引用改變了,就變成了一個(gè)實(shí)例變量,self.name不再引用Person的類(lèi)變量name了.
可以看看下面的例子:
class Person:
name=[]
p1=Person()
p2=Person()
p1.name.append(1)
print(p1.name)# [1]
print(p2.name)# [1]
print(Person.name)# [1]
5 Python自省
這個(gè)也是python彪悍的特性.
自省就是面向?qū)ο蟮恼Z(yǔ)言所寫(xiě)的程序在運(yùn)行時(shí),所能知道對(duì)象的類(lèi)型.簡(jiǎn)單一句就是運(yùn)行時(shí)能夠獲得對(duì)象的類(lèi)型.比如type(),dir(),getattr(),hasattr(),isinstance().
6 字典推導(dǎo)式
可能你見(jiàn)過(guò)列表推導(dǎo)時(shí),卻沒(méi)有見(jiàn)過(guò)字典推導(dǎo)式,在2.7中才加入的:
d = {key: value for (key, value) in iterable}
7 Python中單下劃線(xiàn)和雙下劃線(xiàn)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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內(nèi)部的名字,用來(lái)區(qū)別其他用戶(hù)自定義的命名,以防沖突.
_foo:一種約定,用來(lái)指定變量私有.程序員用來(lái)指定私有變量的一種方式.
__foo:這個(gè)有真正的意義:解析器用_classname__foo來(lái)代替這個(gè)名字,以區(qū)別和其他類(lèi)相同的命名.
詳情見(jiàn):
http://www.zhihu.com/question/19754941
8 字符串格式化:%和.format
.format在許多方面看起來(lái)更便利.對(duì)于%最煩人的是它無(wú)法同時(shí)傳遞一個(gè)變量和元組.你可能會(huì)想下面的代碼不會(huì)有什么問(wèn)題:
Python:
"hi there %s" % name
但是,如果name恰好是(1,2,3),它將會(huì)拋出一個(gè)TypeError異常.為了保證它總是正確的,你必須這樣做:
"hi there %s" % (name,) # 提供一個(gè)單元素的數(shù)組而不是一個(gè)參數(shù)
9 迭代器和生成器
在Python中岖食,這種一邊循環(huán)一邊計(jì)算的機(jī)制红碑,稱(chēng)為生成器:generator。
可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象稱(chēng)為迭代器:Iterator泡垃。
這個(gè)是stackoverflow里python排名第一的問(wèn)題,值得一看: http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python
10argsand*kwargs
用args和*kwargs只是為了方便并沒(méi)有強(qiáng)制使用它們.
當(dāng)你不確定你的函數(shù)里將要傳遞多少參數(shù)時(shí)你可以用*args.例如,它可以傳遞任意數(shù)量的參數(shù):
1
2
3
4
5
6
7
8
def print_everything(*args):
for count, thing in enumerate(args):
... print '{0}. {1}'.format(count, thing)
...
print_everything('apple', 'banana', 'cabbage')
apple
banana
cabbage
相似的,**kwargs允許你使用沒(méi)有事先定義的參數(shù)名:
1
2
3
4
5
6
7
def table_things(**kwargs):
... for name, value in kwargs.items():
... print '{0} = {1}'.format(name, value)
...
table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit
你也可以混著用.命名參數(shù)首先獲得參數(shù)值然后所有的其他參數(shù)都傳遞給args和*kwargs.命名參數(shù)在列表的最前端.例如:
1
def table_things(titlestring, **kwargs)
args和kwargs可以同時(shí)在函數(shù)的定義中,但是args必須在**kwargs前面.
當(dāng)調(diào)用函數(shù)時(shí)你也可以用和*語(yǔ)法.例如:
1
2
3
4
5
6
7
def print_three_things(a, b, c):
... print 'a = {0}, b = {1}, c = {2}'.format(a,b,c)
...
mylist = ['aardvark', 'baboon', 'cat']
print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
就像你看到的一樣,它可以傳遞列表(或者元組)的每一項(xiàng)并把它們解包.注意必須與它們?cè)诤瘮?shù)里的參數(shù)相吻合.當(dāng)然,你也可以在函數(shù)定義或者函數(shù)調(diào)用時(shí)用*.
http://stackoverflow.com/questions/3394835/args-and-kwargs
11 面向切面編程AOP和裝飾器
這個(gè)AOP一聽(tīng)起來(lái)有點(diǎn)懵,同學(xué)面試的時(shí)候就被問(wèn)懵了…
裝飾器是一個(gè)很著名的設(shè)計(jì)模式析珊,經(jīng)常被用于有切面需求的場(chǎng)景,較為經(jīng)典的有插入日志蔑穴、性能測(cè)試唾琼、事務(wù)處理等。裝飾器是解決這類(lèi)問(wèn)題的絕佳設(shè)計(jì)澎剥,有了裝飾器锡溯,我們就可以抽離出大量函數(shù)中與函數(shù)功能本身無(wú)關(guān)的雷同代碼并繼續(xù)重用。概括的講哑姚,裝飾器的作用就是為已經(jīng)存在的對(duì)象添加額外的功能祭饭。
這個(gè)問(wèn)題比較大,推薦: 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 鴨子類(lèi)型
“當(dāng)看到一只鳥(niǎo)走起來(lái)像鴨子、游泳起來(lái)像鴨子叙量、叫起來(lái)也像鴨子倡蝙,那么這只鳥(niǎo)就可以被稱(chēng)為鴨子〗逝澹”
我們并不關(guān)心對(duì)象是什么類(lèi)型寺鸥,到底是不是鴨子,只關(guān)心行為品山。
比如在python中胆建,有很多file-like的東西,比如StringIO,GzipFile,socket肘交。它們有很多相同的方法笆载,我們把它們當(dāng)作文件使用。
又比如list.extend()方法中,我們并不關(guān)心它的參數(shù)是不是list,只要它是可迭代的,所以它的參數(shù)可以是list/tuple/dict/字符串/生成器等.
鴨子類(lèi)型在動(dòng)態(tài)語(yǔ)言中經(jīng)常使用涯呻,非常靈活凉驻,使得python不想java那樣專(zhuān)門(mén)去弄一大堆的設(shè)計(jì)模式。
13 Python中重載
引自知乎:http://www.zhihu.com/question/20053359
函數(shù)重載主要是為了解決兩個(gè)問(wèn)題复罐。
可變參數(shù)類(lèi)型涝登。
可變參數(shù)個(gè)數(shù)。
另外效诅,一個(gè)基本的設(shè)計(jì)原則是胀滚,僅僅當(dāng)兩個(gè)函數(shù)除了參數(shù)類(lèi)型和參數(shù)個(gè)數(shù)不同以外咳短,其功能是完全相同的,此時(shí)才使用函數(shù)重載蛛淋,如果兩個(gè)函數(shù)的功能其實(shí)不同咙好,那么不應(yīng)當(dāng)使用重載,而應(yīng)當(dāng)使用一個(gè)名字不同的函數(shù)褐荷。
好吧勾效,那么對(duì)于情況 1 ,函數(shù)功能相同叛甫,但是參數(shù)類(lèi)型不同层宫,python 如何處理?答案是根本不需要處理其监,因?yàn)?python 可以接受任何類(lèi)型的參數(shù)萌腿,如果函數(shù)的功能相同,那么不同的參數(shù)類(lèi)型在 python 中很可能是相同的代碼抖苦,沒(méi)有必要做成兩個(gè)不同函數(shù)毁菱。
那么對(duì)于情況 2 ,函數(shù)功能相同锌历,但參數(shù)個(gè)數(shù)不同贮庞,python 如何處理?大家知道究西,答案就是缺省參數(shù)窗慎。對(duì)那些缺少的參數(shù)設(shè)定為缺省參數(shù)即可解決問(wèn)題。因?yàn)槟慵僭O(shè)函數(shù)功能相同卤材,那么那些缺少的參數(shù)終歸是需要用的遮斥。
好了,鑒于情況 1 跟 情況 2 都有了解決方案扇丛,python 自然就不需要函數(shù)重載了术吗。
14 新式類(lèi)和舊式類(lèi)
這個(gè)面試官問(wèn)了,我說(shuō)了老半天,不知道他問(wèn)的真正意圖是什么.
這篇文章很好的介紹了新式類(lèi)的特性: http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html
新式類(lèi)很早在2.2就出現(xiàn)了,所以舊式類(lèi)完全是兼容的問(wèn)題,Python3里的類(lèi)全部都是新式類(lèi).這里有一個(gè)MRO問(wèn)題可以了解下(新式類(lèi)是廣度優(yōu)先,舊式類(lèi)是深度優(yōu)先),<Python核心編程>里講的也很多.
15__new__和init的區(qū)別
這個(gè)new確實(shí)很少見(jiàn)到,先做了解吧.
new是一個(gè)靜態(tài)方法,而init是一個(gè)實(shí)例方法.
new方法會(huì)返回一個(gè)創(chuàng)建的實(shí)例,而init什么都不返回.
只有在new返回一個(gè)cls的實(shí)例時(shí)后面的init才能被調(diào)用.
當(dāng)創(chuàng)建一個(gè)新實(shí)例時(shí)調(diào)用new,初始化一個(gè)實(shí)例時(shí)用init.
ps:metaclass是創(chuàng)建類(lèi)時(shí)起作用.所以我們可以分別使用metaclass,new和init來(lái)分別在類(lèi)創(chuàng)建,實(shí)例創(chuàng)建和實(shí)例初始化的時(shí)候做一些小手腳.
16 單例模式
這個(gè)絕對(duì)常考啊.絕對(duì)要記住1~2個(gè)方法,當(dāng)時(shí)面試官是讓手寫(xiě)的.
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 共享屬性
創(chuàng)建實(shí)例時(shí)把所有實(shí)例的dict指向同一個(gè)字典,這樣它們具有相同的屬性和方法.
1
2
3
4
5
6
7
8
9
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 裝飾器版本
1
2
3
4
5
6
7
8
9
10
11
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:
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()
17 Python中的作用域
Python 中晕拆,一個(gè)變量的作用域總是由在代碼中被賦值的地方所決定的藐翎。
當(dāng) Python 遇到一個(gè)變量的話(huà)他會(huì)按照這樣的順序進(jìn)行搜索:
本地作用域(Local)→當(dāng)前作用域被嵌入的本地作用域(Enclosing locals)→全局/模塊作用域(Global)→內(nèi)置作用域(Built-in)
18 GIL線(xiàn)程全局鎖
線(xiàn)程全局鎖(Global Interpreter Lock),即Python為了保證線(xiàn)程安全而采取的獨(dú)立線(xiàn)程運(yùn)行的限制,說(shuō)白了就是一個(gè)核只能在同一時(shí)間運(yùn)行一個(gè)線(xiàn)程.
解決辦法就是多進(jìn)程和下面的協(xié)程(協(xié)程也只是單CPU,但是能減小切換代價(jià)提升性能).
19 協(xié)程
簡(jiǎn)單點(diǎn)說(shuō)協(xié)程是進(jìn)程和線(xiàn)程的升級(jí)版,進(jìn)程和線(xiàn)程都面臨著內(nèi)核態(tài)和用戶(hù)態(tài)的切換問(wèn)題而耗費(fèi)許多切換時(shí)間,而協(xié)程就是用戶(hù)自己控制切換的時(shí)機(jī),不再需要陷入系統(tǒng)的內(nèi)核態(tài).
Python里最常見(jiàn)的yield就是協(xié)程的思想!可以查看第九個(gè)問(wèn)題.
20 閉包
閉包(closure)是函數(shù)式編程的重要的語(yǔ)法結(jié)構(gòu)。閉包也是一種組織代碼的結(jié)構(gòu)实幕,它同樣提高了代碼的可重復(fù)使用性。
當(dāng)一個(gè)內(nèi)嵌函數(shù)引用其外部作作用域的變量,我們就會(huì)得到一個(gè)閉包. 總結(jié)一下,創(chuàng)建一個(gè)閉包必須滿(mǎn)足以下幾點(diǎn):
必須有一個(gè)內(nèi)嵌函數(shù)
內(nèi)嵌函數(shù)必須引用外部函數(shù)中的變量
外部函數(shù)的返回值必須是內(nèi)嵌函數(shù)
感覺(jué)閉包還是有難度的,幾句話(huà)是說(shuō)不明白的,還是查查相關(guān)資料.
重點(diǎn)是函數(shù)運(yùn)行后并不會(huì)被撤銷(xiāo),就像16題的instance字典一樣,當(dāng)函數(shù)運(yùn)行完后,instance并不被銷(xiāo)毀,而是繼續(xù)留在內(nèi)存空間里.這個(gè)功能類(lèi)似類(lèi)里的類(lèi)變量,只不過(guò)遷移到了函數(shù)上.
閉包就像個(gè)空心球一樣,你知道外面和里面,但你不知道中間是什么樣.
21 lambda函數(shù)
其實(shí)就是一個(gè)匿名函數(shù),為什么叫l(wèi)ambda?因?yàn)楹秃竺娴暮瘮?shù)式編程有關(guān).
22 Python函數(shù)式編程
這個(gè)需要適當(dāng)?shù)牧私庖幌掳?畢竟函數(shù)式編程在Python中也做了引用.
python中函數(shù)式編程支持:
filter 函數(shù)的功能相當(dāng)于過(guò)濾器堤器。調(diào)用一個(gè)布爾函數(shù)bool_func來(lái)迭代遍歷每個(gè)seq中的元素昆庇;返回一個(gè)使bool_seq返回值為true的元素的序列。
a = [1,2,3,4,5,6,7]
b = filter(lambda x: x > 5, a)
print b
[6,7]
map函數(shù)是對(duì)一個(gè)序列的每個(gè)項(xiàng)依次執(zhí)行函數(shù)闸溃,下面是對(duì)一個(gè)序列每個(gè)項(xiàng)都乘以2:
a = map(lambda x:x*2,[1,2,3])
list(a)
[2, 4, 6]
reduce函數(shù)是對(duì)一個(gè)序列的每個(gè)項(xiàng)迭代調(diào)用函數(shù)整吆,下面是求3的階乘:
reduce(lambda x,y:x*y,range(1,4))
6
23 Python里的拷貝
引用和copy(),deepcopy()的區(qū)別
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import copy
a = [1, 2, 3, 4, ['a', 'b']]#原始對(duì)象
b = a#賦值拱撵,傳對(duì)象的引用
c = copy.copy(a)#對(duì)象拷貝,淺拷貝
d = copy.deepcopy(a)#對(duì)象拷貝表蝙,深拷貝
a.append(5)#修改對(duì)象a
a[4].append('c')#修改對(duì)象a中的['a', 'b']數(shù)組對(duì)象
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
輸出結(jié)果:
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垃圾回收機(jī)制
Python GC主要使用引用計(jì)數(shù)(reference counting)來(lái)跟蹤和回收垃圾拴测。在引用計(jì)數(shù)的基礎(chǔ)上,通過(guò)“標(biāo)記-清除”(mark and sweep)解決容器對(duì)象可能產(chǎn)生的循環(huán)引用問(wèn)題府蛇,通過(guò)“分代回收”(generation collection)以空間換時(shí)間的方法提高垃圾回收效率叶组。
1 引用計(jì)數(shù)
PyObject是每個(gè)對(duì)象必有的內(nèi)容柱蟀,其中ob_refcnt就是做為引用計(jì)數(shù)。當(dāng)一個(gè)對(duì)象有新的引用時(shí),它的ob_refcnt就會(huì)增加窃爷,當(dāng)引用它的對(duì)象被刪除,它的ob_refcnt就會(huì)減少.引用計(jì)數(shù)為0時(shí)晾虑,該對(duì)象生命就結(jié)束了千诬。
優(yōu)點(diǎn):
簡(jiǎn)單
實(shí)時(shí)性
缺點(diǎn):
維護(hù)引用計(jì)數(shù)消耗資源
循環(huán)引用
2 標(biāo)記-清除機(jī)制
基本思路是先按需分配,等到?jīng)]有空閑內(nèi)存的時(shí)候從寄存器和程序棧上的引用出發(fā)蚪黑,遍歷以對(duì)象為節(jié)點(diǎn)盅惜、以引用為邊構(gòu)成的圖,把所有可以訪(fǎng)問(wèn)到的對(duì)象打上標(biāo)記忌穿,然后清掃一遍內(nèi)存空間酷窥,把所有沒(méi)標(biāo)記的對(duì)象釋放。
3 分代技術(shù)
分代回收的整體思想是:將系統(tǒng)中的所有內(nèi)存塊根據(jù)其存活時(shí)間劃分為不同的集合伴网,每個(gè)集合就成為一個(gè)“代”蓬推,垃圾收集頻率隨著“代”的存活時(shí)間的增大而減小,存活時(shí)間通常利用經(jīng)過(guò)幾次垃圾回收來(lái)度量澡腾。
Python默認(rèn)定義了三代對(duì)象集合沸伏,索引數(shù)越大,對(duì)象存活時(shí)間越長(zhǎng)动分。
舉例:
當(dāng)某些內(nèi)存塊M經(jīng)過(guò)了3次垃圾收集的清洗之后還存活時(shí)毅糟,我們就將內(nèi)存塊M劃到一個(gè)集合A中去,而新分配的內(nèi)存都劃分到集合B中去澜公。當(dāng)垃圾收集開(kāi)始工作時(shí)姆另,大多數(shù)情況都只對(duì)集合B進(jìn)行垃圾回收,而對(duì)集合A進(jìn)行垃圾回收要隔相當(dāng)長(zhǎng)一段時(shí)間后才進(jìn)行坟乾,這就使得垃圾收集機(jī)制需要處理的內(nèi)存少了迹辐,效率自然就提高了。在這個(gè)過(guò)程中甚侣,集合B中的某些內(nèi)存塊由于存活時(shí)間長(zhǎng)而會(huì)被轉(zhuǎn)移到集合A中明吩,當(dāng)然,集合A中實(shí)際上也存在一些垃圾殷费,這些垃圾的回收會(huì)因?yàn)檫@種分代的機(jī)制而被延遲印荔。
25 Python里面如何實(shí)現(xiàn)tuple和list的轉(zhuǎn)換低葫?
答:tuple,可以說(shuō)是不可變的list仍律,訪(fǎng)問(wèn)方式還是通過(guò)索引下標(biāo)的方式嘿悬。
當(dāng)你明確定義個(gè)tuple是,如果僅有一個(gè)元素水泉,必須帶有,例如:(1,)善涨。
當(dāng)然,在2.7以后的版茶行,python里還增加了命名式的tuple躯概!
至于有什么用,首先第一點(diǎn)畔师,樓主玩過(guò)python都知道娶靡,python的函數(shù)可以有多返回值的,而python里看锉,多返回值姿锭,就是用tuple來(lái)表示,這是用的最廣的了伯铣,
比如說(shuō)呻此,你需要定義一個(gè)常量的列表,但你又不想使用list腔寡,那也可以是要你管tuple焚鲜,例如:
if a in ('A','B','C'):pass
26 Python的is
is是對(duì)比地址,==是對(duì)比值
27 read,readline和readlines
read 讀取整個(gè)文件
readline 讀取下一行,使用生成器方法
readlines 讀取整個(gè)文件到一個(gè)迭代器以供我們遍歷
28 Python2和3的區(qū)別
大部分Python庫(kù)都同時(shí)支持Python 2.7.x和3.x版本的,所以不論選擇哪個(gè)版本都是可以的放前。但為了在使用Python時(shí)避開(kāi)某些版本中一些常見(jiàn)的陷阱忿磅,或需要移植某個(gè)Python項(xiàng)目
使用future模塊
print函數(shù)
整數(shù)除法
Unicode
xrange
觸發(fā)異常
處理異常
next()函數(shù)和.next()方法
For循環(huán)變量與全局命名空間泄漏
比較無(wú)序類(lèi)型
使用input()解析輸入內(nèi)容
返回可迭代對(duì)象,而不是列表
推薦:《Python 2.7.x 和 3.x 版本的重要區(qū)別》
29到底什么是Python凭语?你可以在回答中與其他技術(shù)進(jìn)行對(duì)比
答案
下面是一些關(guān)鍵點(diǎn):
Python是一種解釋型語(yǔ)言葱她。這就是說(shuō),與C語(yǔ)言和C的衍生語(yǔ)言不同似扔,Python代碼在運(yùn)行之前不需要編譯吨些。其他解釋型語(yǔ)言還包括PHP和Ruby。
Python是動(dòng)態(tài)類(lèi)型語(yǔ)言炒辉,指的是你在聲明變量時(shí)豪墅,不需要說(shuō)明變量的類(lèi)型。你可以直接編寫(xiě)類(lèi)似x=111和x="I'm a string"這樣的代碼辆脸,程序不會(huì)報(bào)錯(cuò)但校。
Python非常適合面向?qū)ο蟮木幊蹋∣OP),因?yàn)樗С滞ㄟ^(guò)組合(composition)與繼承(inheritance)的方式定義類(lèi)(class)啡氢。Python中沒(méi)有訪(fǎng)問(wèn)說(shuō)明符(access specifier状囱,類(lèi)似C++中的public和private),這么設(shè)計(jì)的依據(jù)是“大家都是成年人了”倘是。
在Python語(yǔ)言中亭枷,函數(shù)是第一類(lèi)對(duì)象(first-class objects)。這指的是它們可以被指定給變量搀崭,函數(shù)既能返回函數(shù)類(lèi)型叨粘,也可以接受函數(shù)作為輸入。類(lèi)(class)也是第一類(lèi)對(duì)象瘤睹。
Python代碼編寫(xiě)快升敲,但是運(yùn)行速度比編譯語(yǔ)言通常要慢。好在Python允許加入基于C語(yǔ)言編寫(xiě)的擴(kuò)展轰传,因此我們能夠優(yōu)化代碼驴党,消除瓶頸,這點(diǎn)通常是可以實(shí)現(xiàn)的获茬。numpy就是一個(gè)很好地例子港庄,它的運(yùn)行速度真的非常快恕曲,因?yàn)楹芏嗨阈g(shù)運(yùn)算其實(shí)并不是通過(guò)Python實(shí)現(xiàn)的鹏氧。
Python用途非常廣泛——網(wǎng)絡(luò)應(yīng)用,自動(dòng)化佩谣,科學(xué)建模把还,大數(shù)據(jù)應(yīng)用,等等茸俭。它也常被用作“膠水語(yǔ)言”吊履,幫助其他語(yǔ)言和組件改善運(yùn)行狀況。
Python讓困難的事情變得容易瓣履,因此程序員可以專(zhuān)注于算法和數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)率翅,而不用處理底層的細(xì)節(jié)。
為什么提這個(gè)問(wèn)題:
如果你應(yīng)聘的是一個(gè)Python開(kāi)發(fā)崗位袖迎,你就應(yīng)該知道這是門(mén)什么樣的語(yǔ)言冕臭,以及它為什么這么酷。以及它哪里不好燕锥。
30補(bǔ)充缺失的代碼
def print_directory_contents(sPath):
"""
這個(gè)函數(shù)接受文件夾的名稱(chēng)作為輸入?yún)?shù)辜贵,
返回該文件夾中文件的路徑,
以及其包含文件夾中文件的路徑归形。
"""
# 補(bǔ)充代碼
答案
def print_directory_contents(sPath):
import os
for sChild in os.listdir(sPath):
sChildPath = os.path.join(sPath,sChild)
if os.path.isdir(sChildPath):
print_directory_contents(sChildPath)
else:
print sChildPath
特別要注意以下幾點(diǎn):
命名規(guī)范要統(tǒng)一托慨。如果樣本代碼中能夠看出命名規(guī)范,遵循其已有的規(guī)范暇榴。
遞歸函數(shù)需要遞歸并終止厚棵。確保你明白其中的原理蕉世,否則你將面臨無(wú)休無(wú)止的調(diào)用棧(callstack)。
我們使用os模塊與操作系統(tǒng)進(jìn)行交互婆硬,同時(shí)做到交互方式是可以跨平臺(tái)的狠轻。你可以把代碼寫(xiě)成sChildPath = sPath + '/' + sChild,但是這個(gè)在Windows系統(tǒng)上會(huì)出錯(cuò)彬犯。
熟悉基礎(chǔ)模塊是非常有價(jià)值的向楼,但是別想破腦袋都背下來(lái),記住Google是你工作中的良師益友谐区。
如果你不明白代碼的預(yù)期功能湖蜕,就大膽提問(wèn)。
堅(jiān)持KISS原則宋列!保持簡(jiǎn)單昭抒,不過(guò)腦子就能懂!
為什么提這個(gè)問(wèn)題:
說(shuō)明面試者對(duì)與操作系統(tǒng)交互的基礎(chǔ)知識(shí)
遞歸真是太好用啦
31閱讀下面的代碼虚茶,寫(xiě)出A0戈鲁,A1至An的最終值。
A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
A1 = range(10)
A2 = [i for i in A1 if i in A0]
A3 = [A0[s] for s in A0]
A4 = [i for i in A1 if i in A3]
A5 = {i:i*i for i in A1}
A6 = [[i,i*i] for i in A1]
答案
A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
A1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A2 = []
A3 = [1, 3, 2, 5, 4]
A4 = [1, 2, 3, 4, 5]
A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
為什么提這個(gè)問(wèn)題:
列表解析(list comprehension)十分節(jié)約時(shí)間嘹叫,對(duì)很多人來(lái)說(shuō)也是一個(gè)大的學(xué)習(xí)障礙婆殿。
如果你讀懂了這些代碼,就很可能可以寫(xiě)下正確地值罩扇。
其中部分代碼故意寫(xiě)的怪怪的婆芦。因?yàn)槟愎彩碌娜酥幸矔?huì)有怪人。
32下面代碼會(huì)輸出什么:
def f(x,l=[]):
for i in range(x):
l.append(i*i)
print(l)
f(2)
f(3,[3,2,1])
f(3)
答案:
[0, 1]
[3, 2, 1, 0, 1, 4]
[0, 1, 0, 1, 4]
呃喂饥?
第一個(gè)函數(shù)調(diào)用十分明顯消约,for循環(huán)先后將0和1添加至了空列表l中。l是變量的名字员帮,指向內(nèi)存中存儲(chǔ)的一個(gè)列表或粮。第二個(gè)函數(shù)調(diào)用在一塊新的內(nèi)存中創(chuàng)建了新的列表。l這時(shí)指向了新生成的列表捞高。之后再往新列表中添加0氯材、1和4。很棒吧硝岗。第三個(gè)函數(shù)調(diào)用的結(jié)果就有些奇怪了氢哮。它使用了之前內(nèi)存地址中存儲(chǔ)的舊列表。這就是為什么它的前兩個(gè)元素是0和1了型檀。
33你如何管理不同版本的代碼冗尤?
答案:
版本管理!被問(wèn)到這個(gè)問(wèn)題的時(shí)候,你應(yīng)該要表現(xiàn)得很興奮裂七,甚至告訴他們你是如何使用Git(或是其他你最喜歡的工具)追蹤自己和奶奶的書(shū)信往來(lái)皆看。我偏向于使用Git作為版本控制系統(tǒng)(VCS),但還有其他的選擇碍讯,比如subversion(SVN)悬蔽。
為什么提這個(gè)問(wèn)題:
因?yàn)闆](méi)有版本控制的代碼扯躺,就像沒(méi)有杯子的咖啡捉兴。有時(shí)候我們需要寫(xiě)一些一次性的、可以隨手扔掉的腳本录语,這種情況下不作版本控制沒(méi)關(guān)系倍啥。但是如果你面對(duì)的是大量的代碼,使用版本控制系統(tǒng)是有利的澎埠。版本控制能夠幫你追蹤誰(shuí)對(duì)代碼庫(kù)做了什么操作虽缕;發(fā)現(xiàn)新引入了什么bug;管理你的軟件的不同版本和發(fā)行版蒲稳;在團(tuán)隊(duì)成員中分享源代碼氮趋;部署及其他自動(dòng)化處理。它能讓你回滾到出現(xiàn)問(wèn)題之前的版本江耀,單憑這點(diǎn)就特別棒了剩胁。還有其他的好功能。怎么一個(gè)棒字了得祥国!
34“猴子補(bǔ)丁”(monkey patching)指的是什么昵观?這種做法好嗎?
答案:
“猴子補(bǔ)丁”就是指舌稀,在函數(shù)或?qū)ο笠呀?jīng)定義之后啊犬,再去改變它們的行為。
舉個(gè)例子:
import datetime
datetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)
大部分情況下壁查,這是種很不好的做法 - 因?yàn)楹瘮?shù)在代碼庫(kù)中的行為最好是都保持一致觉至。打“猴子補(bǔ)丁”的原因可能是為了測(cè)試。mock包對(duì)實(shí)現(xiàn)這個(gè)目的很有幫助睡腿。
為什么提這個(gè)問(wèn)題语御?
答對(duì)這個(gè)問(wèn)題說(shuō)明你對(duì)單元測(cè)試的方法有一定了解。你如果提到要避免“猴子補(bǔ)丁”嫉到,可以說(shuō)明你不是那種喜歡花里胡哨代碼的程序員(公司里就有這種人沃暗,跟他們共事真是糟糕透了),而是更注重可維護(hù)性何恶。還記得KISS原則碼孽锥?答對(duì)這個(gè)問(wèn)題還說(shuō)明你明白一些Python底層運(yùn)作的方式,函數(shù)實(shí)際是如何存儲(chǔ)、調(diào)用等等惜辑。
另外:如果你沒(méi)讀過(guò)mock模塊的話(huà)唬涧,真的值得花時(shí)間讀一讀。這個(gè)模塊非常有用盛撑。
35閱讀下面的代碼碎节,它的輸出結(jié)果是什么?
class A(object):
def go(self):
print "go A go!"
def stop(self):
print "stop A stop!"
def pause(self):
raise Exception("Not Implemented")
class B(A):
def go(self):
super(B, self).go()
print "go B go!"
class C(A):
def go(self):
super(C, self).go()
print "go C go!"
def stop(self):
super(C, self).stop()
print "stop C stop!"
class D(B,C):
def go(self):
super(D, self).go()
print "go D go!"
def stop(self):
super(D, self).stop()
print "stop D stop!"
def pause(self):
print "wait D wait!"
class E(B,C): pass
a = A()
b = B()
c = C()
d = D()
e = E()
說(shuō)明下列代碼的輸出結(jié)果
a.go()
b.go()
c.go()
d.go()
e.go()
a.stop()
b.stop()
c.stop()
d.stop()
e.stop()
a.pause()
b.pause()
c.pause()
d.pause()
e.pause()
答案
輸出結(jié)果以注釋的形式表示:
a.go()
go A go!
b.go()
go A go!
go B go!
c.go()
go A go!
go C go!
d.go()
go A go!
go C go!
go B go!
go D go!
e.go()
go A go!
go C go!
go B go!
a.stop()
stop A stop!
b.stop()
stop A stop!
c.stop()
stop A stop!
stop C stop!
d.stop()
stop A stop!
stop C stop!
stop D stop!
e.stop()
stop A stop!
a.pause()
... Exception: Not Implemented
b.pause()
... Exception: Not Implemented
c.pause()
... Exception: Not Implemented
d.pause()
wait D wait!
e.pause()
...Exception: Not Implemented
為什么提這個(gè)問(wèn)題抵卫?
因?yàn)槊嫦驅(qū)ο蟮木幊陶娴恼娴暮苤匾ɡ蟆2或_你。答對(duì)這道問(wèn)題說(shuō)明你理解了繼承和Python中super函數(shù)的用法介粘。
36閱讀下面的代碼殖氏,它的輸出結(jié)果是什么?
class Node(object):
def __init__(self,sName):
self._lChildren = []
self.sName = sName
def __repr__(self):
return "<Node '{}'>".format(self.sName)
def append(self,*args,**kwargs):
self._lChildren.append(*args,**kwargs)
def print_all_1(self):
print self
for oChild in self._lChildren:
oChild.print_all_1()
def print_all_2(self):
def gen(o):
lAll = [o,]
while lAll:
oNext = lAll.pop(0)
lAll.extend(oNext._lChildren)
yield oNext
for oNode in gen(self):
print oNode
oRoot = Node("root")
oChild1 = Node("child1")
oChild2 = Node("child2")
oChild3 = Node("child3")
oChild4 = Node("child4")
oChild5 = Node("child5")
oChild6 = Node("child6")
oChild7 = Node("child7")
oChild8 = Node("child8")
oChild9 = Node("child9")
oChild10 = Node("child10")
oRoot.append(oChild1)
oRoot.append(oChild2)
oRoot.append(oChild3)
oChild1.append(oChild4)
oChild1.append(oChild5)
oChild2.append(oChild6)
oChild4.append(oChild7)
oChild3.append(oChild8)
oChild3.append(oChild9)
oChild6.append(oChild10)
說(shuō)明下面代碼的輸出結(jié)果
oRoot.print_all_1()
oRoot.print_all_2()
答案
oRoot.print_all_1()會(huì)打印下面的結(jié)果:
<Node 'root'>
<Node 'child1'>
<Node 'child4'>
<Node 'child7'>
<Node 'child5'>
<Node 'child2'>
<Node 'child6'>
<Node 'child10'>
<Node 'child3'>
<Node 'child8'>
<Node 'child9'>
oRoot.print_all_1()會(huì)打印下面的結(jié)果:
<Node 'root'>
<Node 'child1'>
<Node 'child2'>
<Node 'child3'>
<Node 'child4'>
<Node 'child5'>
<Node 'child6'>
<Node 'child8'>
<Node 'child9'>
<Node 'child7'>
<Node 'child10'>
為什么提這個(gè)問(wèn)題姻采?
因?yàn)閷?duì)象的精髓就在于組合(composition)與對(duì)象構(gòu)造(object construction)雅采。對(duì)象需要有組合成分構(gòu)成,而且得以某種方式初始化慨亲。這里也涉及到遞歸和生成器(generator)的使用婚瓜。
生成器是很棒的數(shù)據(jù)類(lèi)型。你可以只通過(guò)構(gòu)造一個(gè)很長(zhǎng)的列表刑棵,然后打印列表的內(nèi)容巴刻,就可以取得與print_all_2類(lèi)似的功能。生成器還有一個(gè)好處铐望,就是不用占據(jù)很多內(nèi)存冈涧。
有一點(diǎn)還值得指出,就是print_all_1會(huì)以深度優(yōu)先(depth-first)的方式遍歷樹(shù)(tree),而print_all_2則是寬度優(yōu)先(width-first)正蛙。有時(shí)候督弓,一種遍歷方式比另一種更合適。但這要看你的應(yīng)用的具體情況乒验。
36.介紹一下except的用法和作用愚隧?
答:try…except…except…[else…][finally…]
執(zhí)行try下的語(yǔ)句,如果引發(fā)異常锻全,則執(zhí)行過(guò)程會(huì)跳到except語(yǔ)句狂塘。對(duì)每個(gè)except分支順序嘗試執(zhí)行,如果引發(fā)的異常與except中的異常組匹配鳄厌,執(zhí)行相應(yīng)的語(yǔ)句荞胡。如果所有的except都不匹配,則異常會(huì)傳遞到下一個(gè)調(diào)用本代碼的最高層try代碼中了嚎。
try下的語(yǔ)句正常執(zhí)行泪漂,則執(zhí)行else塊代碼廊营。如果發(fā)生異常,就不會(huì)執(zhí)行
如果存在finally語(yǔ)句萝勤,最后總是會(huì)執(zhí)行露筒。
37.Python中pass語(yǔ)句的作用是什么?
答:pass語(yǔ)句不會(huì)執(zhí)行任何操作敌卓,一般作為占位符或者創(chuàng)建占位程序慎式,whileFalse:pass
38.介紹一下Python下range()函數(shù)的用法?
答:列出一組數(shù)據(jù)趟径,經(jīng)常用在for in range()循環(huán)中
39.如何用Python來(lái)進(jìn)行查詢(xún)和替換一個(gè)文本字符串瘪吏?
答:可以使用re模塊中的sub()函數(shù)或者subn()函數(shù)來(lái)進(jìn)行查詢(xún)和替換,
格式:sub(replacement, string[,count=0])(replacement是被替換成的文本舵抹,string是需要被替換的文本肪虎,count是一個(gè)可選參數(shù),指最大被替換的數(shù)量)
import re
p=re.compile(‘blue|white|red’)
print(p.sub(‘colour’,'blue socks and red shoes’))
colour socks and colourshoes
print(p.sub(‘colour’,'blue socks and red shoes’,count=1))
colour socks and redshoes
subn()方法執(zhí)行的效果跟sub()一樣惧蛹,不過(guò)它會(huì)返回一個(gè)二維數(shù)組,包括替換后的新的字符串和總共替換的數(shù)量
40.Python里面match()和search()的區(qū)別刑枝?
答:re模塊中match(pattern,string[,flags]),檢查string的開(kāi)頭是否與pattern匹配香嗓。
re模塊中research(pattern,string[,flags]),在string搜索pattern的第一個(gè)匹配值。
print(re.match(‘super’, ‘superstition’).span())
(0, 5)
print(re.match(‘super’, ‘insuperable’))
None
print(re.search(‘super’, ‘superstition’).span())
(0, 5)
print(re.search(‘super’, ‘insuperable’).span())
(2, 7)
41.用Python匹配HTML tag的時(shí)候装畅,<.>和<.?>有什么區(qū)別靠娱?
答:術(shù)語(yǔ)叫貪婪匹配( <.> )和非貪婪匹配(<.?> )
例如:
test
<.*> :
test
<.*?> :
42.Python里面如何生成隨機(jī)數(shù)?
答:random模塊
隨機(jī)整數(shù):random.randint(a,b):返回隨機(jī)整數(shù)x,a<=x<=b
random.randrange(start,stop,[,step]):返回一個(gè)范圍在(start,stop,step)之間的隨機(jī)整數(shù)掠兄,不包括結(jié)束值像云。
隨機(jī)實(shí)數(shù):random.random( ):返回0到1之間的浮點(diǎn)數(shù)
random.uniform(a,b):返回指定范圍內(nèi)的浮點(diǎn)數(shù)。
43.有沒(méi)有一個(gè)工具可以幫助查找python的bug和進(jìn)行靜態(tài)的代碼分析蚂夕?
答:PyChecker是一個(gè)python代碼的靜態(tài)分析工具迅诬,它可以幫助查找python代碼的bug, 會(huì)對(duì)代碼的復(fù)雜度和格式提出警告
Pylint是另外一個(gè)工具可以進(jìn)行codingstandard檢查
44.如何在一個(gè)function里面設(shè)置一個(gè)全局的變量?
答:解決方法是在function的開(kāi)始插入一個(gè)global聲明:
def f()
global x
45.單引號(hào)婿牍,雙引號(hào)侈贷,三引號(hào)的區(qū)別
答:?jiǎn)我?hào)和雙引號(hào)是等效的,如果要換行等脂,需要符號(hào)(),三引號(hào)則可以直接換行俏蛮,并且可以包含注釋
如果要表示Let’s go 這個(gè)字符串
單引號(hào):s4 = ‘Let\’s go’
雙引號(hào):s5 = “Let’s go”
s6 = ‘I realy like“python”!’
這就是單引號(hào)和雙引號(hào)都可以表示字符串的原因了
46 Python和多線(xiàn)程(multi-threading)。這是個(gè)好主意碼上遥?列舉一些讓Python代碼以并行方式運(yùn)行的方法搏屑。
答案
Python并不支持真正意義上的多線(xiàn)程。Python中提供了多線(xiàn)程包粉楚,但是如果你想通過(guò)多線(xiàn)程提高代碼的速度辣恋,使用多線(xiàn)程包并不是個(gè)好主意。Python中有一個(gè)被稱(chēng)為Global Interpreter Lock(GIL)的東西,它會(huì)確保任何時(shí)候你的多個(gè)線(xiàn)程中抑党,只有一個(gè)被執(zhí)行包警。線(xiàn)程的執(zhí)行速度非常之快,會(huì)讓你誤以為線(xiàn)程是并行執(zhí)行的底靠,但是實(shí)際上都是輪流執(zhí)行害晦。經(jīng)過(guò)GIL這一道關(guān)卡處理,會(huì)增加執(zhí)行的開(kāi)銷(xiāo)暑中。這意味著壹瘟,如果你想提高代碼的運(yùn)行速度,使用threading包并不是一個(gè)很好的方法鳄逾。
不過(guò)還是有很多理由促使我們使用threading包的稻轨。如果你想同時(shí)執(zhí)行一些任務(wù),而且不考慮效率問(wèn)題雕凹,那么使用這個(gè)包是完全沒(méi)問(wèn)題的殴俱,而且也很方便憾筏。但是大部分情況下檀轨,并不是這么一回事,你會(huì)希望把多線(xiàn)程的部分外包給操作系統(tǒng)完成(通過(guò)開(kāi)啟多個(gè)進(jìn)程)否过,或者是某些調(diào)用你的Python代碼的外部程序(例如Spark或Hadoop)汽摹,又或者是你的Python代碼調(diào)用的其他代碼(例如李丰,你可以在Python中調(diào)用C函數(shù),用于處理開(kāi)銷(xiāo)較大的多線(xiàn)程工作)逼泣。
為什么提這個(gè)問(wèn)題
因?yàn)镚IL就是個(gè)混賬東西(A-hole)趴泌。很多人花費(fèi)大量的時(shí)間,試圖尋找自己多線(xiàn)程代碼中的瓶頸拉庶,直到他們明白GIL的存在嗜憔。
47 將下面的函數(shù)按照?qǐng)?zhí)行效率高低排序。
它們都接受由0至1之間的數(shù)字構(gòu)成的列表作為輸入砍的。這個(gè)列表可以很長(zhǎng)痹筛。一個(gè)輸入列表的示例如下:[random.random() for i in range(100000)]。你如何證明自己的答案是正確的廓鞠。
def f1(lIn):
l1 = sorted(lIn)
l2 = [i for i in l1 if i<0.5]
return [i*i for i in l2]
def f2(lIn):
l1 = [i for i in lIn if i<0.5]
l2 = sorted(l1)
return [i*i for i in l2]
def f3(lIn):
l1 = [i*i for i in lIn]
l2 = sorted(l1)
return [i for i in l1 if i<(0.5*0.5)]
答案
按執(zhí)行效率從高到低排列:f2帚稠、f1和f3。要證明這個(gè)答案是對(duì)的床佳,你應(yīng)該知道如何分析自己代碼的性能滋早。Python中有一個(gè)很好的程序分析包,可以滿(mǎn)足這個(gè)需求砌们。
import cProfile
lIn = [random.random() for i in range(100000)]
cProfile.run('f1(lIn)')
cProfile.run('f2(lIn)')
cProfile.run('f3(lIn)')
為了向大家進(jìn)行完整地說(shuō)明杆麸,下面我們給出上述分析代碼的輸出結(jié)果:
cProfile.run('f1(lIn)')
4 function calls in 0.045 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.009 0.009 0.044 0.044 <stdin>:1(f1)
1 0.001 0.001 0.045 0.045 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.035 0.035 0.035 0.035 {sorted}
cProfile.run('f2(lIn)')
4 function calls in 0.024 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.008 0.008 0.023 0.023 <stdin>:1(f2)
1 0.001 0.001 0.024 0.024 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.016 0.016 0.016 0.016 {sorted}
cProfile.run('f3(lIn)')
4 function calls in 0.055 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.016 0.016 0.054 0.054 <stdin>:1(f3)
1 0.001 0.001 0.055 0.055 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.038 0.038 0.038 0.038 {sorted}
為什么提這個(gè)問(wèn)題搁进?
定位并避免代碼瓶頸是非常有價(jià)值的技能。想要編寫(xiě)許多高效的代碼昔头,最終都要回答常識(shí)上來(lái)——在上面的例子中饼问,如果列表較小的話(huà),很明顯是先進(jìn)行排序更快揭斧,因此如果你可以在排序前先進(jìn)行篩選莱革,那通常都是比較好的做法。其他不顯而易見(jiàn)的問(wèn)題仍然可以通過(guò)恰當(dāng)?shù)墓ぞ邅?lái)定位讹开。因此了解這些工具是有好處的盅视。
48.如何用Python來(lái)進(jìn)行查詢(xún)和替換一個(gè)文本字符串?
可以使用sub()方法來(lái)進(jìn)行查詢(xún)和替換旦万,sub方法的格式為:sub(replacement, string[, count=0])
replacement是被替換成的文本
string是需要被替換的文本
count是一個(gè)可選參數(shù)闹击,指最大被替換的數(shù)量
49.Python里面search()和match()的區(qū)別?
match()函數(shù)只檢測(cè)RE是不是在string的開(kāi)始位置匹配成艘,search()會(huì)掃描整個(gè)string查找匹配, 也就是說(shuō)match()只有在0位置匹配成功的話(huà)才有返回赏半,如果不是開(kāi)始位置匹配成功的話(huà),match()就返回none
50.用Python匹配HTML tag的時(shí)候狰腌,<.>和<.?>有什么區(qū)別除破?
前者是貪婪匹配,會(huì)從頭到尾匹配 <a>xyz</a>琼腔,而后者是非貪婪匹配,只匹配到第一個(gè) >踱葛。
51.Python里面如何生成隨機(jī)數(shù)丹莲?
import random
random.random()
它會(huì)返回一個(gè)隨機(jī)的0和1之間的浮點(diǎn)數(shù)
操作系統(tǒng)
1 select,poll和epoll
其實(shí)所有的I/O都是輪詢(xún)的方法,只不過(guò)實(shí)現(xiàn)的層面不同罷了.
這個(gè)問(wèn)題可能有點(diǎn)深入了,但相信能回答出這個(gè)問(wèn)題是對(duì)I/O多路復(fù)用有很好的了解了.其中tornado使用的就是epoll的.
基本上select有3個(gè)缺點(diǎn):
連接數(shù)受限
查找配對(duì)速度慢
數(shù)據(jù)由內(nèi)核拷貝到用戶(hù)態(tài)
poll改善了第一個(gè)缺點(diǎn)
epoll改了三個(gè)缺點(diǎn).
2 調(diào)度算法
先來(lái)先服務(wù)(FCFS, First Come First Serve)
短作業(yè)優(yōu)先(SJF, Shortest Job First)
最高優(yōu)先權(quán)調(diào)度(Priority Scheduling)
時(shí)間片輪轉(zhuǎn)(RR, Round Robin)
多級(jí)反饋隊(duì)列調(diào)度(multilevel feedback queue scheduling)
實(shí)時(shí)調(diào)度算法:
最早截至?xí)r間優(yōu)先 EDF
最低松弛度優(yōu)先 LLF
3 死鎖
原因:
競(jìng)爭(zhēng)資源
程序推進(jìn)順序不當(dāng)
必要條件:
互斥條件
請(qǐng)求和保持條件
不剝奪條件
環(huán)路等待條件
處理死鎖基本方法:
預(yù)防死鎖(摒棄除1以外的條件)
避免死鎖(銀行家算法)
檢測(cè)死鎖(資源分配圖)
解除死鎖
剝奪資源
撤銷(xiāo)進(jìn)程
4 程序編譯與鏈接
Bulid過(guò)程可以分解為4個(gè)步驟:預(yù)處理(Prepressing), 編譯(Compilation)、匯編(Assembly)尸诽、鏈接(Linking)
以c語(yǔ)言為例:
1 預(yù)處理
預(yù)編譯過(guò)程主要處理那些源文件中的以“#”開(kāi)始的預(yù)編譯指令甥材,主要處理規(guī)則有:
將所有的“#define”刪除,并展開(kāi)所用的宏定義
處理所有條件預(yù)編譯指令性含,比如“#if”洲赵、“#ifdef”、 “#elif”商蕴、“#endif”
處理“#include”預(yù)編譯指令叠萍,將被包含的文件插入到該編譯指令的位置,注:此過(guò)程是遞歸進(jìn)行的
刪除所有注釋
添加行號(hào)和文件名標(biāo)識(shí)绪商,以便于編譯時(shí)編譯器產(chǎn)生調(diào)試用的行號(hào)信息以及用于編譯時(shí)產(chǎn)生編譯錯(cuò)誤或警告時(shí)可顯示行號(hào)
保留所有的#pragma編譯器指令苛谷。
2 編譯
編譯過(guò)程就是把預(yù)處理完的文件進(jìn)行一系列的詞法分析、語(yǔ)法分析格郁、語(yǔ)義分析及優(yōu)化后生成相應(yīng)的匯編代碼文件腹殿。這個(gè)過(guò)程是整個(gè)程序構(gòu)建的核心部分独悴。
3 匯編
匯編器是將匯編代碼轉(zhuǎn)化成機(jī)器可以執(zhí)行的指令,每一條匯編語(yǔ)句幾乎都是一條機(jī)器指令锣尉。經(jīng)過(guò)編譯刻炒、鏈接、匯編輸出的文件成為目標(biāo)文件(Object File)
4 鏈接
鏈接的主要內(nèi)容就是把各個(gè)模塊之間相互引用的部分處理好自沧,使各個(gè)模塊可以正確的拼接坟奥。
鏈接的主要過(guò)程包塊 地址和空間的分配(Address and Storage Allocation)、符號(hào)決議(Symbol Resolution)和重定位(Relocation)等步驟暂幼。
5 靜態(tài)鏈接和動(dòng)態(tài)鏈接
靜態(tài)鏈接方法:靜態(tài)鏈接的時(shí)候筏勒,載入代碼就會(huì)把程序會(huì)用到的動(dòng)態(tài)代碼或動(dòng)態(tài)代碼的地址確定下來(lái)
靜態(tài)庫(kù)的鏈接可以使用靜態(tài)鏈接,動(dòng)態(tài)鏈接庫(kù)也可以使用這種方法鏈接導(dǎo)入庫(kù)
動(dòng)態(tài)鏈接方法:使用這種方式的程序并不在一開(kāi)始就完成動(dòng)態(tài)鏈接旺嬉,而是直到真正調(diào)用動(dòng)態(tài)庫(kù)代碼時(shí)管行,載入程序才計(jì)算(被調(diào)用的那部分)動(dòng)態(tài)代碼的邏輯地址,然后等到某個(gè)時(shí)候邪媳,程序又需要調(diào)用另外某塊動(dòng)態(tài)代碼時(shí)捐顷,載入程序又去計(jì)算這部分代碼的邏輯地址,所以雨效,這種方式使程序初始化時(shí)間較短迅涮,但運(yùn)行期間的性能比不上靜態(tài)鏈接的程序
6 虛擬內(nèi)存技術(shù)
虛擬存儲(chǔ)器是值具有請(qǐng)求調(diào)入功能和置換功能,能從邏輯上對(duì)內(nèi)存容量加以擴(kuò)充的一種存儲(chǔ)系統(tǒng).
7 分頁(yè)和分段
分頁(yè): 用戶(hù)程序的地址空間被劃分成若干固定大小的區(qū)域,稱(chēng)為“頁(yè)”徽龟,相應(yīng)地叮姑,內(nèi)存空間分成若干個(gè)物理塊,頁(yè)和塊的大小相等据悔〈福可將用戶(hù)程序的任一頁(yè)放在內(nèi)存的任一塊中,實(shí)現(xiàn)了離散分配极颓。
分段: 將用戶(hù)程序地址空間分成若干個(gè)大小不等的段朱盐,每段可以定義一組相對(duì)完整的邏輯信息。存儲(chǔ)分配時(shí)菠隆,以段為單位兵琳,段與段在內(nèi)存中可以不相鄰接,也實(shí)現(xiàn)了離散分配骇径。
分頁(yè)與分段的主要區(qū)別
頁(yè)是信息的物理單位,分頁(yè)是為了實(shí)現(xiàn)非連續(xù)分配,以便解決內(nèi)存碎片問(wèn)題,或者說(shuō)分頁(yè)是由于系統(tǒng)管理的需要.段是信息的邏輯單位,它含有一組意義相對(duì)完整的信息,分段的目的是為了更好地實(shí)現(xiàn)共享,滿(mǎn)足用戶(hù)的需要.
頁(yè)的大小固定,由系統(tǒng)確定,將邏輯地址劃分為頁(yè)號(hào)和頁(yè)內(nèi)地址是由機(jī)器硬件實(shí)現(xiàn)的.而段的長(zhǎng)度卻不固定,決定于用戶(hù)所編寫(xiě)的程序,通常由編譯程序在對(duì)源程序進(jìn)行編譯時(shí)根據(jù)信息的性質(zhì)來(lái)劃分.
分頁(yè)的作業(yè)地址空間是一維的.分段的地址空間是二維的.
8 頁(yè)面置換算法
最佳置換算法OPT:不可能實(shí)現(xiàn)
先進(jìn)先出FIFO
最近最久未使用算法LRU:最近一段時(shí)間里最久沒(méi)有使用過(guò)的頁(yè)面予以置換.
clock算法
9 邊沿觸發(fā)和水平觸發(fā)
邊緣觸發(fā)是指每當(dāng)狀態(tài)變化時(shí)發(fā)生一個(gè) io 事件躯肌,條件觸發(fā)是只要滿(mǎn)足條件就發(fā)生一個(gè) io 事件
數(shù)據(jù)庫(kù)
1 事務(wù)
數(shù)據(jù)庫(kù)事務(wù)(Database Transaction) ,是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作既峡,要么完全地執(zhí)行羡榴,要么完全地不執(zhí)行。
2 數(shù)據(jù)庫(kù)索引
索引是對(duì)數(shù)據(jù)庫(kù)表中一列或多列的值進(jìn)行排序的一種結(jié)構(gòu)运敢,使用索引可快速訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)表中的特定信息校仑。
索引分為聚簇索引和非聚簇索引兩種忠售,聚簇索引 是按照數(shù)據(jù)存放的物理位置為順序的,而非聚簇索引就不一樣了迄沫;聚簇索引能提高多行檢索的速度稻扬,而非聚簇索引對(duì)于單行的檢索很快。
推薦: http://tech.meituan.com/mysql-index.html
3 Redis原理
4 樂(lè)觀(guān)鎖和悲觀(guān)鎖
悲觀(guān)鎖:假定會(huì)發(fā)生并發(fā)沖突羊瘩,屏蔽一切可能違反數(shù)據(jù)完整性的操作
樂(lè)觀(guān)鎖:假設(shè)不會(huì)發(fā)生并發(fā)沖突泰佳,只在提交操作時(shí)檢查是否違反數(shù)據(jù)完整性。
5 MVCC
大多數(shù)的MySQL事務(wù)型存儲(chǔ)引擎尘吗,如InnoDB逝她,F(xiàn)alcon以及PBXT都不使用一種簡(jiǎn)單的行鎖機(jī)制。事實(shí)上睬捶,他們都和另外一種用來(lái)增加并發(fā)性的被稱(chēng)為“多版本并發(fā)控制(MVCC)”的機(jī)制來(lái)一起使用黔宛。MVCC不只使用在MySQL中,Oracle擒贸、PostgreSQL臀晃,以及其他一些數(shù)據(jù)庫(kù)系統(tǒng)也同樣使用它。
6 MyISAM和InnoDB
MyISAM 適合于一些需要大量查詢(xún)的應(yīng)用介劫,但其對(duì)于有大量寫(xiě)操作并不是很好徽惋。甚至你只是需要update一個(gè)字段,整個(gè)表都會(huì)被鎖起來(lái)座韵,而別的進(jìn)程险绘,就算是讀進(jìn)程都無(wú)法操作直到讀操作完成。另外誉碴,MyISAM 對(duì)于 SELECT COUNT(*) 這類(lèi)的計(jì)算是超快無(wú)比的隆圆。
InnoDB 的趨勢(shì)會(huì)是一個(gè)非常復(fù)雜的存儲(chǔ)引擎,對(duì)于一些小的應(yīng)用翔烁,它會(huì)比 MyISAM 還慢。他是它支持“行鎖” 旨涝,于是在寫(xiě)操作比較多的時(shí)候蹬屹,會(huì)更優(yōu)秀。并且白华,他還支持更多的高級(jí)應(yīng)用慨默,比如:事務(wù)。
網(wǎng)絡(luò)
1 三次握手
客戶(hù)端通過(guò)向服務(wù)器端發(fā)送一個(gè)SYN來(lái)創(chuàng)建一個(gè)主動(dòng)打開(kāi)弧腥,作為三路握手的一部分厦取。客戶(hù)端把這段連接的序號(hào)設(shè)定為隨機(jī)數(shù) A管搪。
服務(wù)器端應(yīng)當(dāng)為一個(gè)合法的SYN回送一個(gè)SYN/ACK虾攻。ACK 的確認(rèn)碼應(yīng)為 A+1铡买,SYN/ACK 包本身又有一個(gè)隨機(jī)序號(hào) B。
最后霎箍,客戶(hù)端再發(fā)送一個(gè)ACK奇钞。當(dāng)服務(wù)端受到這個(gè)ACK的時(shí)候,就完成了三路握手漂坏,并進(jìn)入了連接創(chuàng)建狀態(tài)景埃。此時(shí)包序號(hào)被設(shè)定為收到的確認(rèn)號(hào) A+1,而響應(yīng)則為 B+1顶别。
2 四次揮手
CP的連接的拆除需要發(fā)送四個(gè)包谷徙,因此稱(chēng)為四次揮手(four-way handshake)⊙币铮客戶(hù)端或服務(wù)器均可主動(dòng)發(fā)起揮手動(dòng)作完慧,在socket編程中,任何一方執(zhí)行close()操作即可產(chǎn)生揮手操作条篷。
(1)客戶(hù)端A發(fā)送一個(gè)FIN骗随,用來(lái)關(guān)閉客戶(hù)A到服務(wù)器B的數(shù)據(jù)傳送。
(2)服務(wù)器B收到這個(gè)FIN赴叹,它發(fā)回一個(gè)ACK鸿染,確認(rèn)序號(hào)為收到的序號(hào)加1。和SYN一樣乞巧,一個(gè)FIN將占用一個(gè)序號(hào)涨椒。
(3)服務(wù)器B關(guān)閉與客戶(hù)端A的連接,發(fā)送一個(gè)FIN給客戶(hù)端A绽媒。
(4)客戶(hù)端A發(fā)回ACK報(bào)文確認(rèn)蚕冬,并將確認(rèn)序號(hào)設(shè)置為收到序號(hào)加1。
3 ARP協(xié)議
地址解析協(xié)議(Address Resolution Protocol): 根據(jù)IP地址獲取物理地址的一個(gè)TCP/IP協(xié)議
4 urllib和urllib2的區(qū)別
這個(gè)面試官確實(shí)問(wèn)過(guò),當(dāng)時(shí)答的urllib2可以Post而urllib不可以.
urllib提供urlencode方法用來(lái)GET查詢(xún)字符串的產(chǎn)生是辕,而urllib2沒(méi)有囤热。這是為何urllib常和urllib2一起使用的原因。
urllib2可以接受一個(gè)Request類(lèi)的實(shí)例來(lái)設(shè)置URL請(qǐng)求的headers获三,urllib僅可以接受URL旁蔼。這意味著,你不可以偽裝你的User Agent字符串等疙教。
5 Post和Get區(qū)別
GET后退按鈕/刷新無(wú)害棺聊,POST數(shù)據(jù)會(huì)被重新提交(瀏覽器應(yīng)該告知用戶(hù)數(shù)據(jù)會(huì)被重新提交)。
GET書(shū)簽可收藏贞谓,POST為書(shū)簽不可收藏限佩。
GET能被緩存,POST不能緩存 。
GET編碼類(lèi)型application/x-www-form-url祟同,POST編碼類(lèi)型encodedapplication/x-www-form-urlencoded 或 multipart/form-data作喘。為二進(jìn)制數(shù)據(jù)使用多重編碼。
GET歷史參數(shù)保留在瀏覽器歷史中耐亏。POST參數(shù)不會(huì)保存在瀏覽器歷史中徊都。
GET對(duì)數(shù)據(jù)長(zhǎng)度有限制,當(dāng)發(fā)送數(shù)據(jù)時(shí)广辰,GET 方法向 URL 添加數(shù)據(jù)暇矫;URL 的長(zhǎng)度是受限制的(URL 的最大長(zhǎng)度是 2048 個(gè)字符)。POST無(wú)限制择吊。
GET只允許 ASCII 字符李根。POST沒(méi)有限制。也允許二進(jìn)制數(shù)據(jù)几睛。
與 POST 相比房轿,GET 的安全性較差,因?yàn)樗l(fā)送的數(shù)據(jù)是 URL 的一部分所森。在發(fā)送密碼或其他敏感信息時(shí)絕不要使用 GET 囱持!POST 比 GET 更安全,因?yàn)閰?shù)不會(huì)被保存在瀏覽器歷史或 web 服務(wù)器日志中焕济。
GET的數(shù)據(jù)在 URL 中對(duì)所有人都是可見(jiàn)的纷妆。POST的數(shù)據(jù)不會(huì)顯示在 URL 中。
6 Cookie和Session
Cookie
Session
儲(chǔ)存位置
客戶(hù)端
服務(wù)器端
目的
跟蹤會(huì)話(huà)晴弃,也可以保存用戶(hù)偏好設(shè)置或者保存用戶(hù)名密碼等
跟蹤會(huì)話(huà)
安全性
不安全
安全
session技術(shù)是要使用到cookie的掩幢,之所以出現(xiàn)session技術(shù),主要是為了安全上鞠。
7 apache和nginx的區(qū)別
nginx 相對(duì) apache 的優(yōu)點(diǎn):
輕量級(jí)际邻,同樣起web 服務(wù),比apache 占用更少的內(nèi)存及資源
抗并發(fā)芍阎,nginx 處理請(qǐng)求是異步非阻塞的世曾,支持更多的并發(fā)連接,而apache 則是阻塞型的谴咸,在高并發(fā)下nginx 能保持低資源低消耗高性能
配置簡(jiǎn)潔
高度模塊化的設(shè)計(jì)度硝,編寫(xiě)模塊相對(duì)簡(jiǎn)單
社區(qū)活躍
apache 相對(duì)nginx 的優(yōu)點(diǎn):
rewrite ,比nginx 的rewrite 強(qiáng)大
模塊超多寿冕,基本想到的都可以找到
少bug ,nginx 的bug 相對(duì)較多
超穩(wěn)定
8 網(wǎng)站用戶(hù)密碼保存
明文保存
明文hash后保存,如md5
MD5+Salt方式,這個(gè)salt可以隨機(jī)
知乎使用了Bcrypy(好像)加密
9 HTTP和HTTPS
HTTPS(全稱(chēng):Hypertext Transfer Protocol over Secure Socket Layer)椒袍,是以安全為目標(biāo)的HTTP通道驼唱,簡(jiǎn)單講是HTTP的安全版。即HTTP下加入SSL層驹暑,HTTPS的安全基礎(chǔ)是SSL玫恳,因此加密的詳細(xì)內(nèi)容就需要SSL辨赐。 它是一個(gè)URI scheme(抽象標(biāo)識(shí)符體系),句法類(lèi)同http:體系京办。用于安全的HTTP數(shù)據(jù)傳輸掀序。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默認(rèn)端口及一個(gè)加密/身份驗(yàn)證層(在HTTP與TCP之間)惭婿。這個(gè)系統(tǒng)的最初研發(fā)由網(wǎng)景公司進(jìn)行不恭,提供了身份驗(yàn)證與加密通訊方法,現(xiàn)在它被廣泛用于萬(wàn)維網(wǎng)上安全敏感的通訊财饥,例如交易支付方面换吧。
超文本傳輸協(xié)議 (HTTP-Hypertext transfer protocol) 是一種詳細(xì)規(guī)定了瀏覽器和萬(wàn)維網(wǎng)服務(wù)器之間互相通信的規(guī)則,通過(guò)因特網(wǎng)傳送萬(wàn)維網(wǎng)文檔的數(shù)據(jù)傳送協(xié)議钥星。
10 XSRF和XSS
CSRF(Cross-site request forgery)跨站請(qǐng)求偽造
XSS(Cross Site Scripting)跨站腳本攻擊
CSRF重點(diǎn)在請(qǐng)求,XSS重點(diǎn)在腳本
11 RESTful架構(gòu)(SOAP,RPC)
推薦: http://www.ruanyifeng.com/blog/2011/09/restful.html
12 SOAP
SOAP(原為Simple Object Access Protocol的首字母縮寫(xiě)沾瓦,即簡(jiǎn)單對(duì)象訪(fǎng)問(wèn)協(xié)議)是交換數(shù)據(jù)的一種協(xié)議規(guī)范,使用在計(jì)算機(jī)網(wǎng)絡(luò)Web服務(wù)(web service)中谦炒,交換帶結(jié)構(gòu)信息贯莺。SOAP為了簡(jiǎn)化網(wǎng)頁(yè)服務(wù)器(Web Server)從XML數(shù)據(jù)庫(kù)中提取數(shù)據(jù)時(shí),節(jié)省去格式化頁(yè)面時(shí)間宁改,以及不同應(yīng)用程序之間按照HTTP通信協(xié)議缕探,遵從XML格式執(zhí)行資料互換,使其抽象于語(yǔ)言實(shí)現(xiàn)透且、平臺(tái)和硬件撕蔼。
13 RPC
RPC(Remote Procedure Call Protocol)——遠(yuǎn)程過(guò)程調(diào)用協(xié)議,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù)秽誊,而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議鲸沮。RPC協(xié)議假定某些傳輸協(xié)議的存在,如TCP或UDP锅论,為通信程序之間攜帶信息數(shù)據(jù)讼溺。在OSI網(wǎng)絡(luò)通信模型中,RPC跨越了傳輸層和應(yīng)用層最易。RPC使得開(kāi)發(fā)包括網(wǎng)絡(luò)分布式多程序在內(nèi)的應(yīng)用程序更加容易怒坯。
總結(jié):服務(wù)提供的兩大流派.傳統(tǒng)意義以方法調(diào)用為導(dǎo)向通稱(chēng)RPC。為了企業(yè)SOA,若干廠(chǎng)商聯(lián)合推出webservice,制定了wsdl接口定義,傳輸soap.當(dāng)互聯(lián)網(wǎng)時(shí)代,臃腫SOA被簡(jiǎn)化為http+xml/json.但是簡(jiǎn)化出現(xiàn)各種混亂藻懒。以資源為導(dǎo)向,任何操作無(wú)非是對(duì)資源的增刪改查剔猿,于是統(tǒng)一的REST出現(xiàn)了.
進(jìn)化的順序: RPC -> SOAP -> RESTful
14 CGI和WSGI
CGI是通用網(wǎng)關(guān)接口,是連接web服務(wù)器和應(yīng)用程序的接口嬉荆,用戶(hù)通過(guò)CGI來(lái)獲取動(dòng)態(tài)數(shù)據(jù)或文件等归敬。
CGI程序是一個(gè)獨(dú)立的程序,它可以用幾乎所有語(yǔ)言來(lái)寫(xiě),包括perl汪茧,c椅亚,lua,python等等舱污。
WSGI, Web Server Gateway Interface呀舔,是Python應(yīng)用程序或框架和Web服務(wù)器之間的一種接口,WSGI的其中一個(gè)目的就是讓用戶(hù)可以用統(tǒng)一的語(yǔ)言(Python)編寫(xiě)前后端扩灯。
16 中間人攻擊
在GFW里屢見(jiàn)不鮮的,呵呵.
中間人攻擊(Man-in-the-middle attack媚赖,通常縮寫(xiě)為MITM)是指攻擊者與通訊的兩端分別創(chuàng)建獨(dú)立的聯(lián)系驴剔,并交換其所收到的數(shù)據(jù)省古,使通訊的兩端認(rèn)為他們正在通過(guò)一個(gè)私密的連接與對(duì)方直接對(duì)話(huà),但事實(shí)上整個(gè)會(huì)話(huà)都被攻擊者完全控制丧失。
17 c10k問(wèn)題
所謂c10k問(wèn)題豺妓,指的是服務(wù)器同時(shí)支持成千上萬(wàn)個(gè)客戶(hù)端的問(wèn)題,也就是concurrent 10 000 connection(這也是c10k這個(gè)名字的由來(lái))布讹。
18 socket
Socket=Ip address+ TCP/UDP + port
19 瀏覽器緩存
推薦:http://web.jobbole.com/84367/
瀏覽器緩存機(jī)制琳拭,其實(shí)主要就是HTTP協(xié)議定義的緩存機(jī)制(如: Expires; Cache-control等)
Expires策略
Expires是Web服務(wù)器響應(yīng)消息頭字段描验,在響應(yīng)http請(qǐng)求時(shí)告訴瀏覽器在過(guò)期時(shí)間前瀏覽器可以直接從瀏覽器緩存取數(shù)據(jù)白嘁,而無(wú)需再次請(qǐng)求。
Cache-control策略(重點(diǎn)關(guān)注)
Cache-Control與Expires的作用一致膘流,都是指明當(dāng)前資源的有效期絮缅,控制瀏覽器是否直接從瀏覽器緩存取數(shù)據(jù)還是重新發(fā)請(qǐng)求到服務(wù)器取數(shù)據(jù)。只不過(guò)Cache-Control的選擇更多呼股,設(shè)置更細(xì)致耕魄,如果同時(shí)設(shè)置的話(huà),其優(yōu)先級(jí)高于Expires
20 HTTP1.0和HTTP1.1
推薦: http://blog.csdn.net/elifefly/article/details/3964766
請(qǐng)求頭Host字段,一個(gè)服務(wù)器多個(gè)網(wǎng)站
長(zhǎng)鏈接
文件斷點(diǎn)續(xù)傳
身份認(rèn)證,狀態(tài)管理,Cache緩存
21 Ajax
AJAX,Asynchronous JavaScript and XML(異步的 JavaScript 和 XML), 是與在不重新加載整個(gè)頁(yè)面的情況下彭谁,與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁(yè)的技術(shù)吸奴。
數(shù)據(jù)結(jié)構(gòu)
1 紅黑樹(shù)
紅黑樹(shù)與AVL的比較:
AVL是嚴(yán)格平衡樹(shù),因此在增加或者刪除節(jié)點(diǎn)的時(shí)候缠局,根據(jù)不同情況则奥,旋轉(zhuǎn)的次數(shù)比紅黑樹(shù)要多;
紅黑是用非嚴(yán)格的平衡來(lái)?yè)Q取增刪節(jié)點(diǎn)時(shí)候旋轉(zhuǎn)次數(shù)的降低狭园;
所以簡(jiǎn)單說(shuō)读处,如果你的應(yīng)用中,搜索的次數(shù)遠(yuǎn)遠(yuǎn)大于插入和刪除唱矛,那么選擇AVL档泽,如果搜索俊戳,插入刪除次數(shù)幾乎差不多,應(yīng)該選擇RB馆匿。
1 臺(tái)階問(wèn)題/斐波納挈
一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)燥滑。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法渐北。
1
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)
第三種方法
1
2
3
4
5
def fib(n):
a, b = 0, 1
for _ in xrange(n):
a, b = b, a + b
return b
2 變態(tài)臺(tái)階問(wèn)題
一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)……它也可以跳上n級(jí)铭拧。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法赃蛛。
1
fib = lambda n: n if n < 2 else 2 * fib(n - 1)
3 矩形覆蓋
我們可以用21的小矩形橫著或者豎著去覆蓋更大的矩形。請(qǐng)問(wèn)用n個(gè)21的小矩形無(wú)重疊地覆蓋一個(gè)2*n的大矩形搀菩,總共有多少種方法呕臂?
第2n個(gè)矩形的覆蓋方法等于第2(n-1)加上第2*(n-2)的方法。
1
f = lambda n: 1 if n < 2 else f(n - 1) + f(n - 2)
4 楊氏矩陣查找
在一個(gè)m行n列二維數(shù)組中肪跋,每一行都按照從左到右遞增的順序排序歧蒋,每一列都按照從上到下遞增的順序排序。請(qǐng)完成一個(gè)函數(shù)州既,輸入這樣的一個(gè)二維數(shù)組和一個(gè)整數(shù)谜洽,判斷數(shù)組中是否含有該整數(shù)。
5 去除列表中的重復(fù)元素
用集合
1
list(set(l))
用字典
1
2
3
l1 = ['b','c','d','b','c','a','a']
l2 = {}.fromkeys(l1).keys()
print l2
用字典并保持順序
1
2
3
4
l1 = ['b','c','d','b','c','a','a']
l2 = list(set(l1))
l2.sort(key=l1.index)
print l2
1
2
3
l1 = ['b','c','d','b','c','a','a']
l2 = []
[l2.append(i) for i in l1 if not i in l2]
面試官提到的,先排序然后刪除.
6 鏈表成對(duì)調(diào)換
1->2->3->4轉(zhuǎn)換成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
7 創(chuàng)建字典的方法
1 直接創(chuàng)建
1
dict = {'name':'earth', 'port':'80'}
2 工廠(chǎng)方法
1
2
3
items=[('name','earth'),('port','80')]
dict2=dict(items)
dict1=dict((['name','earth'],['port','80']))
3 fromkeys()方法
1
2
3
4
dict1={}.fromkeys(('x','y'),-1)
dict={'x':-1,'y':-1}
dict2={}.fromkeys(('x','y'))
dict2={'x':None, 'y':None}
8 合并兩個(gè)有序列表
知乎遠(yuǎn)程面試要求編程
尾遞歸
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, [])
循環(huán)算法
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 交叉鏈表求交點(diǎn)
去哪兒的面試,沒(méi)做出來(lái).
class ListNode:
def init(self, x):
self.val = x
self.next = None
def node(l1, l2):
length1, lenth2 = 0, 0
求兩個(gè)鏈表長(zhǎng)度
while l1.next:
l1 = l1.next
length1 += 1
while l2.next:
l2 = l2.next
length2 += 1
長(zhǎng)的鏈表先走
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
10 二分查找
def binarySearch(l, t):
low, high = 0, len(l) - 1
while low < high:
print low, high
mid = (low + high) / 2
if l[mid] > t:
high = mid
elif l[mid] < t:
low = mid + 1
else:
return mid
return low if l[low] == t else False
if name == 'main':
l = [1, 4, 12, 45, 66, 99, 120, 444]
print binarySearch(l, 12)
print binarySearch(l, 1)
print binarySearch(l, 13)
print binarySearch(l, 444)
11 快排
1
2
3
4
5
6
7
8
9
10
11
12
def qsort(seq):
if seq==[]:
return []
else:
pivot=seq[0]
lesser=qsort([x for x in seq[1:] if x<pivot])
greater=qsort([x for x in seq[1:] if x>=pivot])
return lesser+[pivot]+greater
if name=='main':
seq=[5,6,78,9,0,-1,2,3,-65,12]
print(qsort(seq))
12 找零問(wèn)題
defcoinChange(values, money, coinsUsed):
valuesT[1:n]數(shù)組
valuesCounts 錢(qián)幣對(duì)應(yīng)的種類(lèi)數(shù)
money找出來(lái)的總錢(qián)數(shù)
coinsUsed 對(duì)應(yīng)于目前錢(qián)幣總數(shù)i所使用的硬幣數(shù)目
for cents in range(1, money+1):
minCoins = cents #從第一個(gè)開(kāi)始到money的所有情況初始
for value in values:
if value <= cents:
temp = coinsUsed[cents - value] + 1
if temp < minCoins:
minCoins = temp
coinsUsed[cents] = minCoins
print('面值為:{0} 的最小硬幣數(shù)目為:{1} '.format(cents, coinsUsed[cents]) )
if name == 'main':
values = [ 25, 21, 10, 5, 1]
money = 63
coinsUsed = {i:0 for i in range(money+1)}
coinChange(values, money, coinsUsed)
13 廣度遍歷和深度遍歷二叉樹(shù)
給定一個(gè)數(shù)組,構(gòu)建二叉樹(shù),并且按層次打印這個(gè)二叉樹(shù)
14 二叉樹(shù)節(jié)點(diǎn)
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)))
15 層次遍歷
def lookup(root):
stack = [root]
while stack:
current = stack.pop(0)
print current.data
if current.left:
stack.append(current.left)
if current.right:
stack.append(current.right)
16 深度遍歷
def deep(root):
if not root:
return
print root.data
deep(root.left)
deep(root.right)
if name == 'main':
lookup(tree)
deep(tree)
17 前中后序遍歷
深度遍歷改變順序就OK了
18 求最大樹(shù)深
1
2
3
4
def maxDepth(root):
if not root:
return 0
return max(maxDepth(root.left), maxDepth(root.right)) + 1
19 求兩棵樹(shù)是否相同
1
2
3
4
5
6
7
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
20 前序中序求后序
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
21 單鏈表逆置
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
Python Web相關(guān)
解釋一下 WSGI 和 FastCGI 的關(guān)系扛伍?
CGI全稱(chēng)是“公共網(wǎng)關(guān)接口”(CommonGateway Interface)龄减,HTTP服務(wù)器與你的或其它機(jī)器上的程序進(jìn)行“交談”的一種工具,其程序須運(yùn)行在網(wǎng)絡(luò)服務(wù)器上烟馅。 CGI可以用任何一種語(yǔ)言編寫(xiě),只要這種語(yǔ)言具有標(biāo)準(zhǔn)輸入咸灿、輸出和環(huán)境變量。如php,perl,tcl等诫龙。
FastCGI像是一個(gè)常駐(long-live)型的CGI析显,它可以一直執(zhí)行著,只要激活后签赃,不會(huì)每次都要花費(fèi)時(shí)間去fork一次(這是CGI最為人詬病的fork-and-execute模式)谷异。它還支持分布式的運(yùn)算, 即 FastCGI 程序可以在網(wǎng)站服務(wù)器以外的主機(jī)上執(zhí)行并且接受來(lái)自其它網(wǎng)站服務(wù)器來(lái)的請(qǐng)求。
FastCGI是語(yǔ)言無(wú)關(guān)的锦聊、可伸縮架構(gòu)的CGI開(kāi)放擴(kuò)展歹嘹,其主要行為是將CGI解釋器進(jìn)程保持在內(nèi)存中并因此獲得較高的性能。眾所周知孔庭,CGI解釋器的反復(fù)加載是CGI性能低下的主要原因尺上,如果CGI解釋器保持在內(nèi)存中并接受FastCGI進(jìn)程管理器調(diào)度材蛛,則可以提供良好的性能、伸縮性怎抛、Fail- Over特性等等卑吭。
WSGI的全稱(chēng)為: PythonWeb Server Gateway Interface v1.0 (Python Web 服務(wù)器網(wǎng)關(guān)接口),
它是 Python 應(yīng)用程序和 WEB 服務(wù)器之間的一種接口马绝。
它的作用豆赏,類(lèi)似于FCGI 或 FASTCGI 之類(lèi)的協(xié)議的作用。
WSGI 的目標(biāo)富稻,是要建立一個(gè)簡(jiǎn)單的普遍適用的服務(wù)器與 WEB 框架之間的接口掷邦。
Flup就是使用 Python 語(yǔ)言對(duì) WSGI 的一種實(shí)現(xiàn),是可以用于 Python 的應(yīng)用開(kāi)發(fā)中的一種工具或者說(shuō)是一種庫(kù)椭赋。
Spawn-fcgi是一個(gè)小程序抚岗,這個(gè)程序的作用是管理fast-cgi進(jìn)程,那么管理wsgi進(jìn)程也是沒(méi)有問(wèn)題的哪怔,功能和php-fpm類(lèi)似宣蔚。
故,簡(jiǎn)單地說(shuō)蔓涧,WSGI和FastCGI都是一種CGI件已,用于連接WEB服務(wù)器與應(yīng)用程序,而WSGI專(zhuān)指Python應(yīng)用程序元暴。而flup是WSGI的一種實(shí)現(xiàn)篷扩,Spawn-fcgi是用于管理flup進(jìn)程的一個(gè)工具,可以啟動(dòng)多個(gè)wsgi進(jìn)程茉盏,并管理它們鉴未。
解釋一下 Django 和 Tornado 的關(guān)系、差別
Django源自一個(gè)在線(xiàn)新聞 Web站點(diǎn)鸠姨,于 2005 年以開(kāi)源的形式被釋放出來(lái)铜秆。
Django 框架的核心組件有:
用于創(chuàng)建模型的對(duì)象關(guān)系映射為最終用戶(hù)設(shè)計(jì)的完美管理界面一流的 URL 設(shè)計(jì)設(shè)計(jì)者友好的模板語(yǔ)言緩存系統(tǒng)等等
它鼓勵(lì)快速開(kāi)發(fā),并遵循MVC設(shè)計(jì)。Django遵守 BSD版權(quán)讶迁,最新發(fā)行版本是Django
1.4连茧,于2012年03月23日發(fā)布.Django的主要目的是簡(jiǎn)便、快速的開(kāi)發(fā)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的網(wǎng)站巍糯。它強(qiáng)調(diào)代碼復(fù)用,多個(gè)組件可以很方便的以“插件”形式服務(wù)于整個(gè)框架啸驯,Django有許多功能強(qiáng)大的第三方插件,你甚至可以很方便的開(kāi)發(fā)出自己的工具包祟峦。這使得Django具有很強(qiáng)的可擴(kuò)展性罚斗。它還強(qiáng)調(diào)快速開(kāi)發(fā)和DRY(Do Not RepeatYourself)原則。
Tornado是 FriendFeed使用的可擴(kuò)展的非阻塞式 web 服務(wù)器及其相關(guān)工具的開(kāi)源版本宅楞。這個(gè) Web 框架看起來(lái)有些像 web.py 或者 Google 的 webapp针姿,不過(guò)為了能有效利用非阻塞式服務(wù)器環(huán)境袱吆,這個(gè) Web 框架還包含了一些相關(guān)的有用工具和優(yōu)化。
Tornado 和現(xiàn)在的主流 Web 服務(wù)器框架(包括大多數(shù)Python 的框架)有著明顯的區(qū)別:它是非阻塞式服務(wù)器距淫,而且速度相當(dāng)快绞绒。得利于其 非阻塞的方式和對(duì)epoll的運(yùn)用,Tornado 每秒可以處理數(shù)以千計(jì)的連接榕暇,這意味著對(duì)于實(shí)時(shí) Web服務(wù)來(lái)說(shuō)处铛,Tornado 是一個(gè)理想的 Web 框架。我們開(kāi)發(fā)這個(gè) Web 服務(wù)器的主要目的就是為了處理 FriendFeed 的實(shí)時(shí)功能 ——在 FriendFeed 的應(yīng)用里每一個(gè)活動(dòng)用戶(hù)都會(huì)保持著一個(gè)服務(wù)器連接拐揭。(關(guān)于如何擴(kuò)容 服務(wù)器,以處理數(shù)以千計(jì)的客戶(hù)端的連接的問(wèn)題奕塑。
解釋下django-debug-toolbar的使用
使用django開(kāi)發(fā)站點(diǎn)時(shí)堂污,可以使用django-debug-toolbar來(lái)進(jìn)行調(diào)試。在settings.py中添加’debug_toolbar.middleware.DebugToolbarMiddleware’到項(xiàng)目的MIDDLEWARE_CLASSES 內(nèi)龄砰。
解釋下Django使用redis緩存服務(wù)器
為了能在Django中使用redis盟猖,還需要安裝redis for Django的插件。然后在Django的settings中配置了』慌铮現(xiàn)在連接和配置都已經(jīng)完成了式镐,接下來(lái)是一個(gè)簡(jiǎn)單的例子:
from django.conf import settings
from django.core.cache import cache
read cache user id
def read_from_cache(self, user_name):
key = 'user_id_of_'+user_name
value = cache.get(key)
if value == None:
data = None
else:
data = json.loads(value)
return data
write cache user id
def write_to_cache(self, user_name):
key = 'user_id_of_'+user_name
cache.set(key, json.dumps(user_name), settings.NEVER_REDIS_TIMEOUT)
如何進(jìn)行Django單元測(cè)試
Django的單元測(cè)試使用python的unittest模塊,這個(gè)模塊使用基于類(lèi)的方法來(lái)定義測(cè)試固蚤。類(lèi)名為django.test.TestCase,繼承于python的unittest.TestCase娘汞。
from django.test import TestCase
from myapp.models import Animal
class AnimalTestCase(TestCase):
def setUp(self):
Animal.objects.create(name="lion", sound="roar")
Animal.objects.create(name="cat", sound="meow")
def test_animals_can_speak(self):
"""Animals that can speak are correctly identified"""
lion = Animal.objects.get(name="lion")
cat = Animal.objects.get(name="cat")
self.assertEqual(lion.speak(), 'The lion says "roar"')
self.assertEqual(cat.speak(), 'The cat says "meow"')
執(zhí)行目錄下所有的測(cè)試(所有的test*.py文件):運(yùn)行測(cè)試的時(shí)候,測(cè)試程序會(huì)在所有以test開(kāi)頭的文件中查找所有的test cases(inittest.TestCase的子類(lèi)),自動(dòng)建立測(cè)試集然后運(yùn)行測(cè)試夕玩。
1
$ python manage.py test
執(zhí)行animals項(xiàng)目下tests包里的測(cè)試:
$ python manage.py testanimals.tests
執(zhí)行animals項(xiàng)目里的test測(cè)試:
1
$ python manage.py testanimals
單獨(dú)執(zhí)行某個(gè)test case:
1
$ python manage.py testanimals.tests.AnimalTestCase
單獨(dú)執(zhí)行某個(gè)測(cè)試方法:
1
$ python manage.py testanimals.tests.AnimalTestCase.test_animals_can_speak
為測(cè)試文件提供路徑:
1
$ python manage.py testanimals/
通配測(cè)試文件名:
1
$ python manage.py test--pattern="tests_*.py"
啟用warnings提醒:
1
$ python -Wall manage.py test
解釋下Http協(xié)議
HTTP是一個(gè)屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議你弦,由于其簡(jiǎn)捷、快速的方式燎孟,適用于分布式超媒體信息系統(tǒng)禽作。
HTTP協(xié)議的主要特點(diǎn)可概括如下:
1.支持客戶(hù)/服務(wù)器模式。
2.簡(jiǎn)單快速:客戶(hù)向服務(wù)器請(qǐng)求服務(wù)時(shí)揩页,只需傳送請(qǐng)求方法和路徑旷偿。請(qǐng)求方法常用的有GET、HEAD爆侣、POST萍程。每種方法規(guī)定了客戶(hù)與服務(wù)器聯(lián)系的類(lèi)型不同。由于HTTP協(xié)議簡(jiǎn)單累提,使得HTTP服務(wù)器的程序規(guī)模小尘喝,因而通信速度很快。
3.靈活:HTTP允許傳輸任意類(lèi)型的數(shù)據(jù)對(duì)象斋陪。正在傳輸?shù)念?lèi)型由Content-Type加以標(biāo)記朽褪。
4.無(wú)連接:無(wú)連接的含義是限制每次連接只處理一個(gè)請(qǐng)求置吓。服務(wù)器處理完客戶(hù)的請(qǐng)求,并收到客戶(hù)的應(yīng)答后缔赠,即斷開(kāi)連接衍锚。采用這種方式可以節(jié)省傳輸時(shí)間。
5.無(wú)狀態(tài):HTTP協(xié)議是無(wú)狀態(tài)協(xié)議嗤堰。無(wú)狀態(tài)是指協(xié)議對(duì)于事務(wù)處理沒(méi)有記憶能力戴质。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息,則它必須重傳踢匣,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大告匠。另一方面,在服務(wù)器不需要先前信息時(shí)它的應(yīng)答就較快离唬。
解釋下Http請(qǐng)求頭和常見(jiàn)響應(yīng)狀態(tài)碼
Accept:指瀏覽器或其他客戶(hù)可以接愛(ài)的MIME文件格式后专。可以根據(jù)它判斷并返回適當(dāng)?shù)奈募袷健?/p>
Accept-Charset:指出瀏覽器可以接受的字符編碼输莺。英文瀏覽器的默認(rèn)值是ISO-8859-1.
Accept-Language:指出瀏覽器可以接受的語(yǔ)言種類(lèi)戚哎,如en或en-us,指英語(yǔ)嫂用。
Accept-Encoding:指出瀏覽器可以接受的編碼方式型凳。編碼方式不同于文件格式,它是為了壓縮文件并加速文件傳遞速度嘱函。瀏覽器在接收到Web響應(yīng)之后先解碼甘畅,然后再檢查文件格式。
Cache-Control:設(shè)置關(guān)于請(qǐng)求被代理服務(wù)器存儲(chǔ)的相關(guān)選項(xiàng)实夹。一般用不到橄浓。
Connection:用來(lái)告訴服務(wù)器是否可以維持固定的HTTP連接。HTTP/1.1使用Keep-Alive為默認(rèn)值亮航,這樣荸实,當(dāng)瀏覽器需要多個(gè)文件時(shí)(比如一個(gè)HTML文件和相關(guān)的圖形文件),不需要每次都建立連接缴淋。
Content-Type:用來(lái)表名request的內(nèi)容類(lèi)型准给。可以用HttpServletRequest的getContentType()方法取得重抖。
Cookie:瀏覽器用這個(gè)屬性向服務(wù)器發(fā)送Cookie露氮。Cookie是在瀏覽器中寄存的小型數(shù)據(jù)體,它可以記載和服務(wù)器相關(guān)的用戶(hù)信息钟沛,也可以用來(lái)實(shí)現(xiàn)會(huì)話(huà)功能畔规。
狀態(tài)代碼有三位數(shù)字組成,第一個(gè)數(shù)字定義了響應(yīng)的類(lèi)別恨统,且有五種可能取值:
1xx:指示信息–表示請(qǐng)求已接收叁扫,繼續(xù)處理
2xx:成功–表示請(qǐng)求已被成功接收三妈、理解、接受
3xx:重定向–要完成請(qǐng)求必須進(jìn)行更進(jìn)一步的操作
4xx:客戶(hù)端錯(cuò)誤–請(qǐng)求有語(yǔ)法錯(cuò)誤或請(qǐng)求無(wú)法實(shí)現(xiàn)
5xx:服務(wù)器端錯(cuò)誤–服務(wù)器未能實(shí)現(xiàn)合法的請(qǐng)求
常見(jiàn)狀態(tài)代碼莫绣、狀態(tài)描述畴蒲、說(shuō)明:
200 OK//客戶(hù)端請(qǐng)求成功
400 Bad Request //客戶(hù)端請(qǐng)求有語(yǔ)法錯(cuò)誤,不能被服務(wù)器所理解
401 Unauthorized //請(qǐng)求未經(jīng)授權(quán)对室,這個(gè)狀態(tài)代碼必須和WWW-Authenticate報(bào)頭域一起使用
403 Forbidden //服務(wù)器收到請(qǐng)求模燥,但是拒絕提供服務(wù)
404 Not Found //請(qǐng)求資源不存在,eg:輸入了錯(cuò)誤的URL
500 Internal Server Error //服務(wù)器發(fā)生不可預(yù)期的錯(cuò)誤
503 Server Unavailable //服務(wù)器當(dāng)前不能處理客戶(hù)端的請(qǐng)求掩宜,一段時(shí)間后可能恢復(fù)正常
eg:HTTP/1.1 200 OK (CRLF)
爬蟲(chóng)
一蔫骂、試列出至少三種目前流行的大型數(shù)據(jù)庫(kù)的名稱(chēng):________、_________牺汤、__________,其中您最熟悉的是__________,從__________年開(kāi)始使用纠吴。
Oracle,Mysql慧瘤,SQLServer Oracle根據(jù)自己情況
二、有表List固该,并有字段A锅减、B、C伐坏,類(lèi)型都是整數(shù)怔匣。表中有如下幾條記錄:
A
B
C
2
7
9
5
6
4
3
11
9
現(xiàn)在對(duì)該表一次完成以下操作:
查詢(xún)出B和C列的值,要求按B列升序排列
寫(xiě)出一條新的記錄桦沉,值為{7,9,8}
查詢(xún)C列每瞒,要求消除重復(fù)的值,按降序排列
寫(xiě)出完成完成以上操作的標(biāo)準(zhǔn)的SQL語(yǔ)句纯露,并且寫(xiě)出操作3的結(jié)果剿骨。
create table List(A int,B int,C int)
Select B,C from List order by B
Insert into List values(7,9,8)
Select distinct(C) from List order by desc;
984
三、請(qǐng)簡(jiǎn)要說(shuō)明視圖的作用
1.數(shù)據(jù)庫(kù)視圖隱藏了數(shù)據(jù)的復(fù)雜性埠褪。
2.數(shù)據(jù)庫(kù)視圖有利于控制用戶(hù)對(duì)表中某些列的訪(fǎng)問(wèn)浓利。
3.數(shù)據(jù)庫(kù)視圖使用戶(hù)查詢(xún)變得簡(jiǎn)單。
四钞速、列舉您使用過(guò)的python網(wǎng)絡(luò)爬蟲(chóng)所用到的網(wǎng)絡(luò)數(shù)據(jù)包(最熟悉的在前):
requests贷掖、urllib、urllib2渴语、httplib2
五苹威、列舉您使用過(guò)的python網(wǎng)絡(luò)爬蟲(chóng)所用到的解析數(shù)據(jù)包(最熟悉的在前):
BeautifulSoup、pyquery驾凶、Xpath牙甫、lxml
六掷酗、列舉您使用過(guò)的python中的編碼方式(最熟悉的在前):
UTF-8,ASCII腹暖,gbk
七汇在、python3.5語(yǔ)言中enumerate的意思是_______________________
對(duì)于一個(gè)可迭代的(iterable)/可遍歷的對(duì)象(如列表、字符串)脏答,enumerate將其組成一個(gè)索引序列糕殉,利用它可以同時(shí)獲得索引和值
enumerate多用于在for循環(huán)中得到計(jì)數(shù)
八、99的八進(jìn)制表示是_______________________
143
九殖告、請(qǐng)舉出三種常用的排序算法
冒泡阿蝶、選擇、快速
十黄绩、列出比較熟悉的爬蟲(chóng)框架
Scrapy
十一羡洁、用4、9爽丹、2筑煮、7四個(gè)數(shù)字,可以使用+粤蝎、-真仲、*和/,每個(gè)數(shù)字使用一次初澎,使表達(dá)式的結(jié)果為24秸应,表達(dá)式是_____________________________
(9+7-4)*2
十二、對(duì)你最有影響的或是您認(rèn)為最有價(jià)值的軟件方面的幾本書(shū)是碑宴?
十三软啼、您最熟悉的Unix環(huán)境是_____________.Unix下查詢(xún)環(huán)境變量的命令是________,查詢(xún)腳本定時(shí)任務(wù)的命令是____________________
1AIX,envcrontab
十四延柠、寫(xiě)出在網(wǎng)絡(luò)爬蟲(chóng)爬取數(shù)據(jù)的過(guò)程中祸挪,遇到的防爬蟲(chóng)問(wèn)題的解決方案
通過(guò)headers反爬蟲(chóng):解決策略,偽造headers
基于用戶(hù)行為反爬蟲(chóng):動(dòng)態(tài)變化去爬取數(shù)據(jù)贞间,模擬普通用戶(hù)的行為
基于動(dòng)態(tài)頁(yè)面的反爬蟲(chóng):跟蹤服務(wù)器發(fā)送的ajax請(qǐng)求匕积,模擬ajax請(qǐng)求
十五、閱讀以下Python程序
foriinrange(5,0,-1):
print(i)
請(qǐng)?jiān)谙旅鎸?xiě)出打印結(jié)果
54321
十六榜跌、在某系統(tǒng)中一個(gè)整數(shù)占用兩個(gè)八位字節(jié)闪唆,使用Python按下面的要求編寫(xiě)完整程序。
接收從標(biāo)準(zhǔn)輸入中依次輸入的五個(gè)數(shù)字钓葫,將其組合成為一個(gè)整數(shù)悄蕾,放入全局變量n中,隨后在標(biāo)準(zhǔn)輸出輸出這個(gè)整數(shù)。(ord(char)獲取字符ASCII值的函數(shù))
人帆调,從剛出生來(lái)到這個(gè)世界奠骄,便開(kāi)始探索這個(gè)世界。累了就歇會(huì)番刊,精神了就繼續(xù)探索含鳞,直至死亡。