1. 程式人生 > >面試題及答案

面試題及答案

1. 為什麼學習Python?
自身覺得有個一技之長在手,心裡踏實,現在瞭解到人工智慧是以後的發展趨勢,然後經過網上查詢資料,以及自己朋友的推薦,說python在人工智慧方面涉及到很多領域,且程式碼簡潔,簡單易學,生態圈強大,因此來學python。

3. Python和Java、PHP、C、C#、C++等其他語言的對比?
如果以解釋型、編譯型來分類的話。python(php)就屬於解釋型
(c/java/c#屬於編譯型),同時python也屬於弱型別語言。
強型別定義語言:強制資料型別定義的語言。也就是說,一旦一個變數被指定了某個資料型別,如果不經過強制轉換,那麼它就永遠是這個資料型別了。
弱型別定義語言:資料型別可以被忽略的語言。它與強型別定義語言相反, 一個變數可以賦不同資料型別的值。

4. 簡述解釋型和編譯型程式語言?
#1. 編譯型(需要編譯器,相當於用谷歌翻譯):如C,執行速度快,除錯麻煩
#2. 解釋型(需要直譯器,相當於同聲傳譯):如python,執行速度慢,除錯方便

解釋型語言:專門的直譯器對源程式每一行解釋成特定平臺的機器碼並立即執行的語言;
解釋型語言不會對整體性的編譯和連結處理,解釋型語言相當於把編譯語言中編譯和解釋過程混合到了一起同時完成。
優點:跨平臺較容易,是以犧牲程式執行效率為代價。 缺點:效率較低,不能脫離直譯器獨立執行。

編譯型的語言: 專門的編譯器, 針對特定的平臺(作業系統)“翻譯”成機器碼(包括機器指令和運算元),
幷包裝成該平臺可執行程式的格式;如需要其他的程式碼,要進行連結。
優點: 可脫離開發環境,特定的平臺上獨立執行,執行效率較高。缺點:無法移植;需要移植,要原始碼重新編譯。

5. Python直譯器種類以及特點?
CPython

  當從Python官方網站下載並安裝好Python2.7後,就直接獲得了一個官方版本的直譯器:Cpython,這個直譯器是用C語言開發的,所以叫CPython,在命名行下執行python,就是啟動CPython直譯器,CPython是使用最廣的Python直譯器。

  IPython

  IPython是基於CPython之上的一個互動式直譯器,也就是說,IPython只是在互動方式上有所增強,但是執行Python程式碼的功能和CPython是完全一樣的,好比很多國產瀏覽器雖然外觀不同,但核心其實是呼叫了IE。

  PyPy

  PyPy是另一個Python直譯器,它的目標是執行速度,PyPy採用JIT技術,對Python程式碼進行動態編譯,所以可以顯著提高Python程式碼的執行速度。

  Jython

  Jython是執行在Java平臺上的Python直譯器,可以直接把Python程式碼編譯成Java位元組碼執行。

  IronPython

  IronPython和Jython類似,只不過IronPython是執行在微軟.Net平臺上的Python直譯器,可以直接把Python程式碼編譯成.Net的位元組碼。

  在Python的直譯器中,使用廣泛的是CPython,對於Python的編譯,除了可以採用以上直譯器進行編譯外,技術高超的開發者還可以按照自己的需求自行編寫Python直譯器來執行Python程式碼,十分的方便!

6. 位和位元組的關係?
最小的儲存單位稱為位(bit):
只能容納兩個值(0或1)之一,不能在一個位中儲存更多的資訊。位是計算機儲存的基本單位。
位元組(byte)是常用的計算機儲存單位。
位元組的標準定義:一個位元組均為8位。由於上述所講每個位或者是0或者是1,所以一個8位的位元組包含256種可能的0,1組合
對於一種給定的計算機設計,字(word)是自然的儲存單位。

一個英文字元和英文標點佔用一個位元組,一箇中文字元和中文標點佔用2個位元組

7. b、B、KB、MB、GB 的關係?
1024b = 1B 1024B = 1KB 1024KB = 1MB 1024MB = GB

8. 請⾄少列舉5個 PEP8 規範(越多越好)。
縮排。4個空格的縮排(編輯器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。
每行最大長度79,換行可以使用反斜槓,最好使用圓括號。換行點要在操作符的後邊敲回車。
類和top-level函式定義之間空兩行;類中的方法定義之間空一行;函式內邏輯無關段落之間空一行;其他地方儘量不要再空行。
各種右括號前不要加空格。
逗號、冒號、分號前不要加空格。
函式的左括號前不要加空格。如Func(1)。
序列的左括號前不要加空格。如list[2]。
操作符左右各加一個空格,不要為了對齊增加空格。
函式預設引數使用的賦值符左右省略空格。
不要將多句語句寫在同一行,儘管使用‘;’允許。
if/for/while語句中,即使執行語句只有一句,也必須另起一行。
變數小寫,多的話用下劃線分割,等號中間不要用空格

9、通過程式碼實現如下轉換:
二進位制轉換成十進位制:v = “11 11 011” print(int('1111011',2))#123
十進位制轉換成二進位制:v = 18 print(bin(18)) #10010
八進位制轉換成十進位制:v = “011” print(int('011',8)) #9
十進位制轉換成八進位制:v = 30 print(oct(30)) #36
十六進位制轉換成十進位制:v = “0x12” print(int('0x12',16)) or print(int('12',16)) #18
十進位制轉換成十六進位制:v = 87 print(hex(87)) #57

10、請編寫一個函式實現將IP地址轉換成一個整數。

如 10.3.9.12 轉換規則為:
00001010
00000011
00001001
00001100
再將以上二進位制拼接起來計算十進位制結果:00001010 00000011 00001001 00001100 = ?

11、python遞迴的最大層數?
最大層數998層
12、求結果:
v1 = 1 or 3 #1
v2 = 1 and 3 # 3
v3 = 0 and 2 and 1 # 0 因為0是錯誤的,一個錯誤的跟一個正確的做比較,肯定是錯誤的
v4 = 0 and 2 or 1 #1
v5 = 0 and 2 or 1 or 4 #1
v6 = 0 or Flase and 1 #0
13、ascii、unicode、utf-8、gbk 區別?

編碼 大小 支援語言
ASCII 1個位元組 英文
Unicode 2個位元組(生僻字4個) 所有語言
UTF-8 1-6個位元組,英文字母1個位元組,漢字3個位元組,生僻字4-6個位元組 所有語言

ascii用1個位元組(8位二進位制)代表一個字元
unicode常用2個位元組(16位二進位制)代表一個字元,生僻字需要用4個位元組
GBK是中國標準,只在中國使用,並沒有表示大多數其它國家的編碼;而各國又陸續推出各自的編碼標準,互不相容,非常不利於全球化發展。於是後來國際組織發行了一個全球統一編碼表,把全球各國文字都統一在一個編碼標準裡,名為Unicode。
unicode----->encode-------->utf-8
utf-8-------->decode---------->unicode
ps:
瀏覽網頁的時候,伺服器會把動態生成的Unicode內容轉換為UTF-8再傳輸到瀏覽器
如果服務端encode的編碼格式是utf-8, 客戶端記憶體中收到的也是utf-8編碼的結果。

gbk-->decode-->unicode
GBK編碼,一個漢字佔兩個位元組。
GBK包含全部中文字元;UTF-8則包含全世界所有國家需要用到的字元。

python2中的str型別就是python3的bytes型別


14、位元組碼和機器碼的區別?
位元組碼(Bytecode):是一種包含執行程式、由一序列 op 程式碼/資料對 組成的二進位制檔案。位元組碼是一種中間碼,它比機器碼更抽象,需要直譯器轉譯後才能成為機器碼的中間程式碼。

機器碼:機器碼是電腦CPU 直接讀取執行的機器指令,執行速度最快,但是非常晦澀難懂,也比較難編寫,一般從業人員接觸不到。



15、三元運算規則以及應用場景?
規則:為真結果 if 判斷條件 else 為假結果(且間隔之間沒有冒號)

場景:主要用於簡單的if else 判斷語句
16. 列舉 Python2和Python3的區別?
說這個的時候,最好講故事,(講一些之前的經歷或者故事,),然後在可以說我記得大概是這樣,python2中字串是位元組,原始碼中bytes=str;python3中字串數Unicode

py2和py3:
1. 檔案操作: xreadlines
--檔案操作:xreadlines,這是python2中的,python3中就沒有了,python3中返回的是range的一個物件

f = open('x.log','rb')

for line in f.xreadlines():
print(line)

f.close()

2. 字串:
py2:
str: 字串 -> 位元組
-在python2中字串其實是位元組(位元組串------在python2中字串其實是位元組(位元組串------>這是python3中的位元組) #這個特點一定要說
-unicode=u'xxxxxx'------>這python3中的字串
py3: #python3中字串就是Unicode
bytes:
str:

3. 預設直譯器編碼
py2: ascii;#py2中在py檔案頂層需要加上-*-code.....補全# -*- coding: utf-8 -*-
py3: utf-8

5.
py2: range/xrange
py3: range

6.
py2: int / long
py3: int
long整數型別被Python3廢棄,統一使用int
xrange函式被Python3廢棄,統一使用range,Python3中range的機制也進行修改並提高了大資料集生成效率

7. input/raw_input

8.
py2: yield
py3: yield/yield from

9.
py2: 新式類和經典類
py3: 新式類
在Python 3.x中取消了經典類,預設都是新式類,並且不必顯式的繼承object,也就是說:
class Person(object):pass
class Person():pass
class Person:pass
三種寫法並無區別,推薦第一種
在Python2.x中,預設都是經典類,只有顯式繼承了object才是新式類,即:
class Person(object):pass 新式類寫法
class Person():pass 經典類寫法
class Person:pass 經典類寫法


python2中print #被視為一個語句
python3中是print() #視為一個函式


17、用一行程式碼實現數值交換:
a = 1
b = 2
答案:a,b=b,a
18、Python3和Python2中 int 和 long的區別?
python3去除了long型別,現在只有一種整型——int,但它的行為就像python2版本的long
python3 徹底廢棄了 long+int 雙整數實現的方法, 統一為 int , 支援高精度整數運算.
int() (符號整數):通常被稱為是整數或整數,沒有小數點的正或負整數。
long() (長整數):或渴望,無限大小的整數,這樣寫整數和一個大寫或小寫的L。

19、xrange和range的區別?
python2中:range返回的是一個列表 xrange返回的是一個迭代器
python3中:取消了xrange 用range代替 返回的是一個 range物件
20、檔案操作時:xreadlines和readlines的區別?
python2中:xreadlines 則直接返回一個iter(file)迭代器,這個一個個迴圈
python3中:取消了xreadlines 用readlines代替 返回的是一個list物件(或者說是一個for物件)
21、列舉布林值為False的常見值?
0、 Flase、 負數 、 None 等
22、字串、列表、元組、字典每個常用的5個方法?
字串方法:len/index/replace/split/find
列表方法:extend、append、insert、pop、remove
元祖方法:len、max、min、clear、index
字典方法:.get、.update、.pop、.items、.values

23、lambda表示式格式以及應用場景?
# val = (lambda x:x+i for i in range(10))
# print(val,type(val))
python 使用 lambda 表示式來建立匿名函式

24、pass的作用?
pass是空語句,為了保持程式結構的完整性,它不做任何事情,可當佔位語句來用

25、*arg和**kwarg作用
*arg和**kwarg 可以幫助我們在呼叫函式的時候傳入多個實參
*arg會把多出來的位置引數轉化為tuple
**kwarg會把關鍵字引數轉化為dict

26、is和==的區別
在python中,is檢查兩個物件是否是同一個物件,而==檢查他們是否相等.
簡述Python的深淺拷貝以及應用場景?
copy和deepcopy
淺拷貝就是對引用的拷貝(只拷貝父物件,不會拷貝資料中的子物件切片拷貝,)
深拷貝就是對物件的資源的拷貝

淺拷貝與原物件的內層資料地址相同;
深拷貝完全獨立開來,與原物件沒有任何聯絡。
Python垃圾回收機制?
Python中的垃圾回收是以引用計數為主,分代收集為輔。引用計數的缺陷是迴圈引用的問題。
在Python中,如果一個物件的引用數為0,Python虛擬機器就會回收這個物件的記憶體。
Python的可變型別和不可變型別?
數字、字串、元組是不可變的,
列表、字典是可變的。
求結果:
v = dict.fromkeys(['k1','k2'],[])
v[‘k1’].append(666)
print(v)
v[‘k1’] = 777
print(v)

#{'k1': [666], 'k2': [666]}
#{'k1': 777, 'k2': [666]}
求結果:
def num():
return [lambda x:i*x for i in range(4)]
#這個range4,其實是4個函式,但是0 1 2都沒執行,最後只剩下3了,所以每次傳進來的引數,執行結果都是2*3=6
print([m(2)for m in num()])
#結果是[6, 6, 6, 6]
列舉常見的內建函式?
len()長度
count()計數
str()字串
int() 數字
filter 過濾 構造一個列表返回所有值為True的元素
instance 判斷是否是class的例項
type 返回該object的型別
dir 不帶引數時,返回當前範圍內的變數、方法和定義的型別列表;
filter、map、reduce的作用?
一行程式碼實現9*9乘法表
print('\n'.join([' '.join(['%s*%s=%-2s' % (j, i, i * j) for j in range(1, i + 1)]) for i in range(1, 10)]))
如何安裝第三方模組?以及用過哪些第三方模組?
pip3 install xxx # 線上安裝制定版本
pip install xxx==版本 # 通過whl檔案離線安裝擴充套件庫
第三方模組:requests,DbUtils,SQLAlchemy等
至少列舉8個常用模組都有那些?
- time/random/re/json/pickle/logging/os/sys/hashlib
- requests/beautifulsoup4
re的match和search區別?
re.match只匹配字串的開始,如果字串開始不符合正則表示式,則匹配失敗,函式返回None;
re.search匹配整個字串,直到找到一個匹配。
什麼是正則的貪婪匹配?
在滿足匹配時,匹配儘可能長的字串,預設情況下,採用貪婪匹配
eg:
string pattern1 = @"a.*c"; // greedy match
Regex regex = new Regex(pattern1);
regex.Match("abcabc"); // return "abcabc"
求結果:
a. [ i % 2 for i in range(10) ] #[0, 1, 0, 1, 0, 1, 0, 1, 0, 1] 為列表生成式
b. ( i % 2 for i in range(10) ) #<generator object <genexpr> at 0x00000000005DB780> 為生成式
求結果:
a. 1 or 2 #1 整個式子 不斷去向右檢視,直到能確定為真就停下來
b. 1 and 2 #2 整個式子 不斷去向右檢視,直到能確定為真就停下來
c. 1 < (2==2) #False 因為布林值是一種特殊的int,所示1<ture,因此是F
d. 1 < 2 == 2 #True
def func(a,b=[]) 這種寫法有什麼坑?
這裡b=[]引數有坑,eg:第一次傳個字串,能正常使用;第二次若傳個列表,那麼會覆蓋第一次傳的字串。
如何實現 “1,2,3” 變成 [‘1’,’2’,’3’] ?
v = “1,2,3”

print(list(v.split(',')))
如何實現[‘1’,’2’,’3’]變成[1,2,3] ?
[int(x) for x in ['1','2','3']]
比較: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的區別?
首先它們都是一個列表 只是列表元素種類不同 a和b的元素都是int型別 c的元素是元祖
如何用一行程式碼生成[1,4,9,16,25,36,49,64,81,100] ?
a=[i*i for i in range(1,11)]
print(a)
一行程式碼實現刪除列表中重複的值 ?
如何在函式中設定一個全域性變數 ?
logging模組的作用?以及應用場景?

通過log的分析,可以方便使用者瞭解系統或軟體、應用的執行情況;如果你的應用log足夠豐富,也可以分析以往使用者的操作行為、型別喜好、地域分佈或其他更多資訊;如果一個應用的log同時也分了多個級別,那麼可以很輕易地分析得到該應用的健康狀況,及時發現問題並快速定位、解決問題,補救損失。

應用場景,資料庫每操作一次,生成一條日誌記錄。
請用程式碼簡答實現stack 。
常用字串格式化哪幾種?
字串格式化有兩種方式:百分號方式、format方式。

格式:%[(name)][flags][width].[precision]typecode

i1 = "i am {},age {} ,{}".format('cairui',18,'kk')
print(i1)
i am cairui,age 18 ,kk
簡述 生成器、迭代器、可迭代物件 以及應用場景?
生成器是什麼?在哪裡用過?
一個函式內部存在yield關鍵字;v = 函式()。那麼函式名()的到的結果就是生成器,並且不會執行函式內部程式碼
本質:就是一個迭代器
應用場景:
- range/xrange
- py2: range(100000000),立即建立;xrange(100000000)生成器;
- py3: range(100000000)生成器;
- stark元件
xx.html:
{% for item in data %}
<p>{{item.k1}} {{item.name}}</p>
{%endfor%}
views.py
def index(request):
data = [
{'k1':1,'name':'alex'},
{'k1':2,'name':'老男孩'},
{'k1':3,'name':'小男孩'},
]

new_data = []
for item in data:
item['email'] = "[email protected]"
new_data.append(item)

return render(request,'xx.html',{'data':new_data})

迭代器是什麼?在哪裡用過?
迭代器即迭代的工具,那什麼是迭代呢?
迭代是一個重複的過程,每次重複即一次迭代,並且每次迭代的結果都是下一次迭代的初始值,內部內部實現__next__方法,幫助我們向後一個一個取值。

什麼叫迭代?:一個一個取值,就像for迴圈一樣取值。
迭代器協議:內部實現了__iter__,__next__方法

-什麼是可迭代物件?
- 可迭代物件,一個類內部實現__iter__方法且返回一個迭代器。即obj.__iter__

class Foo(object):
def __iter__(self):
return iter([11,22,33])
obj = Foo()

應用場景:
- wtforms中對form物件進行迴圈時候,顯示form中包含的所有欄位。
class LoginForm(Form):
name = simple.StringField(
label='使用者名稱',
validators=[
validators.DataRequired(message='使用者名稱不能為空.'),
validators.Length(min=6, max=18, message='使用者名稱長度必須大於%(min)d且小於%(max)d')
],
widget=widgets.TextInput(),
render_kw={'class': 'form-control'}
)
pwd = simple.PasswordField(
label='密碼',
validators=[
validators.DataRequired(message='密碼不能為空.'),
validators.Length(min=8, message='使用者名稱長度必須大於%(min)d'),
validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[[email protected]$!%*?&])[A-Za-z\[email protected]$!%*?&]{8,}",
message='密碼至少8個字元,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字元')

],
widget=widgets.PasswordInput(),
render_kw={'class': 'form-control'}
)


form = LoginForm()
for item in form:
print(item)

- 列表、字典、元組

總結:如果想要讓一個物件可以被for迴圈,那麼就需要在當前類中定義__iter__
用Python實現一個二分查詢的函式。
https://www.cnblogs.com/wgDream/p/7533605.html
百度查詢下什麼是二分查詢
談談你對閉包的理解?
閉包函式,其實就是一個裝飾器,是內部函式包含對外部作用域中變數的引用
閉包:
1.閉 :內部的函式
   2.包 :包含了對外部函式作用域中變數的引用
# 閉包的常用形式:
def hei():
  x=20
  def inner():
    '''閉包函式'''
    print(x)
return inner()
判斷閉包函式的方法:__closure__
#輸出的__closure__有cell元素 :是閉包函式
def func():
name = 'eva'
def inner():
print(name)
print(inner.__closure__)
return inner

f = func()
f()


#輸出的__closure__為None :不是閉包函式
name = 'egon'
def func2():
def inner():
print(name)
print(inner.__closure__)
return inner

f2 = func2()
f2()
os和sys模組的作用?
總結:
就是,os模組負責程式與作業系統的互動,提供了訪問作業系統底層的介面;
sys模組負責程式與python直譯器的互動,提供了一系列的函式和變數,用於操控python的執行時環境。
--os模組是與作業系統互動的一個介面,這個模組提供了一種方便的使用作業系統函式的方法。
'''
os.getcwd() 獲取當前工作目錄,即當前python指令碼工作的目錄路徑
os.chdir("dirname") 改變當前指令碼工作目錄;相當於shell下cd
os.curdir 返回當前目錄: ('.')
os.pardir 獲取當前目錄的父目錄字串名:('..')
os.makedirs('dirname1/dirname2') 可生成多層遞迴目錄
os.removedirs('dirname1') 若目錄為空,則刪除,並遞迴到上一級目錄,如若也為空,則刪除,依此類推
os.mkdir('dirname') 生成單級目錄;相當於shell中mkdir dirname
os.rmdir('dirname') 刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname
os.listdir('dirname') 列出指定目錄下的所有檔案和子目錄,包括隱藏檔案,並以列表方式列印
os.remove() 刪除一個檔案
os.rename("oldname","newname") 重新命名檔案/目錄
os.stat('path/filename') 獲取檔案/目錄資訊
os.sep 輸出作業系統特定的路徑分隔符,win下為"\\",Linux下為"/"
os.linesep 輸出當前平臺使用的行終止符,win下為"\t\n",Linux下為"\n"
os.pathsep 輸出用於分割檔案路徑的字串 win下為;,Linux下為:
os.name 輸出字串指示當前使用平臺。win->'nt'; Linux->'posix'
os.system("bash command") 執行shell命令,直接顯示
os.environ 獲取系統環境變數
os.path.abspath(path) 返回path規範化的絕對路徑
os.path.split(path) 將path分割成目錄和檔名二元組返回
os.path.dirname(path) 返回path的目錄。其實就是os.path.split(path)的第一個元素
os.path.basename(path) 返回path最後的檔名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是絕對路徑,返回True
os.path.isfile(path) 如果path是一個存在的檔案,返回True。否則返回False
os.path.isdir(path) 如果path是一個存在的目錄,則返回True。否則返回False
os.path.join(path1[, path2[, ...]]) 將多個路徑組合後返回,第一個絕對路徑之前的引數將被忽略
os.path.getatime(path) 返回path所指向的檔案或者目錄的最後訪問時間
os.path.getmtime(path) 返回path所指向的檔案或者目錄的最後修改時間
os.path.getsize(path) 返回path的大小
'''
--sys這個模組可供訪問由直譯器使用或維護的變數和與直譯器進行互動的函式。
sys.argv 命令列引數List,第一個元素是程式本身路徑
sys.exit(n) 退出程式,正常退出時exit(0)
sys.version 獲取Python解釋程式的版本資訊
sys.maxint 最大的Int值
sys.path 返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數的值
sys.platform 返回作業系統平臺名稱
如何生成一個隨機數?
import random
a = random.randint(1,100)
print(a)
print(random.random()) # 用於生成一個0到1的隨機符點數: 0 <= n < 1.0
print(random.randint(1,10)) # 用於生成一個指定範圍內的整數
print(random.randrange(1,10)) # 用於生成一個指定範圍內的整數
如何使用python刪除一個檔案?
import os
file = r'F:\test.txt'
if os.path.exists(file):
os.remove(file)
print('delete success')
else:
print('no such file:%s' % file)
談談你對面向物件的理解?

面向物件:
從三大特性說起:繼承、封裝、多型

封裝:
起始就是將很多資料封裝到一個物件中,類似於把很多東西放到一個箱子中,
如:一個函式如果好多引數,起始就可以把引數封裝到一個物件再傳遞。

在哪裡用過:
- django rest framework中的request物件。
- flask中:請求上下文物件中ctx_context/app_context物件
繼承:
如果多個類中都有共同的方法,那麼為了避免反覆編寫,就可以將方法提取到基類中實現,
讓所有派生類去繼承即可。

在哪裡用過?
- 檢視
- 版本、認證、分頁
多型:
python本身就是多型的,崇尚鴨子模型,只要會呱呱叫的就是鴨子。
def func(arg):
arg.send()
Python面向物件中的繼承有什麼特點?
面向物件繼承中的一些特點:
1:在繼承中基類的構造(__init__()方法)不會被自動呼叫,它需要在其派生類的構造中親自專門呼叫。有別於C#
2:在呼叫基類的方法時,需要加上基類的類名字首,且需要帶上self引數變數。區別於在類中呼叫普通函式時並不需要帶上self引數
3:總是首先查詢對應型別的方法,如果它不能在派生類中找到對應的方法,它才開始到基類中逐個查詢。
(先在本類中查詢呼叫的方法,找不到才去基類中找)。

ps:什麼是派生
派生就是子類在繼承父類的基礎上衍生出新的屬性。子類中獨有的,父類中沒有的;或子類定義與父類重名的東西。子類也叫派生類。
面向物件深度優先和廣度優先是什麼?
Python的類可以繼承多個類,Python的類如果繼承了多個類,那麼其尋找方法的方式有兩種
當類是經典類時,多繼承情況下,會按照深度優先方式查詢
當類是新式類時,多繼承情況下,會按照廣度優先方式查詢
簡單點說就是:經典類是縱向查詢,新式類是橫向查詢
典類和新式類的區別就是,在宣告類的時候,新式類需要加上object關鍵字。在python3中預設全是新式類
面向物件中super的作用?
呼叫父類中的方法

在python中,每個類都有一個mro的類方法。 mro方法返回的是類的繼承順序的列表 並且所繼承的類只出現一次
這也是super在父類中查詢成員的順序, 這解決了多繼承的問題。
super在繼承體系中向上的查詢過程,變成了在mro中向右的線性查詢過程,任何類都只會被處理一次。
通過這個方法,python解決了多繼承中的2大難題:
1. 查詢順序問題。
2. 鑽石繼承的多次初始化問題。事實上任何類都只會在mro list中出現一次。這就確保了super向上呼叫的過程中,
任何祖先類的方法都只會被執行一次。
是否使用過functools中的函式?其作用是什麼?
@functools.wraps() 用於修復裝飾器對原函式名的更改

import functools #匯入模組

def wapper(func):
@functools.wraps(func) #函式被裝飾器裝飾後會改變函式的函式名 此方法可以保留原函式名(將原函式的原資訊重新賦值給函式)
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
"""
1. 執行wapper函式,並將被裝飾的函式當做引數。 wapper(index)
2. 將第一步的返回值,重新賦值給 新index = wapper(老index)
"""
@wapper
def index(a1):
return a1 + 1000

@wapper
def order(a1):
return a1 + 1000
列舉面向物件中帶雙下劃線的特殊方法,如:__new__、__init__
_iter__ 迴圈物件是,自定義__iter__
        wtforms中BaseForm中迴圈所有欄位時定義了__iter__
__call__、__dir__、__eq__等__xx__方法
在flask的上下文管理中,LocalProxy裡面用到過,順便說一句上下文管理還挺有意思的。
__call__ 物件名(),觸發執行。
__new__ 類名()會執行__new__ 然後在執行__init__ 方法
__init__ 類名()執行__init__ 方法
__doc__ 返回類的描述資訊(註釋)
__class__ 表示當前操作的物件的類是什麼
__del__ 析構方法,當物件在記憶體中被釋放時,自動觸發執行。
__dict__ 以字典的形式返回類的所有屬性
__str__ 改變物件的字串顯示
如何判斷是函式還是方法?

函式和方法的區別?
from types import MethodType(方法),FunctionType(函式)
def func():
pass
print(isinstance(func,FunctionType)) # True


class A():
def aaa(self):
pass
print(isinstance(aaa,FunctionType)) # True
a=A()
print(isinstance(a.aaa,MethodType)) # True要有例項化出來的物件才可以,如果只是用類名去呼叫的話還是function,只有用例項化出來的物件去呼叫才可以得到method

我們的函式只有跟我們的例項化出來的物件有繫結關係才能稱之為方法,否則都是函式,即便它是寫到類裡面的方法,沒有跟我們的類例項化出來的物件進行繫結,它依然是函式,而不是類裡面的方法.
靜態方法和類方法區別?
儘管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明顯的區別。
classmethod 必須有一個指向類物件的引用作為第一個引數,而 staticmethod 可以沒有任何引數。
列舉面向物件中的特殊成員以及應用場景
在flask的上下文管理中,LocalProxy裡面用到過
__call__ 物件名(),觸發執行。

__new__ 類名()會執行__new__ 然後在執行__init__ 方法

__init__ 類名()執行__init__ 方法

__doc__ 返回類的描述資訊(註釋)

__class__ 表示當前操作的物件的類是什麼

__del__ 析構方法,當物件在記憶體中被釋放時,自動觸發執行。

__dict__ 以字典的形式返回類的所有屬性

__str__ 改變物件的字串顯示
1、2、3、4、5 能組成多少個互不相同且無重複的三位數
60個
import itertools
print(len(list(itertools.permutations('12345', 3)))) # 60

題意理解:組成後的數值不相同,且組合的三個位數之間數字不重複。
使用python內建的排列組合函式(不放回抽樣排列)
product 笛卡爾積  (有放回抽樣排列)
permutations 排列  (不放回抽樣排列)
combinations 組合,沒有重複  (不放回抽樣組合)
combinations_with_replacement 組合,有重複  (有放回抽樣組合)
什麼是反射?以及應用場景?
python面向物件中的反射:通過字串的形式操作物件相關的屬性。python中的一切事物都是物件(都可以使用反射)
反射的核心本質就是以字串的形式去匯入個模組,利用字串的形式去執行函式。
Django中的 CBV就是基於反射實現的。
metaclass作用?以及應用場景?
metaclass用來指定類是由誰建立的。 可以在建立類的前後做一些定製操作
類的metaclass 預設是type。我們也可以指定類的metaclass值。在python3中:
class MyType(type):
def __init__(self,*args,**kwargs):
print('建立類之前')
super(MyType,self).__init__(*args,**kwargs)
print('建立類之後')
class Foo(object,metaclass=MyType): # 當前類,由type類建立。
CITY = "bj"
def func(self, x):
return x + 1
用盡量多的方法實現單例模式。 什麼是單例模式????
# 1. 基於__new__方法
class Singleton:
_INSTANCE = None

def __new__(cls, *args, **kwargs):
if not cls._INSTANCE:
cls._INSTANCE = super().__new__(cls, *args, **kwargs)
return cls._INSTANCE

# a = Singleton()
# b = Singleton()
# print(a is b)

# 2. 基於裝飾器
def singleton(cls):
_instance = None
def inner(*args, **kwargs):
nonlocal _instance
if not _instance:
_instance = cls(*args, **kwargs)
return _instance
return inner


@singleton
class Foo:
x = 5


a = Foo()
b = Foo()
print(a is b)
print(type(a), type(b))
裝飾器的寫法以及應用場景。
什麼是裝飾器?
裝飾器,是一個函式,能作為物件被呼叫,能作為返回值被返回,能做閉包函式;
在不修改被裝飾物件原始碼以及呼叫方式的前提下為其新增新功能;
請手寫裝飾器?
import functools

def wapper(func):
@functools.wraps(func)
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner

問題:裝飾器都在哪裡用過?或者說應用場景在哪裡?
   - 應用:
   - flask:路由、before_request
   - django: csrf、快取、使用者登入
異常處理寫法以及如何主動跑出異常(應用場景)
try:

try塊的語句...

except exceptiontype1 as var:#使用as語句獲得本次捕獲到的異常的例項var

   except塊語句...

raise主動丟擲一個異常
什麼是面向物件的mro
類的mro方法 會返回一個列表 裡面是按順序排列的類所繼承的所有的父類 且不會重複
isinstance作用以及應用場景?
isinstance() 函式來判斷一個物件是否是一個已知的型別,類似 type()。
isinstance() 與 type() 區別:
type() 不會認為子類是一種父類型別,不考慮繼承關係。
isinstance() 會認為子類是一種父類型別,考慮繼承關係。
如果要判斷兩個型別是否相同推薦使用 isinstance()。

isinstance用得少。只有在用某些面向物件的生產模式的時候才會用到。通常是判斷類的繼承關係。
>>> class a:
... v1=1
>>> class b:
... v2=2
>>> class c(a):
... v1=3
>>> x=c()
>>> isinstance(x,a)
True
>>> isinstance(x,c)
True
>>> isinstance(x,b)
False
寫程式碼並實現: 參考部落格# https://blog.csdn.net/qq_28119401/article/details/52972461
Given an array of integers, return indices of the two numbers such that they add up to a specific target.You may assume that each input would
have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1]
json序列化時,可以處理的資料型別有哪些?如何定製支援datetime型別?
1、數字(整型、浮點數、定點數);
2、字元和字串;
3、布林型別。
還有其他資料型別:
一、物件;
二、null;
三、陣列。
注意,複合資料型別物件的資料結構可以被解構為原始資料型別。
datetime型別:
import json
from json import JSONEncoder
from datetime import datetime
class ComplexEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
else:
return super(ComplexEncoder,self).default(obj)
d = { 'name':'alex','data':datetime.now()}
print(d)
print(json.dumps(d,cls=ComplexEncoder))
json序列化時,預設遇到中文會轉換成unicode,如果想要保留中文怎麼辦?
json.dumps(json.loads(result),ensure_ascii=False) #ensure_ascii=False用這個
什麼是斷言?應用場景?
斷言是面向物件中的,as
python assert斷言是宣告其布林值必須為真的判定,如果發生異常就說明表達示為假
比如我想測試 a==1。就可以用斷言。如果我的猜想錯誤就會丟擲異常,可以用於測試一段表示式是否成立。

a = 1
assert a == 1
assert a == 2
應用場景:
from rest_framework.generics import GenericAPIView 這裡面有assert,如果不是queryset= 型別,則報錯
有用過with statement嗎?它的好處是什麼?
要使用 with 語句,首先要明白上下文管理器這一概念。有了上下文管理器,with 語句才能工作。
下面是一組與上下文管理器和with 語句有關的概念。with 語句支援執行時上下文這一概念。
上下文管理器(Context Manager):支援上下文管理協議的物件,這種物件實現了
__enter__() 和 __exit__() 方法。 __enter__() 和__exit__() 方法負責執行 with 語句塊上下文中的進入與退出操作。
語句體(with-body):with 語句包裹起來的程式碼塊,在執行語句體之前會呼叫上下文管
理器的 __enter__() 方法,執行完語句體之後會執行 __exit__() 方法。 當我們操作檔案結束時 它能幫我們自動關閉檔案。
使用程式碼實現檢視列舉目錄下的所有檔案。
import os
for filename in os.listdir(r'c:\windows'):
print(filename)
簡述 yield和yield from關鍵字。

函式中使用yield,可以使函式變成生成器。一個函式如果是生成一個數組,就必須把資料儲存在記憶體中,
如果使用生成器,則在呼叫的時候才生成資料,可以節省記憶體。
為了讓生成器(帶yield函式),能簡易的在其他函式中直接呼叫,就產生了yield from。
yield from 可以直接呼叫生成器(帶yield函式)。

第二部分 網路程式設計和併發(34題)
簡述osi七層協議
應用層 #桌面上所見的應用(.exe檔案),以及能看到的應用程式
-表示層
-會話層#OSI是理論模型,其他協議裡一般抽象成一個應用層,由程式的開發者控制。
傳輸層 #可靠性傳輸,校驗,糾錯,重傳,重排序等。
網路層 # IP協議和路由協議。IP包的組包,解包和傳送。
資料鏈路層 # arp協議;有一定的糾錯,如重傳可以解決短時間的鏈路質量波動。單還是要靠TCP保證傳輸可靠性。
物理層 # 把資料轉化成高低電平傳送出去
什麼是C/S和B/S架構?
client和server端
Broswer端(網頁端)與server端
簡述三次握手、四次揮手的流程
建立連線需要三次握手:
三次握手,客戶端先發給服務端說我要跟你建立連線,可以嗎?;然後服務端發給客戶端,我也要和你建立連線可以嗎?;客戶端再發給服務端說可以,這就表示建立連線成功
斷開連線需要四次揮手:
客戶端告訴服務端,要準備斷開連線,服務端第一次告訴客戶端,說同意斷開連線;第二次再告訴客戶端要進行斷開連線了。然後客戶端再發給服務端表示也斷開連線了。
什麼是arp協議?
ARP是英文Address Resolution Protocol的簡稱,中文名叫做:地址解析協議,是一個位於TCP/IP協議棧中的底層協議,對應於資料鏈路層,負責將某個IP地址解析成對應的MAC地址。

ARP協議的基本功能就是通過目標裝置的IP地址,查詢目標裝置的MAC地址,以保證通訊的進行。從IP地址到實體地址的對映有兩種方式:表格方式和非表格方式。ARP具體說來就是將網路層(IP層,也就是相當於OSI的第三層)地址解析為資料鏈路層(MAC層,也就是相當於OSI的第二層)的MAC地址。

對於普通使用者來說,以上的解釋可能很難理解,下面用通俗易懂的語音為大家說明一下。我們的電腦、手機等裝置要上網際網路需要一塊網絡卡,這個網絡卡有一個實體地址,又叫做MAC地址,MAC地址具有全球唯一性;同時我們上網的時候還需要一個IP地址。ARP的作用就是把IP地址和MAC地址對應起來,建立一張對應的表格,根據ARP對映表,就可以根據IP地址找到目標裝置,實現通訊。
TCP和UDP的區別?
PS:什麼是TCP和UDP?
TCP和UDP是OSI模型中的運輸層中的協議。TCP提供可靠的通訊傳輸,而UDP則常被用於讓廣播和細節控制交給應用的通訊傳輸。
TCP協議操作:
伺服器端: 客戶端
建立套接字 建立套接字
繫結ip和埠 繫結ip和埠
監聽 連線伺服器
accept等待連線 通訊(收recv,發send)
通訊(收recv,發send)

面向連線:
通訊之前先要三次握手
斷開之前先要四次揮手
安全、可靠、面向連線(不會丟包)

UDP:傳輸速度快
不面向連線,不能保證資料的完整性

伺服器端: 客戶端:
建立套接字 繫結套接字
繫結ip和埠 通訊(收recvfrom,發sendto)
通訊(收recvfrom,發sendto)
什麼是區域網和廣域網?
區域網和廣域網是按規模大小而劃分的兩種計算機網路。範圍在幾千米以內的計算機網路統稱為區域網;而連線的範圍超過10千米的,則稱為廣域網,因特網(Intenet)就是目前最大的廣域網。
為何基於TCP協議的通訊比基於udp的協議通訊更可靠?
TCP協議操作:
面向連線:
通訊之前先要三次握手
斷開之前先要四次揮手
安全、可靠、面向連線(不會丟包)

UDP:傳輸速度快
不面向連線,不能保證資料的完整性
什麼是socket?簡述基於tcp協議的套接字通訊流程。
Socket是連線執行在網路上的兩個程式間的雙向通訊的端點。
伺服器端程式將一個套接字繫結到一個特定的埠,並通過此套接字等待和監聽客戶的連線請求。
客戶端程式根據伺服器程式所在的主機名和埠號發出連線請求。
什麼是粘包? socket 中造成粘包的原因是什麼? 哪些情況會發生粘包現象?
粘包問題的本質就是資料讀取邊界錯誤所致。
原因:所謂粘包問題主要還是因為接收方不知道訊息之間的界限,不知道一次性提取多少位元組的資料所造成的。
兩種情況下會發生粘包。

傳送端需要等緩衝區滿才傳送出去,造成粘包(傳送資料時間間隔很短,資料了很小,會合到一起,產生粘包)
IO多路複用的作用?
IO多路複用的作用?
目標:用於監聽多個socket物件是否發生變化。
- select,內部迴圈檢測socket是否發生變化;1024個socket
- poll,內部迴圈檢測socket是否發生變化;
- epoll,回撥的方式

程式碼例項:

import select

while True:
# 讓select模組幫助我們去檢測sk1/sk2兩個socket物件是否已經發生“變化”
# r=[]
# 如果r中有值
# r=[sk1,] 表示:sk1這個socket已經獲取到響應的內容
# r=[sk1,sk2] 表示:sk1,sk2兩個socket已經獲取到響應的內容
# w=[],如果w中有值
# w=[sk1,], 表示:sk1這個socket已經連線成功;
# w=[sk1,sk2],表示:sk1/sk2兩個socket已經連線成功;

r,w,e = select.select([sk1,sk2],[sk1,sk2],[],0.5)

for client in w:
content = "GET /wupeiqi HTTP/1.1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36\r\n\r\n"
client.sendall(content.encode('utf-8'))

for cli in r:
response = cli.recv(8096)
print(response)
cli.close()
什麼是防火牆以及作用?

防火牆它是一種位於內部網路與外部網路之間的網路安全系統。一項資訊保安的防護系統,依照特定的規則,允許或是限制傳輸的資料通過。 它可通過監測、限制、更改跨越防火牆的資料流,儘可能地對外部遮蔽網路內部的資訊、結構和執行狀況, 以此來實現網路的安全保護。
作用:
它可通過監測、限制、更改跨越防火牆的資料流,儘可能地對外部遮蔽網路內部的資訊、結構和執行狀況, 以此來實現網路的安全保護。
select、poll、epoll 模型的區別?
- select,內部迴圈檢測socket是否發生變化;1024個socket
- poll,內部迴圈檢測socket是否發生變化;
- epoll,回撥的方式
簡述 程序、執行緒、協程的區別 以及應用場景?
程序:
正在執行的一個程式或者一個任務,而執行任務的是cpu。
每個程序都有自己的獨立記憶體空間,不同程序通過程序間通訊來通訊。由於程序比較重量,佔據獨立的記憶體,所以上下文程序間的切換開銷(棧、暫存器、虛擬記憶體、檔案控制代碼等)比較大,相比執行緒資料相對比較穩定安全。

程序:
是一種狀態,執行過程中的才叫程序
程序:
是最小的資源管理單元


切換:
是程式的儲存
切換的操作者:作業系統
##########
執行緒:
執行緒是程序的一個實體,是CPU排程和分派的基本單位
  執行緒間通訊主要通過共享記憶體,上下文切換很快,資源開銷較少,但相比程序不夠穩定容易丟失資料。
--執行緒也叫輕量級程序,它是一個基本的CPU執行單元,也是程式執行過程中的最小單元,由執行緒ID、程式計數器、暫存器集合和堆疊共同組成。 執行緒是最小的執行單位
--執行緒開銷要遠遠小於程序開銷。

執行緒:最小的執行單位

------>
程序和執行緒兩者關係:
執行緒一定要在程序裡面的
(1)一個執行緒只能屬於一個程序,而一個程序可以有多個執行緒,但至少有一個執行緒。
(2)資源分配給程序,同一程序的所有執行緒共享該程序的所有資源。
(3)CPU分給執行緒,即真正在CPU上執行的是執行緒。
------>

程序/執行緒切換的原則:
1、時間片 就是切換時候所需的時間,有時候覺得很短,我們察覺不到,其實也是有的
2、遇到IO操作切換 io阻塞,是等待期間,不佔cpu,io就類似炒菜期間,沒有鹽了,就需要去買鹽一樣。
3、優先順序切換,一定要按照優先順序來執行(類似手機來電話似得,在玩遊戲時候,來電話了也會有顯示)
##########


原理:
1. 什麼是協程?
- 是“微執行緒”,不存在;是由程式設計師人為創造出來並控制程式:先執行某段程式碼、再跳到某處執行某段程式碼。

- 如果遇到非IO請求來回切換:效能更低。
- 如果遇到IO(耗時)請求來回切換:效能高、實現併發(本質上利用IO等待的過程,再去幹一些其他的事)


  優點:
    1. 協程的切換開銷更小,屬於程式級別的切換,作業系統完全感知不到,因而更加輕量級
    2. 單執行緒內就可以實現併發的效果,最大限度地利用cpu
  缺點:
    1、遇到非IO請求來回切換:效能更低。
    2、無法利用多核

1、程序與執行緒比較
  1) 地址空間:執行緒是程序內的一個執行單元,程序內至少有一個執行緒,它們共享程序的地址空間,而程序有自己獨立的地址空間
  2) 資源擁有:程序是資源分配和擁有的單位,同一個程序內的執行緒共享程序的資源
  3) 執行緒是處理器排程的基本單位,但程序不是
  4) 二者均可併發執行
  5) 每個獨立的執行緒有一個程式執行的入口、順序執行序列和程式的出口,但是執行緒不能夠獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制
2、協程與執行緒進行比較
  1) 一個執行緒可以多個協程,一個程序也可以單獨擁有多個協程,這樣python中則能使用多核CPU。
  2) 執行緒程序都是同步機制,而協程則是非同步
  3) 協程能保留上一次呼叫時的狀態,每次過程重入時,就相當於進入上一次呼叫的狀態
GIL鎖是什麼鬼?
GIL互斥鎖,將併發執行變成序列,以此來控制同一時間內共享資料只能被一個任務所修改,進而保證資料安全。
簡單說,就是鎖住其他程序,只能執行一個程序
Python中如何使用執行緒池和程序池?
程序池
就是在一個程序內控制一定個數的執行緒,
程序池內部維護一個程序序列,當使用時,則去程序池中獲取一個程序,如果程序池序列中沒有可供使用的進程序,那麼程式就會等待,直到程序池中有可用程序為止。

程序池中有兩個方法:

apply
apply_async

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from multiprocessing import Process,Pool
import time

def Foo(i):
time.sleep(2)
return i+100

def Bar(arg):
print arg

pool = Pool(5)
#print pool.apply(Foo,(1,))
#print pool.apply_async(func =Foo, args=(1,)).get()

for i in range(10):
pool.apply_async(func=Foo, args=(i,),callback=Bar)

print 'end'
pool.close()
pool.join()#程序池中程序執行完畢後再關閉,如果註釋,那麼程式直接關閉。
threading.local的作用?

為執行緒之間建立相互隔離的儲存
或者說:為每個執行緒開闢一塊空間進行資料儲存。
程序之間如何進行通訊?
1. 管道pipe:管道是一種半雙工的通訊方式,資料只能單向流動,而且只能在具有親緣關係的程序間使用。程序的親緣關係通常是指父子程序關係。
2. 命名管道FIFO:有名管道也是半雙工的通訊方式,但是它允許無親緣關係程序間的通訊。
4. 訊息佇列MessageQueue:訊息佇列是由訊息的連結串列,存放在核心中並由訊息佇列識別符號標識。訊息佇列克服了訊號傳遞資訊少、管道只能承載無格式位元組流以及緩衝區大小受限等缺點。
5. 共享儲存SharedMemory:共享記憶體就是對映一段能被其他程序所訪問的記憶體,這段共享記憶體由一個程序建立,但多個程序都可以訪問。共享記憶體是最快的 IPC 方式,它是針對其他程序間通訊方式執行效率低而專門設計的。它往往與其他通訊機制,如訊號兩,配合使用,來實現程序間的同步和通訊。
6. 訊號量Semaphore:訊號量是一個計數器,可以用來控制多個程序對共享資源的訪問。它常作為一種鎖機制,防止某程序正在訪問共享資源時,其他程序也訪問該資源。因此,主要作為程序間以及同一程序內不同執行緒之間的同步手段。
7. 套接字Socket:套解口也是一種程序間通訊機制,與其他通訊機制不同的是,它可用於不同及其間的程序通訊。
8. 訊號 ( sinal ) : 訊號是一種比較複雜的通訊方式,用於通知接收程序某個事件已經發生。
什麼是併發和並行?
併發和並行從巨集觀上來講都是同時處理多路請求的概念。
但併發和並行又有區別,並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多個事件在同一時間間隔內發生。
19程序鎖和執行緒鎖的作用?
執行緒鎖是鎖執行緒的,鎖住禁用,如果4執行緒的CPU鎖一個執行緒剩餘三個(如果可以鎖的話),就像四車道封鎖一條車道還剩3個車道可以跑車;
程序鎖是鎖程序的,程序就是正在執行的程式,鎖住程序就是鎖住程式禁止程式的任何操作,就像鎖住汽車不能開車一樣。

說了這麼多,再補充一點,執行緒鎖,程序鎖,分散式鎖的作用都是一樣的,只是作用的範圍大小不同。範圍大小:分散式鎖>程序鎖>執行緒鎖。能用執行緒鎖,程序鎖情況下使用分散式鎖也是可以的,能用執行緒鎖的情況下使用程序鎖也是可以的。只是範圍越大技術複雜度就越大。
解釋什麼是非同步非阻塞?
什麼是非同步非阻塞?
- 非阻塞
- 不等待(報錯,捕捉異常)
- 程式碼:
sk = socket.socket()
sk.setblocking(False)
- 非同步:
- 回撥,當達到某個指定的狀態之後,自動呼叫特定函式。

示例:nb_async.py 實現非同步非阻塞的模組。

自定義非同步非阻塞模組
路由器和交換機的區別? #http://www.cnblogs.com/hanfei-1005/p/5685938.html
 --路由器可以給你的區域網自動分配IP,虛擬撥號,就像一個交通警察,指揮著你的電腦該往哪走,你自己不用操心那麼多了。交換機只是用來分配網路資料的。
 路由器在網路層,路由器根據IP地址定址,路由器可以處理TCP/IP協議,交換機不可以。

交換機在中繼層,交換機根據MAC地址定址。

--路由器可以把一個IP分配給很多個主機使用,這些主機對外只表現出一個IP。
交換機可以把很多主機連起來,這些主機對外各有各的IP。
--路由器提供防火牆的服務,交換機不能提供該功能。集線器、交換機都是做埠擴充套件的,就是擴大區域網(通常都是乙太網)的接入點,也就是能讓區域網可以連進來更多的電腦。 路由器是用來做網間連線,也就是用來連線不同的網路。
什麼是域名解析?
域名解析是把域名指向網站空間IP,讓人們通過註冊的域名可以方便地訪問到網站的一種服務。I
如何修改本地hosts檔案?
Hosts是一個沒有副檔名的系統檔案,可以用記事本等工具開啟,其作用就是將一些常用的網址域名與其對應的IP地址建立一個關聯“資料庫”,
當用戶在瀏覽器中輸入一個需要登入的網址時,系統會首先自動從Hosts檔案中尋找對應的IP地址,一旦找到,系統會立即開啟對應網頁,
如果沒有找到,則系統會再將網址提交DNS域名解析伺服器進行IP地址的解析。
瀏覽器訪問網站,要首先通過DNS伺服器把要訪問的網站域名解析成一個唯一的IP地址,之後,瀏覽器才能對此網站進行定位並且訪問其資料。
作業系統規定,在進行DNS請求以前,先檢查系自己的Hosts檔案中是否有這個域名和IP的對映關係。如果有,則直接訪問這個IP地址指定的網路位置,
如果沒有,再向已知的DNS伺服器提出域名解析請求。也就是說Hosts的IP解析優先順序比DNS要高。
修改方式:ip 域名 127.0.0.1 www.163.com
生產者消費者模型應用場景及優勢?
生產者------>緩衝區------>消費者
有流程圖我們可以知道,生產者不關心資料什麼時候被處理,消費者不關心資料什麼時候產生,實現瞭解耦,也解決了阻塞。
還有一個比較典型的例子便是日誌的記錄,多執行緒產生日誌,但寫日誌由於檔案獨佔,不能多執行緒來寫,於是我們就可以把執行緒壓入佇列,由日誌執行緒來讀取佇列資料,完成寫日誌的操作。

為什麼要使用生產者和消費者模式
線上程世界裡,生產者就是生產資料的執行緒,消費者就是消費資料的執行緒。在多執行緒開發當中,
如果生產者處理速度很快,而消費者處理速度很慢,那麼生產者就必須等待消費者處理完,
才能繼續生產資料。同樣的道理,如果消費者的處理能力大於生產者,那麼消費者就必須等待生產者。
為了解決這個問題於是引入了生產者和消費者模式。
什麼是生產者消費者模式
生產者消費者模式是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,
而通過阻塞佇列來進行通訊,所以生產者生產完資料之後不用等待消費者處理,直接扔給阻塞佇列,
消費者不找生產者要資料,而是直接從阻塞佇列裡取,阻塞佇列就相當於一個緩衝區,平衡了生產者和消費者的處理能力。
在併發程式設計中使用生產者和消費者模式能夠解決絕大多數併發問題。該模式通過平衡生產執行緒和消費執行緒的工作能力來提高程式的整體處理資料的速度。
什麼是cdn?
CDN的全稱是Content Delivery Network,即內容分發網路。其目的是通過在現有的Internet中增加一層新的網路架構,
將網站的內容釋出到最接近使用者的網路"邊緣",使使用者可以就近取得所需的內容,解決Internet網路擁擠的狀況,提高使用者訪問網站的響應速度。
從技術上全面解決由於網路頻寬小、使用者訪問量大、網點分佈不均等原因所造成的使用者訪問網站響應速度慢的問題。
LVS是什麼及作用?
LVS 是 Linux Virtual Server ,Linux 虛擬伺服器;是一個虛擬的伺服器叢集【多臺機器 LB IP】是一個虛擬的四層交換器集群系統,
根據目標地址和目標埠實現使用者請求轉發,本身不產生流量,只做使用者請求轉發,目前是負載均衡效能最好的集群系統。

LVS主 要用於多伺服器的負載均衡。它工作在網路層,可以實現高效能,高可用的伺服器叢集技術。它廉價,可把許多低效能的伺服器組合在一起形成一個超級伺服器。它 易用,配置非常簡單,且有多種負載均衡的方法。它穩定可靠,即使在叢集的伺服器中某臺伺服器無法正常工作,也不影響整體效果。另外可擴充套件性也非常好。
Nginx是什麼及作用?
--靜態HTTP伺服器
首先,Nginx是一個HTTP伺服器,可以將伺服器上的靜態檔案(如HTML、圖片)通過HTTP協議展現給客戶端。
--反向代理伺服器
客戶端本來可以直接通過HTTP協議訪問某網站應用伺服器,網站管理員可以在中間加上一個Nginx,客戶端請求Nginx,Nginx請求應用伺服器,然後將結果返回給客戶端,此時Nginx就是反向代理伺服器。
--負載均衡 當網站訪問量非常大,網站站長開心賺錢的同時,也攤上事兒了。因為網站越來越慢,一臺伺服器已經不夠用了。於是將同一個應用部署在多臺伺服器上,將大量使用者的請求分配給多臺機器處理。同時帶來的好處是,其中一臺伺服器萬一掛了,只要還有其他伺服器正常執行,就不會影響使用者使用。

Nginx可以通過反向代理來實現負載均衡。
keepalived是什麼及作用? #https://blog.csdn.net/cooling88/article/details/52504854
keepalived是基於VRRP協議實現的保證叢集高可用的一個服務軟體,主要功能是實現真機的故障隔離和負載均衡器間的失敗切換,防止單點故障。
haproxy是什麼以及作用?#https://blog.csdn.net/qq_26562641/article/details/52511690
haproxy是一款功能強大、靈活好用反向代理軟體,提供了高可用、負載均衡、後端伺服器代理的功能,它在7層負載均衡方面的功能很強大(支援cookie track, header rewrite等等),支援雙機熱備,支援虛擬主機,擁有非常不錯的伺服器健康檢查功能,當其代理的後端伺服器出現故障, HAProxy會自動將該伺服器摘除,故障恢復後再自動將該伺服器加入;同時還提供直觀的監控頁面,可以清晰實時的監控服務叢集的執行狀況。
什麼是負載均衡? 建立在現有網路結構之上,它提供了一種廉價有效透明的方法擴充套件網路裝置和伺服器的頻寬、增加吞吐量、加強網路資料處理能力、提高網路的靈活性和可用性。
什麼是rpc及應用場景?
RPC 的主要功能目標是讓構建分散式計算(應用)更容易,在提供強大的遠端呼叫能力時不損失本地呼叫的語義簡潔性。為實現該目標,RPC 框架需提供一種透明呼叫機制讓使用者不必顯式的區分本地呼叫和遠端呼叫,在前文《淺出篇》中給出了一種實現結構,基於 stub 的結構來實現。下面我們將具體細化 stub 結構的實現。
簡述 asynio模組的作用和應用場景。
實現高併發的一個模組

非同步網路操作
併發
協程
當然到目前為止實現協程的不僅僅只有asyncio,tornado和gevent都實現了類似功能
簡述 gevent模組的作用和應用場景。
gevent是python的一個併發框架,以微執行緒greenlet為核心,使用了epoll事件監聽機制以及諸多其他優化而變得高效.而且其中有個monkey類,

將現有基於Python執行緒直接轉化為greenlet(類似於打patch)
1.遊戲伺服器,基本是gevent ,tornado,twisted三選一,如遊戲伺服器框架gfirefly2.爬蟲,gevent的pool是個大殺器3.使用gevent加速web應用,如flask搭配gevent,還可以實現長連線(ajax方式),websocketgevent一般高併發用的比較多,goagent也使用了gevent,openstack使用了eventlet,這是gevent的胞弟
twisted框架的使用和應用?
http://www.cnblogs.com/zhiyong-ITNote/p/7360442.html

第三部分 資料庫和快取(46題)
列舉常見的關係型資料庫和非關係型都有那些?
什麼是關係型資料庫?
關係型資料庫是依據關係模型來建立的資料庫。
所謂關係模型就是“一對一、一對多、多對多”等關係模型,關係模型就是指二維表格模型,因而一個關係型資料庫就是由二維表及其之間的聯絡組成的一個數據組織。
關係型資料可以很好地儲存一些關係模型的資料,比如一個老師對應多個學生的資料(“多對多”),一本書對應多個作者(“一對多”),一本書對應一個出版日期(“一對一”)
關係模型是我們生活中能經常遇見的模型,儲存這類資料一般用關係型資料庫
關係模型包括資料結構(資料儲存的問題,二維表)、操作指令集合(SQL語句)、完整性約束(表內資料約束、表與表之間的約束)。

常見的關係型資料庫:
Oracle、DB2、PostgreSQL、Microsoft SQL Server、Microsoft Access、MySQL
關係型資料庫的特點:
安全(因為儲存在磁碟中,不會說突然斷電資料就沒有了)、
容易理解(建立在關係模型上)、
但不節省空間(因為建立在關係模型上,就要遵循某些規則,好比資料中某欄位值即使為空仍要分配空間)
什麼是非關係型資料庫?
非關係型資料庫主要是基於“非關係模型”的資料庫(由於關係型太大,所以一般用“非關係型”來表示其他型別的資料庫)
非關係型模型比如有:
列模型:儲存的資料是一列列的。關係型資料庫以一行作為一個記錄,列模型資料庫以一列為一個記錄。(這種模型,資料即索引