1 Python字符串格式化中,%s和.format的主要區(qū)別是什么?
1.1、匿名tuple(推薦在參數(shù)少時(shí)用)
python用一個(gè)tuple將多個(gè)值傳遞給模板,每個(gè)值對(duì)應(yīng)一個(gè)格式符。
print ("I'm %s.I'm %d year old" % ('Vamei',99))
#引號(hào)內(nèi)的為模板 連接模板和tuple的"%"為格式化操作符
#或者將整個(gè)字符串表達(dá)式賦值給a,再輸出a.
a="I'm %s.I'm %d year old" % ('Vamei',99)
print (a)
2.字符串格式化(format)(不需要指定字符串還是數(shù)字類型)
自python2.6開始,新增了一種格式化字符串的函數(shù)str.format(),通過{ }和 . 來代替?zhèn)鹘y(tǒng)%
2.1位置參數(shù)
print ('my name is {},age is {}'.format('hoho',18))
print ('my name is {1},age is {0}'.format(18,'hoho'))
li=['hoho',18]
print ('my name is {1},age is {0}'.format(*li))
2.2 關(guān)鍵字參數(shù)
hash={'name':'hoho','age':18}
print 'my name is {name},age is {age}'.format(**hash)
print 'my name is {name},age is {age}'.format(name='hoho',age=18)
主要區(qū)別:不需要指定字符串還是數(shù)字類型
- 現(xiàn)有兩元組,(('a'),('b')), (('c'),('d')) 請(qǐng)用匿名函數(shù)將其變?yōu)閇{'a': 'c'}, {'b': 'd'}]
res = lambda t1,t2:[{i:j} for i,j in zip(t1,t2)]
print(res(t1,t2))
- 請(qǐng)給出二分法查找的python示例代碼
def func(l,aim):
mid = (len(l)-1)//2
print('mid===>',mid)
if l:
if aim > l[mid]:
func(l[mid+1:],aim)
elif aim< l[mid]:
func(l[:mid],aim)
elif aim == l[mid]:
print('There you are',l[mid])
else:
print('No match')
func(l,88)
- 如何給列表去重并保持原先順序不變。
示例一(簡(jiǎn)單粗暴):
l = [11,2,3,4,5,6,7,2,3,4]
new_l = []
for i in l:
if i not in new_l:
new_l.append(i)
print(new_l)
- 示例說明args和*kwargs 的作用
多個(gè)實(shí)參,放到一個(gè)元組里面,以開頭,可以傳多個(gè)參數(shù);*是形參中按照關(guān)鍵字傳值把多余的傳值以字典的方式呈現(xiàn)
*args:(表示的就是將實(shí)參中按照位置傳值,多出來的值都給args,且以元祖的方式呈現(xiàn))
**kwargs:(表示的就是形參中按照關(guān)鍵字傳值把多余的傳值以字典的方式呈現(xiàn))
- 解釋一下什么是匿名函數(shù),它有什么好處?
匿名
lambda x,y,z=1:x+y+z #與函數(shù)有相同的作用域,但是匿名意味著引用計(jì)數(shù)為0,使用一次就釋放,除非讓其有名字
func=lambda x,y,z=1:x+y+z
func(1,2,3)
#讓其有名字就沒有意義
好處:一次性使用,隨時(shí)隨地定義。
更易讀,因?yàn)槟莻€(gè)映射到列表上的函數(shù)具體是要做什么,非常一目了然。
- Python中如何書寫可變參數(shù)和關(guān)鍵字參數(shù)?
在Python中定義函數(shù),可以用必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù),這4種參數(shù)都可以一起使用,或者只用其中某些,但是請(qǐng)注意,參數(shù)定義的順序必須是:必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù)。
詳情請(qǐng)見鏈接:http://blog.csdn.net/zxy987872674/article/details/55252501
- Python 模塊中的match 和 search的區(qū)別
re.match() 總是從字符串“開頭”去匹配,并返回匹配的字符串的match對(duì)象。所以當(dāng)我用re.match()函數(shù)去匹配字符串非開頭部分的字符串時(shí),會(huì)返回NONE。
re.search()函數(shù)將對(duì)整個(gè)字符串進(jìn)行搜索,并返回第一個(gè)匹配的字符串的match對(duì)象。
- 1 and 2 和 1 or 2 的輸出結(jié)果分別是什么?為什么?
python 中的and從左到右計(jì)算表達(dá)式,若所有值均為真,則返回最后一個(gè)值,若存在假,返回第一個(gè)假值。
1 or 2 是因?yàn)?1 是非零 所以返回的值是1.
- 寫出一下打印結(jié)果
print((i%2 for i in range(10))) #<generator object <genexpr> at 0x000001C577DDE258>
print([i%2 for i in range(10)]) #[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
總結(jié):
1.把列表解析的[]換成()得到的就是生成器表達(dá)式
2.列表解析與生成器表達(dá)式都是一種便利的編程方式,只不過生成器表達(dá)式更節(jié)省內(nèi)存
3.Python不但使用迭代器協(xié)議,讓for循環(huán)變得更加通用。大部分內(nèi)置函數(shù),也是使用迭代器協(xié)議訪問對(duì)象的。例如, sum函數(shù)是Python的內(nèi)置函數(shù),該函數(shù)使用迭代器協(xié)議訪問對(duì)象,而生成器實(shí)現(xiàn)了迭代器協(xié)議。
-
python2 和 Python3 有哪些顯著的區(qū)別?
. 在 Python3 中 print要加括號(hào)。
.Python3 中,數(shù)字除法將會(huì)帶小數(shù)點(diǎn)。
.字符編碼。
image.png
詳情:
英文網(wǎng):
http://blog.teamtreehouse.com/python-2-vs-python-3
中文網(wǎng):
http://www.runoob.com/python/python-2x-3x.html
-
請(qǐng)描述 unicode,utf-8, gbk之間的關(guān)系。
unicode----->encode-------->utf-8
utf-8-------->decode---------->unicode
迭代器,生成器,裝飾器
迭代器
#迭代器即迭代的工具,那什么是迭代呢?
#迭代是一個(gè)重復(fù)的過程,每次重復(fù)即一次迭代,并且每次迭代的結(jié)果都是下一次迭代的初始值
while True: #只是單純地重復(fù),因而不是迭代
print('===>')
l=[1,2,3]
count=0
while count < len(l): #迭代
print(l[count])
count+=1
為何要有迭代器?什么是可迭代對(duì)象?什么是迭代器對(duì)象?
#1、為何要有迭代器?
對(duì)于序列類型:字符串、列表、元組,我們可以使用索引的方式迭代取出其包含的元素。
但對(duì)于字典、集合、文件等類型是沒有索引的,若還想取出其內(nèi)部包含的元素,
則必須找出一種不依賴于索引的迭代方式,這就是迭代器
#2、什么是可迭代對(duì)象?
可迭代對(duì)象指的是內(nèi)置有__iter__方法的對(duì)象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__
#3、什么是迭代器對(duì)象?
可迭代對(duì)象執(zhí)行obj.__iter__()得到的結(jié)果就是迭代器對(duì)象
而迭代器對(duì)象指的是即內(nèi)置有__iter__又內(nèi)置有__next__方法的對(duì)象
文件類型是迭代器對(duì)象
open('a.txt').__iter__()
open('a.txt').__next__()
#4、注意:
迭代器對(duì)象一定是可迭代對(duì)象,而可迭代對(duì)象不一定是迭代器對(duì)象
迭代器對(duì)象的使用
dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__() #得到迭代器對(duì)象,迭代器對(duì)象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
iter_dic.__iter__() is iter_dic #True
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
# print(iter_dic.__next__()) #拋出異常StopIteration,或者說結(jié)束標(biāo)志
#有了迭代器,我們就可以不依賴索引迭代取值了
iter_dic=dic.__iter__()
while 1:
try:
k=next(iter_dic)
print(dic[k])
except StopIteration:
break
迭代器優(yōu)缺點(diǎn)
#優(yōu)點(diǎn):
- 提供一種統(tǒng)一的、不依賴于索引的迭代方式
- 惰性計(jì)算,節(jié)省內(nèi)存
#缺點(diǎn):
- 無法獲取長(zhǎng)度(只有在next完畢才知道到底有幾個(gè)值)
- 一次性的,只能往后走,不能往前退
生成器
我們知道的迭代器有兩種:一種是調(diào)用方法直接返回的,一種是可迭代對(duì)象通過執(zhí)行iter方法得到的,迭代器有的好處是可以節(jié)省內(nèi)存。
如果在某些情況下,我們也需要節(jié)省內(nèi)存,就只能自己寫。我們自己寫的這個(gè)能實(shí)現(xiàn)迭代器功能的東西就叫生成器。
Python中提供的生成器:
1.生成器函數(shù):常規(guī)函數(shù)定義,但是,使用yield語(yǔ)句而不是return語(yǔ)句返回結(jié)果。yield語(yǔ)句一次返回一個(gè)結(jié)果,在每個(gè)結(jié)果中間,掛起函數(shù)的狀態(tài),以便下次重它離開的地方繼續(xù)執(zhí)行
2.生成器表達(dá)式:類似于列表推導(dǎo),但是,生成器返回按需產(chǎn)生結(jié)果的一個(gè)對(duì)象,而不是一次構(gòu)建一個(gè)結(jié)果列表
生成器Generator:
本質(zhì):迭代器(所以自帶了__iter__方法和__next__方法,不需要我們?nèi)?shí)現(xiàn))
特點(diǎn):惰性運(yùn)算,開發(fā)者自定義
生成器函數(shù):
一個(gè)包含yield關(guān)鍵字的函數(shù)就是一個(gè)生成器函數(shù)。yield可以為我們從函數(shù)中返回值,但是yield又不同于return,return的執(zhí)行意味著程序的結(jié)束,調(diào)用生成器函數(shù)不會(huì)得到返回的具體的值,而是得到一個(gè)可迭代的對(duì)象。每一次獲取這個(gè)可迭代對(duì)象的值,就能推動(dòng)函數(shù)的執(zhí)行,獲取新的返回值。直到函數(shù)執(zhí)行結(jié)束。
#只要函數(shù)內(nèi)部包含有yield關(guān)鍵字,那么函數(shù)名()的到的結(jié)果就是生成器,并且不會(huì)執(zhí)行函數(shù)內(nèi)部代碼
def func(): print('====>first') yield 1
print('====>second') yield 2
print('====>third') yield 3
print('====>end')
g=func() print(g) #<generator object func at 0x0000000002184360> </pre>
迭代器,生成器詳情請(qǐng)見:
https://www.zhihu.com/question/20829330
裝飾器
#開放封閉原則:對(duì)修改封閉,對(duì)擴(kuò)展開放
裝飾器他人的器具,本身可以是任意可調(diào)用對(duì)象,被裝飾者也可以是任意可調(diào)用對(duì)象。
強(qiáng)調(diào)裝飾器的原則:1 不修改被裝飾對(duì)象的源代碼 2 不修改被裝飾對(duì)象的調(diào)用方式
裝飾器的目標(biāo):在遵循1和2的前提下,為被裝飾對(duì)象添加上新功能
- def func(a,b=[]) 這樣的寫法有什么陷阱?
Python函數(shù)在定義的時(shí)候,默認(rèn)參數(shù)b的值就被計(jì)算出來了,即[],因?yàn)槟J(rèn)參數(shù)b也是一個(gè)變量,它指向?qū)ο骩],每次調(diào)用該函數(shù),如果改變了b的內(nèi)容,則下次調(diào)用時(shí),默認(rèn)參數(shù)的內(nèi)容就變了,不再是函數(shù)定義時(shí)的[]了。
所以,定義默認(rèn)參數(shù)要牢記一點(diǎn):默認(rèn)參數(shù)必須指向不變對(duì)象!
- python 實(shí)現(xiàn)九九乘法表 兩種方式?
方式一:
for i in range(1,10):
for j in range(1,i+1):
print('%s * %s = %s '%(i,j,i*j), end=' ')
print(' ')
方式二:
print( '\n'.join([' '.join(['%s*%s=%-2s' % (y,x,x*y) for y in range(1,x+1)]) for x in range(1,10)]))
- 如何在Python中拷貝一個(gè)對(duì)象,并說出他們的區(qū)別。
拷貝的方法有兩種:深拷貝和淺拷貝 copy.copy() and copy.deepcopy().
區(qū)別,官網(wǎng)鏈接:https://docs.python.org/dev/library/copy.html
—–我們尋常意義的復(fù)制就是深復(fù)制,即將被復(fù)制對(duì)象完全再?gòu)?fù)制一遍作為獨(dú)立的新個(gè)體單獨(dú)存在。所以改變?cè)斜粡?fù)制對(duì)象不會(huì)對(duì)已經(jīng)復(fù)制出來的新對(duì)象產(chǎn)生影響。
—–而淺復(fù)制并不會(huì)產(chǎn)生一個(gè)獨(dú)立的對(duì)象單獨(dú)存在,他只是將原有的數(shù)據(jù)塊打上一個(gè)新標(biāo)簽,所以當(dāng)其中一個(gè)標(biāo)簽被改變的時(shí)候,數(shù)據(jù)塊就會(huì)發(fā)生變化,另一個(gè)標(biāo)簽也會(huì)隨之改變。這就和我們尋常意義上的復(fù)制有所不同了。
- 談?wù)勀銓?duì)Python裝飾器的理解。
裝飾器本質(zhì)上是一個(gè)Python的函數(shù),他可以讓其他函數(shù)在不需要任何代碼變動(dòng)的前提下增加額外功能,裝飾器的返回值也是一個(gè)函數(shù)對(duì)象。它有很多應(yīng)用場(chǎng)景,比如:插入日志,事務(wù)處理,緩存,權(quán)限等。概括的總結(jié):裝飾器的作用就是為已經(jīng)存在的對(duì)象添加額外的功能。
def outer(func):
def inner(*args,**kwargs):
'''
before the decorator
:param args:
:param kwargs:
:return:
'''
ret = func(*args,**kwargs)
'''
after the decorator
'''
return ret
return inner
@outer
def bar():
print('from bar')
bar()
- Python基礎(chǔ):
計(jì)算列表中元素的個(gè)數(shù)和向末尾追加元素所用的方法? len(), append().
判斷字典中有沒有某個(gè)key的方法? 用get('key')方法,若沒有, 返回值是None
現(xiàn)有my_list = range(100)
#取前三個(gè)元素
print(my_list[0:4])
#取倒數(shù)第二個(gè)元素
print(my_list[-2])
#取最后十個(gè)元素
print(my_list[-10:])
- 簡(jiǎn)述Python中的垃圾回收機(jī)制。
官網(wǎng)鏈接:
https://docs.python.org/3/library/gc.html#module-gc
Python在內(nèi)存中存儲(chǔ)了每個(gè)對(duì)象的引用計(jì)數(shù)(reference count)。如果計(jì)數(shù)值變成0,那么相應(yīng)的對(duì)象就會(huì)小時(shí),分配給該對(duì)象的內(nèi)存就會(huì)釋放出來用作他用。
偶爾也會(huì)出現(xiàn)引用循環(huán)(reference cycle)。垃圾回收器會(huì)定時(shí)尋找這個(gè)循環(huán),并將其回收。舉個(gè)例子,假設(shè)有兩個(gè)對(duì)象o1和o2,而且符合o1.x == o2和o2.x == o1這兩個(gè)條件。如果o1和o2沒有其他代碼引用,那么它們就不應(yīng)該繼續(xù)存在。但它們的引用計(jì)數(shù)都是1。
Python中使用了某些啟發(fā)式算法(heuristics)來加速垃圾回收。例如,越晚創(chuàng)建的對(duì)象更有可能被回收。對(duì)象被創(chuàng)建之后,垃圾回收器會(huì)分配它們所屬的代(generation)。每個(gè)對(duì)象都會(huì)被分配一個(gè)代,而被分配更年輕代的對(duì)象是優(yōu)先被處理的。
- Python的名稱空間問題:
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)
打印結(jié)果
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
https://docs.python.org/3/tutorial/classes.html#a-first-look-at-classes
- 如何判斷一個(gè)變量是否是字符串?
a = 'sdsdf'
print(isinstance(a,str))
Differences between list and tuple in python.
link:
http://www.hacksparrow.com/python-difference-between-list-and-tuple.htmlrange 和 xrange的區(qū)別
首先,xrange在python3中已經(jīng)不適用。
range:
函數(shù)說明:range([start,] stop[, step]),根據(jù)start與stop指定的范圍以及step設(shè)定的步長(zhǎng),生成一個(gè)列表。
xrange:
xrange與range類似,只是返回的是一個(gè)“xrange object”對(duì)象,而非數(shù)組list。要生成很大的數(shù)字序列的時(shí)候,用xrange會(huì)比range性能優(yōu)很多,因?yàn)椴恍枰簧蟻砭烷_辟一塊很大的內(nèi)存空間,這兩個(gè)基本上都是在循環(huán)的時(shí)候用。
區(qū)別:
range 會(huì)生成一個(gè)list對(duì)象,而xrange會(huì)返回一個(gè)生成器對(duì)象。
- '1','2','3' 如何 變成 ['1','2','3']?
x = '1','2','3'
li = []
for i in x:
li.append(i)
print(li)
'1','2','3' 如何 變成 [1,2,3]
x = '1','2','3'
li = []
for i in x:
li.append(int(i))
print(li)
- is 和 == 的區(qū)別
Python中的對(duì)象包含三要素:id、type、value
其中id用來唯一標(biāo)識(shí)一個(gè)對(duì)象,type標(biāo)識(shí)對(duì)象的類型,value是對(duì)象的值
is判斷的是a對(duì)象是否就是b對(duì)象,是通過id來判斷的
== is for comparsion.
= is assignment.
- 一行實(shí)現(xiàn)[1,4,9,16,25,36,49,81,100]
target = list(map(lambda x: x*x,[1,2,3,4,5,6,7,8,9,10]))
- print(map(str,[1,2,3,4])) 輸入的是啥?
map object
- PEP8開發(fā)規(guī)范:
https://www.python.org/dev/peps/pep-0008/ - 請(qǐng)簡(jiǎn)單解釋Python中的 staticmethod(靜態(tài)方法)和 classmethod(類方法),并補(bǔ)全下面的代碼
方法包括:普通方法、靜態(tài)方法和類方法,三種方法在內(nèi)存中都?xì)w屬于類,區(qū)別在于調(diào)用方式不同。
普通方法:由對(duì)象調(diào)用;至少一個(gè)self參數(shù);執(zhí)行普通方法時(shí),自動(dòng)將調(diào)用該方法的對(duì)象賦值給self;
類方法:由類調(diào)用; 至少一個(gè)cls參數(shù);執(zhí)行類方法時(shí),自動(dòng)將調(diào)用該方法的類復(fù)制給cls;
靜態(tài)方法:由類調(diào)用;無默認(rèn)參數(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()
#調(diào)用foo函數(shù),參數(shù)傳入1
a.foo(1)
#調(diào)用class_foo函數(shù),參數(shù)傳入1
a.class_foo(1)
A.class_foo(1)
#調(diào)用static_foo函數(shù),參數(shù)傳入1
a.static_foo(1)
A.static_foo(1)
30、Python如何實(shí)現(xiàn)單例模式?
1 基于類 注意: 加鎖,否則多線程模式會(huì)報(bào)錯(cuò)
import time,threading
class Foo(object):
lock = threading.Lock()
def __init__(self):
time.sleep(1)
@classmethod
def instance(cls,*args,**kwargs):
if not hasattr(cls,'_instance'):
with Foo.lock:
if not hasattr(cls,'_instance'):
obj = cls(*args,**kwargs)
setattr(cls,'_instance',obj)
return cls._instance
def func(arg):
obj = Foo.instance()
print(obj)
for i in range(10):
t = threading.Thread(target=func,args=(i,))
t.start()
2 . 基于new方法,也要加鎖,原理同上
import threading,time
class Singleton(object):
lock = threading.Lock()
def __init__(self):
time.sleep(1)
def __new__(cls, *args, **kwargs):
if not hasattr(cls,'_instance'):
with Singleton.lock:
if not hasattr(cls,'_instance'):
Singleton._instance = object.__new__(cls,*args,**kwargs)
return Singleton._instance
def task(args):
obj = Singleton()
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=(i,))
t.start()
- 基于metaclass 加鎖,原理同上
class MyType(type):
lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if not hasattr(cls,'_instance'):
with MyType.lock:
if not hasattr(cls,'_instance'):
cls._instance = super(MyType,cls).__call__(*args, **kwargs)
return cls._instance
class Foo(metaclass=MyType):
def __init__(self):
time.sleep(1)
def task():
obj = Foo()
print(obj)
for i in range(10):
t = threading.Thread(target=task,)
t.start()
31、請(qǐng)寫出一段代碼去除list里面的重復(fù)元素
法一:print(list(set(li)))
法二:for i in li:
if li.count(i)>1:
li.remove(i)
print(li)
32、如何用Python刪除一個(gè)文件?
import os
os.remove(r'D:\ggg\fileobj')
os.remove('路徑')
- 面相對(duì)象
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __hash__(self):
return hash(self.name+self.sex)
def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:return True
p_lst = []
for i in range(84):
p_lst.append(Person('egon',i,'male'))
print(p_lst) ####每一個(gè)Person對(duì)象的內(nèi)存地址,打印在一個(gè)列表里。
print(set(p_lst)) ######一個(gè)Person對(duì)象的內(nèi)存地址 {<__main__.Person object at 0x000002A1C8566A58>}
34、Python如何生成隨機(jī)數(shù)
import random
print(random.randint(1,10))
35、如何在一個(gè)function里面設(shè)置一個(gè)全局的變量
n = 1
def func():
global n ##聲明n是全局變量
n = 2
print('inside the function',n) # n = 2
print('outside the funciton',n) #調(diào)func之前,n=1
func()
print(n) #調(diào)func之后,n的值被修改為2
36、介紹except的用法和作用
答案:http://www.lxweimin.com/p/1c3162189f54
37、
請(qǐng)用Python寫一個(gè)獲取用戶輸入數(shù)字,并根據(jù)數(shù)字大小輸出不同信息的腳本
while 1:
digit_input = int(input('Please enter a integer: ').strip())
if not digit_input:
continue
else:
if digit_input>0:
print('This is a positive number')
elif digit_input == 0:
print('This is a zero')
elif digit_input <0:
print('This is a negative number')
38、請(qǐng)解釋生成器與函數(shù)的不同,并實(shí)現(xiàn)和簡(jiǎn)單地使用生成器。
先看生成器:
def gensquares(N):
for i in range(N):
yield i **2
for item in gensquares(5):
print(item)
再看普通函數(shù):
def gensquares(N):
res = []
for i in range(N):
res.append(i*i)
return res
for item in gensquares(5):
print(item)
總結(jié):
1、語(yǔ)法上和函數(shù)類似: 生成器函數(shù)和常規(guī)函數(shù)幾乎是一模一樣的。它們都是使用def語(yǔ)句進(jìn)行定義,區(qū)別在于,生成器使用yield語(yǔ)句返回一個(gè)值,而常規(guī)函數(shù)使用return語(yǔ)句返回一個(gè)值。
2、自動(dòng)實(shí)現(xiàn)迭代協(xié)議:對(duì)于生成器,Python會(huì)自動(dòng)實(shí)現(xiàn)迭代協(xié)議,以便應(yīng)用到迭代背景中(如for循環(huán)等),由于生成器自動(dòng)實(shí)現(xiàn)了迭代協(xié)議,所以,我們可以調(diào)用它的next方法,并且,在沒有值可以返回的時(shí)候,生成器自動(dòng)產(chǎn)生StopIteration異常。
- 狀態(tài)掛起,生成器使用yield語(yǔ)句返回一個(gè)值。yield語(yǔ)句掛起該生成器函數(shù)的狀態(tài),保留足夠的信息,以便之后從它離開的地方繼續(xù)執(zhí)行
39、請(qǐng)輸入一個(gè)字符串,打印結(jié)果為倒敘
while 1:
a = input('please enter a string ')
print(a[::-1])
40、請(qǐng)寫出自己的算法,按升序合并如下列表
list1 = [2,3,8,4,9,5,6]
list2 = [5,6,10,17,11,2]
list1 = [2,3,8,4,9,5,6]
list2 = [5,6,10,17,11,2]
list1.extend(list2)
print(sorted(list(set(list1))))
41、已排好序的列表aList和字符char1,表示aList中存在char1則返回False,不存在則返回True的表達(dá)式:
expression = lambda a:False if a in aList else True
print(expression('pea'))
42、不依賴中間變量,交換a和b的值
a = a + b
b = a - b
a = a - b
43、求aList 和 bList交集的表達(dá)式:
aList&bList
44、現(xiàn)有列表 aList = [3,1,-4,-2] 按照其元素的絕對(duì)值大小進(jìn)行排序的表達(dá)式是sorted(abs(i) for i in a)
45、獲取Python解釋器版本的方法是:
import sys
print(sys.version)
46、到底什么是Python?你可以在回答中與其他技術(shù)進(jìn)行對(duì)比(也鼓勵(lì)這樣做)。
關(guān)鍵點(diǎn):
(1)Python是一門解釋型語(yǔ)言,這就是說與C語(yǔ)言和C的衍生語(yǔ)言不同,Python代碼運(yùn)行之前不需要編譯,其他解釋型語(yǔ)言還包括Ruby和PHP。
(2)Python是動(dòng)態(tài)類型語(yǔ)言,在聲明變量時(shí),不需要聲明變量的類型。
(3)Python非常適合面向?qū)ο缶幊蹋∣OP),因?yàn)樗С滞ㄟ^組合(composition)和繼承(inheritance)的方式定義類(class)。
(4)Python代碼編寫快,但是運(yùn)行速度比編譯語(yǔ)言通常要慢。好在Python允許加入基于C語(yǔ)言編寫的擴(kuò)展,因此我們能夠優(yōu)化代碼,消除瓶頸,這點(diǎn)通常是可以實(shí)現(xiàn)的。numpy就是一個(gè)很好的例子。
(5)Python的用途非常廣---網(wǎng)絡(luò)應(yīng)用,自動(dòng)化,科學(xué)建模,大數(shù)據(jù)應(yīng)用,等等。它通常也被用作膠水語(yǔ)言,幫助其他語(yǔ)言和組件改善運(yùn)行狀況。
47、如果模塊是被導(dǎo)入的,則name的值是py文件名,如果模塊時(shí)被執(zhí)行的,則name的值是'main'.
48、要保持追蹤內(nèi)存中的狀態(tài), python使用了引用計(jì)數(shù)這一項(xiàng)技術(shù), 就是python內(nèi)部記錄著所有使用中的對(duì)象各有多少引用.
49、簡(jiǎn)述一下Python內(nèi)存中的垃圾回收機(jī)制。
Python在內(nèi)存中存儲(chǔ)了每個(gè)對(duì)象的引用計(jì)數(shù)(reference count)。如果計(jì)數(shù)值變?yōu)?,那么相應(yīng)的對(duì)象就會(huì)消失。分配給該對(duì)象的內(nèi)存就會(huì)釋放出來用作他用。
偶爾也會(huì)出現(xiàn)引用循環(huán)。垃圾回收器會(huì)定時(shí)尋找這個(gè)循環(huán),并將其回收。
Python中還使用了某些啟示算法來加速回收。
50、從輸入www.baidu.com到頁(yè)面返回,中間都發(fā)生了什么?
1、瀏覽器向 DNS 服務(wù)器請(qǐng)求解析該 URL 中的域名所對(duì)應(yīng)的 IP 地址;
2、解析出 IP 地址后,根據(jù)該 IP 地址和默認(rèn)端口 80,和服務(wù)器建立[TCP連接]
3、瀏覽器發(fā)出讀取文件(URL 中域名后面部分對(duì)應(yīng)的文件)的HTTP 請(qǐng)求,該請(qǐng)求報(bào)文作為 TCP 三次握手的第三個(gè)報(bào)文的數(shù)據(jù)發(fā)送給服務(wù)器;
4、服務(wù)器對(duì)瀏覽器請(qǐng)求作出響應(yīng),并把對(duì)應(yīng)的 html 文本發(fā)送給瀏覽器;
5、釋放 TCP連接;
6、瀏覽器將該 html 文本并顯示內(nèi)容;
51、HTTP狀態(tài)碼有什么不同,列出你知道的HTTP狀態(tài)代碼,然后請(qǐng)講出他們都是什么意思。
狀態(tài)代碼有三位數(shù)字組成,第一個(gè)數(shù)字定義了響應(yīng)的類別,共分五種類別:
1xx:指示信息--表示請(qǐng)求已接收,繼續(xù)處理
2xx:成功--表示請(qǐng)求已被成功接收、理解、接受
3xx:重定向--要完成請(qǐng)求必須進(jìn)行更進(jìn)一步的操作
4xx:客戶端錯(cuò)誤--請(qǐng)求有語(yǔ)法錯(cuò)誤或請(qǐng)求無法實(shí)現(xiàn)
5xx:服務(wù)器端錯(cuò)誤--服務(wù)器未能實(shí)現(xiàn)合法的請(qǐng)求
常見狀態(tài)碼:
200 OK//客戶端請(qǐng)求成功
400 Bad Request//客戶端請(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)前不能處理客戶端的請(qǐng)求,一段時(shí)間后可能恢復(fù)正常
52、lambda表達(dá)式和列表推導(dǎo)式:
l1 = [i for i in range(10)]
l2 = [lambda: i for i in range(10)]
print(l1[0]) ###0
print(l2[0]) #<function <listcomp>.<lambda> at 0x000002003F170B70>
print(l2[0]()) #9
53、eval和exec的區(qū)別
eval有返回值
exec沒有返回值
print(eval('2+3')) #5 eval中的參數(shù)是一個(gè)字符串,可以把這個(gè)字符串當(dāng)作表達(dá)式求值
exec('a=2+1') #exec中的參數(shù)是 a
print(a) # 3
exec("print('1+1')") # 1+1
eval還可以將字符串轉(zhuǎn)換成對(duì)象
class obj(object):
pass
a = eval('obj()')
print(a,type(a)) #<__main__.obj object at 0x000001F1F6897550> <class '__main__.obj'>
53、cookie和session的區(qū)別
a、session在服務(wù)器端,cookie在客戶端(瀏覽器)
b、session默認(rèn)被存在服務(wù)器的一個(gè)文件里(不是內(nèi)存)
c、sesison 的運(yùn)行依賴session_id, 而session_id是存在cookie中,也就是說,如果瀏覽器禁用了cookie,同時(shí)session也會(huì)失效(但是可以通過其他方式實(shí)現(xiàn),比如在URL中傳遞session_id)
d、session可以放在文件、數(shù)據(jù)庫(kù)、或內(nèi)存中都可以、
e、用戶驗(yàn)證場(chǎng)景通常會(huì)用session
f、維持一個(gè)會(huì)話的核心就是客戶端的唯一標(biāo)識(shí),即session_id
54、http是有狀態(tài)協(xié)議還是無狀態(tài)協(xié)議?如何從兩次請(qǐng)求中判斷是否是同一用戶?
無狀態(tài)協(xié)議。判斷session_id 是否是相同。
55、有一個(gè)數(shù)組[3,4,1,2,5,6,6,5,4,3,3]請(qǐng)寫一個(gè)函數(shù),找出該數(shù)組中沒有重復(fù)的書的總和。
def MyPlus(l):
new_l = []
for i in l:
if i not in new_l:
new_l.append(i)
return sum(new_l)
print(MyPlus(l = [2,3,4,4,5,5,6,7,8]))
56、Python一行print出1~100的偶數(shù)列表:
print([i for i in range(1,100) if i % 2 == 0 ])
57、1,2,3,4,5能組成多少個(gè)互不相同且無重復(fù)的元素?
nums = []
for i in range(1,6):
for j in range(1,6):
for k in range(1,6):
if i != j and j != k and i !=k:
new_num = i*100 + k*10 + j
if new_num not in nums:
nums.append(new_num)
print(nums)
58、請(qǐng)寫出五種http的請(qǐng)求方法:
get,post,put,delete,head,connect.
59、描述多進(jìn)程開發(fā)中join與daemon的區(qū)別
守護(hù)進(jìn)程(daemon)
主進(jìn)程創(chuàng)建守護(hù)進(jìn)程
其一:守護(hù)進(jìn)程會(huì)在主進(jìn)程代碼執(zhí)行結(jié)束后就終止
其二:守護(hù)進(jìn)程內(nèi)無法開啟子進(jìn)程,否則拋出異常:AssertionError: daemonic processes are not allowed to have children
注意:進(jìn)程之間是相互獨(dú)立的,主進(jìn)程的代碼運(yùn)行結(jié)束,守護(hù)進(jìn)程隨即終止
p.join([timeout]): 主進(jìn)程等待相應(yīng)的子進(jìn)程p終止(強(qiáng)調(diào):是主線程處于等的狀態(tài),而p是處于運(yùn)行的狀態(tài))。需要強(qiáng)調(diào)的是p.join()只能join住start開始的進(jìn)程,而不能join住run開啟的進(jìn)程。
60、簡(jiǎn)述GIL對(duì)Python性能的影響。
由于GIL(Global Interpreter Lock)的影響,Python無法利用多核優(yōu)勢(shì)。
GIL本質(zhì)就是一把互斥鎖,既然是互斥鎖,所有互斥鎖的本質(zhì)都是一樣--將并發(fā)運(yùn)行變成串行,以此來控制同一時(shí)間內(nèi)共享的數(shù)據(jù)只能被一個(gè)任務(wù)修改,進(jìn)而保證數(shù)據(jù)安全。
可以肯定的一點(diǎn)是:保護(hù)不同的數(shù)據(jù)的安全,就應(yīng)該加不同的鎖。
現(xiàn)在的計(jì)算機(jī)基本上都是多核,python對(duì)于計(jì)算密集型的任務(wù)開多線程的效率并不能帶來多大性能上的提升,甚至不如串行(沒有大量切換),但是,對(duì)于IO密集型的任務(wù)效率還是有顯著提升的。
因此,對(duì)于IO密集型的任務(wù),Python多線程更合適。
61、執(zhí)行Python腳本的兩種方式
1、./run.py.shell直接調(diào)用python腳本
2、python run.py 調(diào)用python 解釋器來調(diào)用python腳本
62、TCP協(xié)議和UDP協(xié)議的區(qū)別是什么?
1、TCP協(xié)議是有連接的,有連接的意思是開始傳輸實(shí)際數(shù)據(jù)之前TCP的客戶端和服務(wù)器端必須通過三次握手建立連接,會(huì)話結(jié)束后也要結(jié)束連接。而UDP是無連接的
2、TCP協(xié)議保證數(shù)據(jù)發(fā)送,按序送達(dá),提供超時(shí)重傳保證數(shù)據(jù)可靠性,但是UDP不保證按序到達(dá),甚至不能保證到達(dá),還是努力交付,即便是按序發(fā)送的序列,也不保證按序送到。
3、TCP協(xié)議所需資源多,TCP首部需20個(gè)字節(jié)(不算可選項(xiàng)),UDP首部字段只需8個(gè)字節(jié)。
4、TCP有流量控制和擁塞控制,UDP沒有。網(wǎng)絡(luò)擁堵不會(huì)影響發(fā)送端的發(fā)送速率。
5、TCP面向的字節(jié)流的服務(wù),UDP面向的是報(bào)文的服務(wù)。
三次握手建立連接時(shí),發(fā)送方再次發(fā)送確認(rèn)的必要性?
主 要是為了防止已失效的連接請(qǐng)求報(bào)文段突然又傳到了B,因而產(chǎn)生錯(cuò)誤。假定出現(xiàn)一種異常情況,即A發(fā)出的第一個(gè)連接請(qǐng)求報(bào)文段并沒有丟失,而是在某些網(wǎng)絡(luò)結(jié) 點(diǎn)長(zhǎng)時(shí)間滯留了,一直延遲到連接釋放以后的某個(gè)時(shí)間才到達(dá)B,本來這是一個(gè)早已失效的報(bào)文段。但B收到此失效的連接請(qǐng)求報(bào)文段后,就誤認(rèn)為是A又發(fā)出一次 新的連接請(qǐng)求,于是就向A發(fā)出確認(rèn)報(bào)文段,同意建立連接。假定不采用三次握手,那么只要B發(fā)出確認(rèn),新的連接就建立了,這樣一直等待A發(fā)來數(shù)據(jù),B的許多 資源就這樣白白浪費(fèi)了。
四次揮手釋放連接時(shí),等待2MSL的意義?
第 一,為了保證A發(fā)送的最有一個(gè)ACK報(bào)文段能夠到達(dá)B。這個(gè)ACK報(bào)文段有可能丟失,因而使處在LAST-ACK狀態(tài)的B收不到對(duì)已發(fā)送的FIN和ACK 報(bào)文段的確認(rèn)。B會(huì)超時(shí)重傳這個(gè)FIN和ACK報(bào)文段,而A就能在2MSL時(shí)間內(nèi)收到這個(gè)重傳的ACK+FIN報(bào)文段。接著A重傳一次確認(rèn)。
第二,就是防止上面提到的已失效的連接請(qǐng)求報(bào)文段出現(xiàn)在本連接中,A在發(fā)送完最有一個(gè)ACK報(bào)文段后,再經(jīng)過2MSL,就可以使本連接持續(xù)的時(shí)間內(nèi)所產(chǎn)生的所有報(bào)文段都從網(wǎng)絡(luò)中消失。
一句話總結(jié)TCP和UDP的區(qū)別:
TCP是面向連接的,可靠的字節(jié)流服務(wù),UPD是面向無連接的,不可靠而數(shù)據(jù)報(bào)服務(wù)。
63、Python中有如下一個(gè)字典,
dic_tmp = {'carry':17,'bob':21,'matty':23,'jack':33,'tom':17,'alex':23}
請(qǐng)按照key值進(jìn)行排序
print(sorted(dic_tmp.items(),key=lambda dic_tmp : dic_tmp[0]))
64、簡(jiǎn)述InnoDB和MyISAM的特點(diǎn):
InnoDB是MySQL最常用的一種引擎,F(xiàn)acebook,Google等公司的成功應(yīng)用已經(jīng)證明了InnoDB存儲(chǔ)引擎具備高可用性,高性能以及高可擴(kuò)展性。支持事務(wù),其特點(diǎn)是行鎖設(shè)計(jì),支持外鍵,并支持類似Oracle的非鎖定讀。對(duì)于表中數(shù)據(jù)的存儲(chǔ),InnoDB 存儲(chǔ)引擎采用了聚集(clustered)的方式,每張表都是按 主鍵的順序進(jìn)行存儲(chǔ)的,如果沒有顯式地在表定義時(shí)指定主鍵,InnoDB 存儲(chǔ)引擎會(huì)為每一 行生成一個(gè) 6 字節(jié)的 ROWID,并以此作為主鍵。
MyISAM 不支持事務(wù)、表鎖設(shè)計(jì)、支持全文索引,主要面向一些 OLAP 數(shù) 據(jù)庫(kù)應(yīng)用,
此外,MyISAM 存儲(chǔ)引擎的 另一個(gè)與眾不同的地方是,它的緩沖池只緩存(cache)索引文件,而不緩存數(shù)據(jù)文件,這與 大多數(shù)的數(shù)據(jù)庫(kù)都不相同。
65、利用Python上下文管理器,實(shí)現(xiàn)一個(gè)寫入文件的功能(寫入內(nèi)容為‘hello world’)
class Open(object):
def __init__(self,name,mode):
self.name = name
self.mode = mode
def __enter__(self):
self.opened = open(self.name,self.mode) # 在enter方法中打開文件并返回文件名稱
return self.opened # 返回值就是as后面的writer
def __exit__(self, exc_type, exc_val, exc_tb): #在 close方法中關(guān)閉文件
self.opened.close()
with Open('mytext.txt','w') as writer:
writer.write('hello world')
65、django的請(qǐng)求生命周期
當(dāng)用戶在瀏覽器中輸入url時(shí),瀏覽器會(huì)生成請(qǐng)求頭和請(qǐng)求體發(fā)給服務(wù)端
請(qǐng)求頭和請(qǐng)求體中會(huì)包含瀏覽器的動(dòng)作(action),這個(gè)動(dòng)作通常為get或者post,體現(xiàn)在url之中.url經(jīng)過Django中的wsgi,再經(jīng)過Django的中間件,最后url到過路由映射表,在路由中一條一條進(jìn)行匹配,
一旦其中一條匹配成功就執(zhí)行對(duì)應(yīng)的視圖函數(shù),后面的路由就不再繼續(xù)匹配了.視圖函數(shù)根據(jù)客戶端的請(qǐng)求查詢相應(yīng)的數(shù)據(jù).返回給Django,然后Django把客戶端想要的數(shù)據(jù)做為一個(gè)字符串返回給客戶端.
客戶端瀏覽器接收到返回的數(shù)據(jù),經(jīng)過渲染后顯示給用戶
66、django rest framework規(guī)范
1、URL后面盡量用名詞,因?yàn)閞est frame是面向資源的編程,因此URL命名的時(shí)候,用名詞能體現(xiàn)出資源。
2、method的不同,實(shí)現(xiàn)增刪改查。
3、版本號(hào),因?yàn)橛邪姹镜母妫瑸榱梭w現(xiàn)出版本間的過渡,因此在發(fā)請(qǐng)求的時(shí)候,要體現(xiàn)出版本號(hào)。
4、返回值,與以往的只返回json數(shù)據(jù)不同,rest API規(guī)范還要加上狀態(tài)碼。
5、域名,由于前后端分離,因此要處理跨域問題。解決辦法:JSONP,CORS。
6、過濾,通過URL傳參的形式傳遞搜索條件,(例如,指定返回的記錄數(shù)量,指定分頁(yè)等)
67、JSONP和CORS
JSONP的本質(zhì)就是利用script的src屬性繞過同源策略。
CORS
整個(gè)CORS通信過程,都是瀏覽器自動(dòng)完成,不需要用戶參與。對(duì)于開發(fā)者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn)AJAX請(qǐng)求跨源,就會(huì)自動(dòng)添加一些附加的頭信息,有時(shí)還會(huì)多出一次附加的請(qǐng)求,但用戶不會(huì)有感覺。
一句話總結(jié)CORS,在代碼中添加上響應(yīng)頭即可。
68、現(xiàn)有字典dic = {'a':1,'b':2,'c':23,'d':11,'e':4,'f':21},請(qǐng)按照字段中的value進(jìn)行排序
print(sorted(dic.items(),key=lambda dic: dic[1] ))
69、如何查看端口號(hào)為8080的是什么進(jìn)程
netstat -nao | findstr '8080'
70、MySQL搜索引擎和局域網(wǎng)權(quán)限,MySQL中的鎖
InnoDB 存儲(chǔ)引擎(最常用的引擎,支持事務(wù),特點(diǎn)是行鎖設(shè)計(jì),支持外鍵)
MyISAM 存儲(chǔ)引擎(不支持事務(wù),表鎖設(shè)計(jì),支持全文索引)
NDB 存儲(chǔ)引擎
Memory 存儲(chǔ)引擎
71、算法,按照空間復(fù)雜度,進(jìn)行優(yōu)化。
72、ES6語(yǔ)法,
73、二叉樹的遍歷
class BiTreeNode(object):
def __init__(self,data):
self.data = data
self.lchild = None
self.rchild = None
a = BiTreeNode('A')
b= BiTreeNode('B')
c = BiTreeNode('C')
d = BiTreeNode('D')
e = BiTreeNode('E')
f = BiTreeNode('F')
g = BiTreeNode('G')
e.lchild = a
e.rchild = g
a.rchild = c
c.lchild = b
c.rchild = d
g.rchild = f
root = e
# 前序遍歷 (先找做子樹,后找右子樹)
def pre_order(root):
if root:
print(root.data,end='') # EACBDGF
pre_order(root.lchild)
pre_order(root.rchild)
pre_order(root)
print('')
# 中序遍歷
def in_order(root):
if root:
in_order(root.lchild)
print(root.data,end='') # ABCDEGF
in_order(root.rchild)
in_order(root) # ABCDEGF
print('')
# 后序遍歷
def post_order(root):
if root:
post_order(root.lchild)
post_order(root.rchild)
print(root.data,end='')
post_order(root) #BDCAFGE
74、實(shí)現(xiàn)頁(yè)面實(shí)時(shí)刷新的方法:
1、輪詢
2、長(zhǎng)輪詢
3、websocket
輪詢:客戶端定時(shí)向服務(wù)器發(fā)送Ajax請(qǐng)求,服務(wù)器接到請(qǐng)求后馬上返回響應(yīng)信息并關(guān)閉連接。
優(yōu)點(diǎn):后端程序編寫比較容易。
缺點(diǎn):請(qǐng)求中有大半是無用,浪費(fèi)帶寬和服務(wù)器資源。
實(shí)例:適于小型應(yīng)用。
長(zhǎng)輪詢:客戶端向服務(wù)器發(fā)送Ajax請(qǐng)求,服務(wù)器接到請(qǐng)求后hold住連接,直到有新消息才返回響應(yīng)信息并關(guān)閉連接,客戶端處理完響應(yīng)信息后再向服務(wù)器發(fā)送新的請(qǐng)求。
優(yōu)點(diǎn):在無消息的情況下不會(huì)頻繁的請(qǐng)求。
缺點(diǎn):服務(wù)器hold連接會(huì)消耗資源。
實(shí)例:WebQQ、Hi網(wǎng)頁(yè)版、Facebook IM。
75、提高數(shù)據(jù)庫(kù)性能的方法
a、建立索引。
b、書寫:SQL語(yǔ)句優(yōu)化,盡量不要使用select * from等語(yǔ)句
c、
76、請(qǐng)寫出以下函數(shù)的輸出結(jié)果
def multiplier():
return [lambda x: x * i for i in range(4)]
print([m(2) for m in multiplier()]) # 6,6,6,6
具體原因請(qǐng)見:http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures
77、rabbitMQ的幾種模式以及簡(jiǎn)述RPC
總共6中模式,相關(guān)如下:
RPC:official link for Python
http://www.rabbitmq.com/tutorials/tutorial-six-python.html
78、你了解webSocket嗎?
a、最近在研究。
b、很久以前研究過。
79、簡(jiǎn)單談?wù)勀懔私獾膚ebsocket。
a. 自己手寫socket研究其原理
b. 握手信息
c. 數(shù)據(jù)加密
了解的應(yīng)用:
1.基于tornado實(shí)現(xiàn)的websocket聊天室
2.彈幕。
80、redis和memcached的區(qū)別
memcache與redis區(qū)別
1)redis不僅僅支持簡(jiǎn)單的k/v類型的數(shù)據(jù),同時(shí)還提供list,set,hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)
2)內(nèi)存使用使用效率對(duì)比
使用簡(jiǎn)單的key-value存儲(chǔ)的話,memcached的內(nèi)存利用率會(huì)更高一點(diǎn),如果redis采用hash結(jié)構(gòu)來做key-value存儲(chǔ),由于其組合式的壓縮,內(nèi)存的利用率更高。
3)性能對(duì)比:由于redis只使用單核,而memcached使用多核,所以平均在每一個(gè)核上redis在存儲(chǔ)小數(shù)據(jù)時(shí)比memcached性能更高,而在100Ks=以上的時(shí)候memcached性能要高于redis
4)內(nèi)存管理機(jī)制的不同
在redis中,并不是所有的數(shù)據(jù)都一一直存儲(chǔ)在內(nèi)存中的,這是和memcached相比最大的一個(gè)區(qū)別
Redis只會(huì)緩存所有的key端的信息,如果redis發(fā)現(xiàn)內(nèi)存的使用量超過某一個(gè)值,將觸發(fā)swap的操作,redis根據(jù)相應(yīng)的表達(dá)式計(jì)算出那些key對(duì)應(yīng)value需要swap到磁盤,然后再將這些這些key對(duì)應(yīng)的value持久化到磁盤中,同時(shí)再內(nèi)存清除。
5)數(shù)據(jù)持久化的支持
雖然redis是基于內(nèi)存的存儲(chǔ)系統(tǒng),但是他本身是支持內(nèi)存數(shù)據(jù)的持久化,而且主要提供兩種主要的持久化策略,RDB快照和AOF日志,而memcached是不支持?jǐn)?shù)據(jù)持久化的操作的
81, drop 和 truncate 的區(qū)別
truncate table在功能上與不帶where子句的delete語(yǔ)句相同:二者均能刪除表中的全部行。但truncate table速度比delete快。
TRUNCATE TABLE:刪除內(nèi)容、釋放空間但不刪除定義。
DELETE TABLE:刪除內(nèi)容不刪除定義,不釋放空間。
DROP TABLE:刪除內(nèi)容和定義,釋放空間。
還有個(gè)比較大的區(qū)別就是truncate后自增長(zhǎng)的ID列也會(huì)歸零,以后插入記錄ID從1開始。
但是delete后你再插入記錄,ID會(huì)從上次最大的數(shù)字開始。
delete可以配合where條件
82、differences between threads and process;
Threads share the address space of the process that created it; processes have their own address space.
Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
New threads are easily created; new processes require duplication of the parent process.
Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.
83、寫出你知道的常見異常
AttributeError 試圖訪問一個(gè)對(duì)象沒有的樹形,比如foo.x,但是foo沒有屬性x
IOError 輸入/輸出異常;基本上是無法打開文件
ImportError 無法引入模塊或包;基本上是路徑問題或名稱錯(cuò)誤
IndentationError 語(yǔ)法錯(cuò)誤(的子類) ;代碼沒有正確對(duì)齊
IndexError 下標(biāo)索引超出序列邊界,比如當(dāng)x只有三個(gè)元素,卻試圖訪問x[5]
KeyError 試圖訪問字典里不存在的鍵
KeyboardInterrupt Ctrl+C被按下
NameError 使用一個(gè)還未被賦予對(duì)象的變量
SyntaxError Python代碼非法,代碼不能編譯(個(gè)人認(rèn)為這是語(yǔ)法錯(cuò)誤,寫錯(cuò)了)
TypeError 傳入對(duì)象類型與要求的不符合
UnboundLocalError 試圖訪問一個(gè)還未被設(shè)置的局部變量,基本上是由于另有一個(gè)同名的全局變量,
導(dǎo)致你以為正在訪問它
ValueError 傳入一個(gè)調(diào)用者不期望的值,即使值的類型是正確的`
84、進(jìn)程,線程,協(xié)程
進(jìn)程
進(jìn)程是一個(gè)程序在一個(gè)數(shù)據(jù)集中的一次動(dòng)態(tài)執(zhí)行過程,可以簡(jiǎn)單理解為‘正在進(jìn)行的程序’,它是CPU資源分配和調(diào)度的獨(dú)立單位。
進(jìn)程的局限是創(chuàng)建,撤銷和切換的開銷比較大。
線程
線程也叫輕量級(jí)進(jìn)程,是一個(gè)CPU的基本執(zhí)行單元,也是程序執(zhí)行過程中的最小單元。一個(gè)進(jìn)程可以包含多個(gè)線程。
缺點(diǎn):線程沒有自己的系統(tǒng)資源,若不加鎖,容易造成資源混亂。
協(xié)程
又稱為微線程。協(xié)程的調(diào)度可通過yield來調(diào)用其他協(xié)程。
和線程相比,其優(yōu)勢(shì)在:
1、協(xié)程的執(zhí)行效率非常高。因?yàn)樽映绦蚯袚Q不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數(shù)量越多,協(xié)程的性能優(yōu)勢(shì)就越明顯。
2、協(xié)程不需要多線程的鎖機(jī)制。在協(xié)程中控制共享資源不加鎖,只需要判斷狀態(tài)就好了。
Tips:利用多核CPU最簡(jiǎn)單的方法是多進(jìn)程+協(xié)程,既充分利用多核,又充分發(fā)揮協(xié)程的高效率,可獲得極高的性能。
85、Linux的啟動(dòng)流程
86、同步,異步,阻塞,非阻塞
同步:在發(fā)起一個(gè)功能調(diào)用時(shí),在沒得到結(jié)果之前,該調(diào)用就不會(huì)返回。apply提交任務(wù),遇到io阻塞時(shí),就是等待阻塞結(jié)束。
異步:當(dāng)異步功能調(diào)用發(fā)出后,不會(huì)立即得到最終結(jié)果,當(dāng)異步功能完成后,通過回調(diào)函數(shù)通知調(diào)用者。
87、Python2.7 與 3.x的編碼問題
2.7:
字符串兩種類型:
str:某種編碼(UTF-8、GBK)類型的字符串
unicode:Unicode類型的字符串 unicode ——> str
3.X:
字符串兩種類型:
bytes:某種編碼(UTF-8、GBK)類型的字符串
str:Unicode類型的字符串 str ——> bytes str.encode(“utf-8”)
decode() 和 encode()
decode 的作用是將其他編碼的字符串轉(zhuǎn)化成Unicode編碼
encode 的作用是將Unicode編碼轉(zhuǎn)化成其他編碼的字符串