315道Python面試題答案

目錄

 

正文

Python基礎篇

1:爲什麼學習Python

家裏有在這個IT圈子裏面,也想讓我接觸這個圈子,然後給我建議學的Python,
然後自己通過百度和向有學過Python的同學瞭解了Python,Python這門語言,入門比較簡單,
它簡單易學,生態圈比較強大,涉及的地方比較多,特別是在人工智能,和數據分析這方面。在未來我覺得是往自動化,
人工智能這方面發展的,所以學習了Python

2:通過什麼途徑學習Python

剛開始接觸Python的時候,到網上裏面跟着視頻學基礎,再後來網上到看技術貼,然後看到有人推薦廖雪峯的Python教程,
練項目到GitHub上面找一些小項目學習。

3:談談對Python和其他語言的區別

複製代碼
Python屬於解釋型語言,當程序運行時,是一行一行的解釋,並運行,所以調式代碼很方便,開發效率高,
還有龜叔給Python定位是任其自由發展、優雅、明確、簡單,所以在每個領域都有建樹,所有它有着非常強大的第三方庫,
特點:
語法簡潔優美,功能強大,標準庫與第三方庫都非常強大,而且應用領域也非常廣
可移植性,可擴展性,可嵌入性
缺點:
  運行速度慢,

- 解釋型 - python/php - 編譯型 - c/java/c#
  • Python弱類型
複製代碼

 (1)與java相比:在很多方面,Python比Java要簡單,比如java中所有變量必須聲明才能使用,而Python不需要聲明,用少量的代碼構建出很多功能;(高效的高級數據結構)

(2)與php相比:python標準包直接提供了工具,並且相對於PHP代碼更易於維護;

(3)Python與c相比:

Python 和 C Python這門語言是由C開發而來

  對於使用:Python的類庫齊全並且使用簡潔,如果要實現同樣的功能,Python 10行代碼可以解決,C可能就需要100行甚至更多.
  對於速度:Python的運行速度相較與C,絕逼是慢了

Python的優勢:

1、Python 易於學習;

2、用少量的代碼構建出很多功能;(高效的高級數據結構)

3、Python 擁有最成熟的程序包資源庫之一;

4、Python完全支持面向對象;

5、Python 是跨平臺且開源的。

6、動態類型:

4:簡述解釋型和編譯型編程語言

解釋型:就是邊解釋邊執行(Python,php)
編譯型:編譯後再執行(c、java、c#)

5:Python的解釋器種類以及相關特點?

複製代碼
CPython

是官方版本的解釋器:CPython。是使用C語言開發的,所以叫CPython。在命令行下運行python就是啓動CPython解釋器。
CPython是使用最廣的Python解釋器。教程的所有代碼也都在CPython下執行。

IPython
IPython是基於CPython之上的一個交互式解釋器,也就是說,IPython只是在交互方式上有所增強,但是執行Python代碼的功能和CPython是完全一樣的。CPython用>>>作爲提示符,而IPython用In [序號]:作爲提示符。
複製代碼
複製代碼


PyPy

由Python寫的解釋器,它的執行速度是最快。PyPy採用JIT技術,對Python代碼進行動態編譯(注意不是解釋),
絕大部分Python代碼都可以在PyPy下運行,但是PyPy和CPython有一些是不同的,這就導致相同的Python代碼在兩種解釋器下執行可能會有不同的結果。

Jython
Jython是運行在Java平臺上的Python解釋器,可以直接把Python代碼編譯成Java字節碼執行。

IronPython
IronPython和Jython類似,只不過IronPython是運行在.Net平臺上的Python解釋器,可以直接把Python代碼編譯成.Net的字節碼。

小結:
  Python的解釋器很多,但使用最廣泛的還是CPython。如果要和Java或.Net平臺交互,最好的辦法不是用Jython或IronPython,而是通過網絡調用來交互,確保各程序之間的獨立性。

複製代碼

6:位和字節的關係

1字節 = 8 位
位(bit),數據存儲是以「字節」(Byte)爲單位,數據傳輸是以大多是以「位」(bit,又名「比特」)爲單位,
一個位就代表一個0或1(即一個二進制),二進制是構成存儲器的最小單位,每8個位(bit,簡寫爲b)組成一個字節(Byte,簡寫爲B),
字節是最小一級的信息單位

7:b、B、KB、MB、GB的關係

b --->位(bit)    

B --->字節      一個字節等於8位

1B = 8 bit

1kb = 1024 B

1 MB = 1024 KB

1 GB = 1024 MB

8:PE8規範

複製代碼
1、使用4個空格而不是tab鍵進行縮進。
2、每行長度不能超過79
3、使用空行來間隔函數和類,以及函數內部的大塊代碼
4、必要時候,在每一行下寫註釋
5、使用文檔註釋,寫出函數註釋
6、在操作符和逗號之後使用空格,但是不要在括號內部使用
7、命名類和函數的時候使用一致的方式,比如使用CamelCase來命名類,
           使用lower_case_with_underscores來命名函數和方法
8、在類中總是使用self來作爲默認
 9、儘量不要使用魔法方法
10、默認使用UTF-8,甚至ASCII作爲編碼方式
11、換行可以使用反斜槓,最好使用圓括號。
12、不要在一句import中多個庫,
空格的使用
  1. 各種右括號前不要加空格。
  2. 逗號、冒號、分號前不要加空格。
  3. 函數的左括號前不要加空格。如Func(1)
  4. 序列的左括號前不要加空格。如list[2]
  5. 操作符左右各加一個空格,不要爲了對齊增加空格
  6. 函數默認參數使用的賦值符左右省略空格
  7. 不要將多句語句寫在同一行,儘管使用‘;’允許
  8. if/for/while語句中,即使執行語句只有一句,也必須另起一行
 函數命名使用全部小寫的方式,常量命名使用大寫,類屬性(方法和變量)使用小寫
類的命名首字母大寫
複製代碼

9:通過代碼實現如下轉換(進制之間轉換)

複製代碼
# 二進制轉換成十進制-->int
v = "0b1111011" b = int(v,2) print(b) # 123 

十進制轉換成二進制—>bin

v2 = 18
print(bin(int(v2)))

0b10010

八進制轉換成十進制

v3 = 「011」
print(int(v3))

11

十進制轉換成八進制:—> oct

v4 = 30
print(oct(int(v4)))

0o36

十六進制轉換成十進制:

v5 = 「0x12」
print(int(v5,16))

18

十進制轉換成十六進制:—> hex

v6 = 87
print(hex(int(v6)))

0x57

複製代碼

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

複製代碼
請編寫一個函數實現將IP地址轉換成一個整數。
如 10.3.9.12 轉換規則爲: 10 00001010 

3            00000011

     9            00001001

    12            00001100<span>

再將以上二進制拼接起來計算十進制結果:00001010 00000011 00001001 00001100 =

def v1(addr):
# 取每個數
id = [int(x) for x in addr.split(".")]
print(id)
return sum(id[i] << [24, 16, 8, 0][i] for i in range(4))

print(v1(「127.0.0.1」))

[127, 0, 0, 1]

2130706433

複製代碼

------------------------------------------------

11、python遞歸的最大層數?998

12:求結果(and or or)

複製代碼
1. 求結果:1 or 3
print(1 or 3)  # 1
  1. 求結果:1 and 3
    print(1 and 3) # 3

  2. 求結果:0 and 2 and 1
    print(0 and 2 and 1) # 0

  3. 求結果:0 and 2 or 1
    print(0 and 2 or 1) # 1

  4. 求結果:0 and 2 or 1 or 4
    print(0 and 2 or 1 or 4) # 1

  5. 求結果:0 or Flase and 1
    print(0 or False and 1) # Flase

總結:
  # x or y 如果 x爲真,則值爲x, 否則爲y
  # x and y 如果 x 爲真,則值爲 y,否則爲 x

複製代碼

運算符

1. 求結果:2 & 5

print(2 & 5)  # 10 & 101 => 000 => 0

2. 求結果:2 ^ 5

print(2 ^ 5)  # 10 ^ 101 => 111 => 1*2**0+1*2**1+1*2**2=1+2+4=7

13 :ascii、unicode、utf-8、gbk 區別

複製代碼
python2內容進行編碼(默認ascii),而python3對內容進行編碼的默認爲utf-8。
ascii   最多隻能用8位來表示(一個字節),即:2**8 = 256,所以,ASCII碼最多隻能表示 256 個符號。 unicode 萬國碼,任何一個字符==兩個字節 utf-8 萬國碼的升級版 一箇中文字符==三個字節 英文是一個字節 歐洲的是 2個字節 gbk 國內版本 一箇中文字符==2個字節 英文是一個字節 gbk 轉 utf-8 需通過媒介 unicode
複製代碼

14:字節碼和機器碼的區別

機器碼,學名機器語言指令,有時也被稱爲原生碼,是電腦的CPU可直接解讀的數據。

字節碼是一種中間狀態(中間碼)的二進制代碼(文件)。需要直譯器轉譯後才能成爲機器碼。

複製代碼
什麼是機器碼

機器碼(machine code),學名機器語言指令,有時也被稱爲原生碼(Native Code),是電腦的CPU可直接解讀的數據。
通常意義上來理解的話,機器碼就是計算機可以直接執行,並且執行速度最快的代碼。

總結:機器碼是電腦CPU直接讀取運行的機器指令,運行速度最快,但是非常晦澀難懂,也比較難編寫

什麼是字節碼
字節碼(Bytecode)是一種包含執行程序、由一序列 op 代碼/數據對 組成的二進制文件。
字節碼是一種中間碼,它比機器碼更抽象,需要直譯器轉譯後才能成爲機器碼的中間代碼。

總結:字節碼是一種中間狀態(中間碼)的二進制代碼(文件)。需要直譯器轉譯後才能成爲機器碼。

複製代碼

-----------

複製代碼
#is  比較的是內存地址
#== 比較的是值 # int 具有範圍:-5---256 #對於int 小數據池 範圍:-5----256 創建的相間的數字,都指向同一個內存地址 

#對於字符串 (面試)
1、小數據池 如果有空格,那指向兩個內存地址,
2、長度不能超過 20
3、不能用特殊字符

i = ‘a’*20
j = ‘a’*20
print(i is j) # True

i = 「a」*21
j = 「a」*21
print(i is j) # False

關於編碼所佔字節
unicode: 所有字符(無論英文、中文等) 1個字符:2個字節
gbk:一個字符,英文1個字節,中文兩個字節
utf-8:英文1個字節、 歐洲:2個字節, 亞洲:3個字節

在utf-8中,一箇中文字符佔用3個字節
在gbk中一個漢字佔用2個字節
黎詩 = utf-8(6字節)=48
黎詩 = gbk(4字節)=32

字節和位的關係。
  #一個字節(byte) = 8 位(bit)
  # 位爲最小的單位

簡述變量命名規範
  #1、以字母,數字,下劃線任由結合
  #2、不能以命名太長,不使用拼音,中文
  #3、不能以數字開頭
  #4、不能用關鍵詞

複製代碼

15:三元運算寫法和應用場景?

複製代碼
應用場景:簡化if語句
# 關於三元運算 # 結果+ if + 條件 + else + 結果 result='gt' if 1>3 else 'lt' print(result) # lt # 理解:如果條件爲真,把if前面的值賦值給變量,否則把else後面的值賦值給變量。

lambda 表達式
temp = lambda x,y:x+y
print(temp(4,10)) # 14

可替代:
def foo(x,y):
return x+y
print(foo(4,10)) # 14

複製代碼

16:Python3和Python2的區別?

複製代碼
1:打印時,py2需要可以不需要加括號,py3 需要
python 2 :print ('lili')   ,   print 'lili' python 3 : print ('lili') python3 必須加括號 

exec語句被python3廢棄,統一使用exec函數

2:內涵
Python2:1,臃腫,源碼的重複量很多。
  2,語法不清晰,摻雜着C,php,Java,的一些陋習。
Python3:幾乎是重構後的源碼,規範,清晰,優美。

3、輸出中文的區別
python2:要輸出中文 需加 # -- encoding:utf-8 --
Python3 : 直接搞

4:input不同
python2 :raw_input
python3 :input 統一使用input函數

5:指定字節
python2在編譯安裝時,可以通過參數-----enable-unicode=ucs2 或-----enable-unicode=ucs4分別用於指定使用2個字節、4個字節表示一個unicode;
python3無法進行選擇,默認使用 ucs4
查看當前python中表示unicode字符串時佔用的空間:

impor sys
print(sys.maxunicode)
#如果值是65535,則表示使用usc2標準,即:2個字節表示
#如果值是1114111,則表示使用usc4標準,即:4個字節表示

6
py2:xrange
    range
py3:range 統一使用range,Python3中range的機制也進行修改並提高了大數據集生成效率

7:在包的知識點裏
包:一羣模塊文件的集合 + init
區別:py2 : 必須有__init__
   py3:不是必須的了

8:不相等操作符"<>「被Python3廢棄,統一使用」!="

9:long整數類型被Python3廢棄,統一使用int

10:迭代器iterator的next()函數被Python3廢棄,統一使用next(iterator)

11:異常StandardError 被Python3廢棄,統一使用Exception

12:字典變量的has_key函數被Python廢棄,統一使用in關鍵詞

13:file函數被Python3廢棄,統一使用open來處理文件,可以通過io.IOBase檢查文件類型

複製代碼

17:用一行代碼實現數值交換

a = 1 
b = 2

a, b = b, a

18:Python3和Python2中int和long區別

在python3裏,只有一種整數類型int,大多數情況下,和python2中的長整型類似。

19:xrange和range的區別

都在循環時使用,xrange內存性能更好,xrange用法與range完全相同,range一個生成list對象,xrange是生成器

要生成很大的數字序列的時候,用xrange會比range性能優很多,因爲不需要一上來就開闢一塊很大的內存空間。

在python2中:

range([start,] stop[, step]),根據start與stop指定的範圍以及step設定的步長,生成一個序列

例子

xrange用法與range完全相同,所不同的是生成的不是一個數組,而是一個生成器。

例子

由上面的示例可以知道:要生成很大的數字序列的時候,用xrange會比range性能優很多,因爲不需要一上來就開闢一塊很大的內存空間,這兩個基本上都是在循環的時候用。

在 Python 3 中,range() 是像 xrange() 那樣實現,xrange()被拋棄。

20:文件操作時:xreadlines和readlines的區別?

readlines     返回一個列表

xreadlines   返回一個生成器

21: 列列舉布爾值爲False的常見值?

0,「」,{},[],(),set()
0 Flask 負數 不成立的表達式  None 等

22. 字符串、列表、元組、字典每個常用的5個方法?

複製代碼
字符串:
字符串用單引號(')或雙引號(")括起來,不可變 1,find通過元素找索引,可切片,找不到返回-1 2,index,找不到報錯。 3,split 由字符串分割成列表,默認按空格。 4,captalize 首字母大寫,其他字母小寫。 5,upper 全大寫。 6,lower 全小寫。 7,title,每個單詞的首字母大寫。 8,startswith 判斷以什麼爲開頭,可以切片,整體概念。 9,endswith 判斷以什麼爲結尾,可以切片,整體概念。 10,format格式化輸出
#format的三種玩法 格式化輸出
res='{} {} {}'.format('egon',18,'male') ==> egon 18 male
res='{1} {0} {1}'.format('egon',18,'male') ==> 18 egon 18
res='{name} {age} {sex}'.format(sex='male',name='egon',age=18)
11,strip 默認去掉兩側空格,有條件, 12,lstrip,rstrip 14,center 居中,默認空格。 
15,count查找元素的個數,可以切片,若沒有返回0
16,expandtabs 將一個tab鍵變成8個空格,如果tab前面的字符長度不足8個,則補全8個,
17,replace(old,new,次數)
18,isdigit 字符串由字母或數字組成 isalpha, 字符串只由字母組成 isalnum 字符串只由數字組成
19,swapcase 大小寫翻轉
20,for i in 可迭代對象。
字典:
1無序(不能索引)2:數據關聯性強3:鍵值對,鍵值對。唯一一個映射數據類型。 #字典的鍵必須是可哈希的 不可變類型。 在同一個字典中,鍵(key)必須是唯一的。

列表是有序的對象集合,字典是無序的對象集合。兩者之間的區別在於:字典當中的元素是通過鍵來存取的,而不是通過偏移存取 key: 輸出所有的鍵 clear:清空 dic:刪除的鍵如果沒有則報錯 pop:鍵值對刪,有返回,沒有原來的鍵會報錯(自行設置返回鍵就不會報錯) popitem:隨機刪鍵值對 del:刪除的鍵如果沒有則報錯 改 update 查 用get時。不會報錯# 沒有可以返回設定的返回值 注意: 1、字典是一種映射類型,它的元素是鍵值對。 2、字典的關鍵字必須爲不可變類型,且不能重複。 3、創建空字典使用 { }。 列表:
索引,切片,加,乘,檢查成員。 增加:有三種, append:在後面添加。 Insert按照索引添加, expend:迭代着添加。 list.extend(seq) - 在列表末尾一次性追加另一個序列中的多個值(用新列表擴展原來的列表) pop 刪除 (pop 有返回值) remove 可以按照元素去刪 clear 清空列表 del 1、可以按照索引去刪除 2、切片 3、步長(隔着刪) 改 1、索引 2、切片:先刪除,再迭代着添加 list.count(obj) - 統計某個元素在列表中出現的次數 list.index(obj) - 從列表中找出某個值第一個匹配項的索引位置 list.reverse() - 反向列表中元素 list.sort([func]) - 對原列表進行排序 注意: 1、List寫在方括號之間,元素用逗號隔開。 2、和字符串一樣,list可以被索引和切片。 3、List可以使用+操作符進行拼接。 4、List中的元素是可以改變的。 元組:
()元組的元素不能修改 1、cmp(tuple1, tuple2):比較兩個元組元素。 2、len(tuple):計算元組元素個數。 3、max(tuple):返回元組中元素最大值。 4、min(tuple):返回元組中元素最小值。 5、tuple(seq):將列表轉換爲元組。 注意 1、與字符串一樣,元組的元素不能修改。 2、元組也可以被索引和切片,方法一樣。 3、注意構造包含0或1個元素的元組的特殊語法規則。 4、元組也可以使用+操作符進行拼接。
Set(集合)
:集合(set )是一個無序不重複元素的序列。 可以使用大括號 { } 或者 set() 函數創建集合,注意:創建一個空集合必須用 set() 而不是 { },因爲 { } 是用來創建一個空字典。
複製代碼

23、 lambda表達式格式以及應用場景?

複製代碼
匿名函數:爲了解決那些功能很簡單的需求而設計的一句話函數
函數名 = lambda 參數 :返回值 

#參數可以有多個,用逗號隔開
#匿名函數不管邏輯多複雜,只能寫一行,且邏輯執行結束後的內容就是返回值
#返回值和正常的函數一樣可以是任意數據類型

lambda 表達式
temp = lambda x,y:x+y
print(temp(4,10)) # 14

可替代:
def foo(x,y):
return x+y
print(foo(4,10)) # 14

複製代碼

24. pass的作用

pass是空語句,是爲了保持程序結構的完整性。pass 不做任何事情,一般用做佔位語句。

25. *arg和**kwarg作用

 *args代表位置參數,它會接收任意多個參數並把這些參數作爲元祖傳遞給函數。
**kwargs代表的關鍵字參數,返回的是字典,位置參數一定要放在關鍵字前面

26. is和==的區別

複製代碼
a = 'lishi'
str1 = "li" str2 = "shi" str3 = str1 + str2 print("a == str3",a == str3) print("a is str3",a is str3) print("id(a)",id(a)) print("id(str3)",id(str3)) # a == str3 True == ---> 只需要內容相等 # a is str3 False is ---> 只需要內存地址相等 # id(a) 38565848 # id(str3) 39110280
複製代碼
is 比較的是兩個實例對象是不是完全相同,它們是不是同一個對象,佔用的內存地址是否相同。

== 比較的是兩個對象的內容是否相等,即內存地址可以不一樣,內容一樣就可以了。默認會調用對象的 eq()方法。

27:談談Python的深淺拷貝?以及實現方法和應用場景。

淺拷貝只是增加了一個指針指向一個存在的地址,

而深拷貝是增加一個指針並且開闢了新的內存,這個增加的指針指向這個新的內存,
採用淺拷貝的情況,釋放內存,會釋放同一內存,深拷貝就不會出現釋放同一內存的錯誤

一層的情況:

複製代碼
import copy

淺拷貝

li1 = [1, 2, 3]
li2 = li1.copy()
li1.append(4)
print(li1, li2) # [1, 2, 3, 4] [1, 2, 3]

深拷貝

li1 = [1, 2, 3]
li2 = copy.deepcopy(li1)
li1.append(4)
print(li1, li2) # [1, 2, 3, 4] [1, 2, 3]

複製代碼

多層的情況:

複製代碼
import copy

淺拷貝 指向共有的地址

li1 = [1, 2, 3,[4,5],6]
li2 = li1.copy()
li1[3].append(7)
print(li1, li2) # [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5, 7], 6]

深拷貝 重指向

li1 = [1, 2, 3,[4,5],6]
li2 = copy.deepcopy(li1)
li1[3].append(7)
print(li1, li2) # [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5], 6]

複製代碼

28. Python垃圾回收機制?

引用計數

標記清除

分代回收

29. Python的可變類型和不可變類型?

可變數據類型:列表、字典、可變集合

不可變數據類型:數字、字符串、元組、不可變集合

30、求結果

def multipliers():
    return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])
複製代碼
def a():
    return [lambda x:i*x for i in range(4)] b=a() #返回個列表函數 # b[2](1) 

print(b1)

print(type(b),b)

print([m(1) for m in a()])
print([i*i for i in [1,2,3]])
[3, 3, 3, 3]
[1, 4, 9]

‘’’
def multipliers():
return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])
#解釋:
  函數返回值爲一個列表表達式,經過4次循環結果爲包含四個lambda函數的列表,
由於函數未被調用,循環中的i值未被寫入函數,經過多次替代,循環結束後i值爲3,
故結果爲:6,6,6,6

func=lambda x:x+1
print(func(1))
#2
print(func(2))
#3

#以上lambda等同於以下函數
def func(x):
return(x+1)
‘’’

複製代碼
請修改multipliers的定義來產生期望的結果(0,2,4,6)。
def multipliers(): return (lambda x:i*x for i in range(4)) #返回一個生成器表達式 print([m(2) for m in multipliers()])
複製代碼
-面試題2:
現有兩個元組(('a'),('b')),(('c'),('d')),請使用python中匿名函數生成列表[{'a':'c'},{'b':'d'}]

#匿名函數形式:
l1=((‘a’),(‘b’))
l2=((‘c’),(‘d’))
ret=map(lambda n:{n[0]:n[1]},zip(l1,l2))
print(list(ret))
#列表表達式形式:
l1=((‘a’),(‘b’))
l2=((‘c’),(‘d’))
print([{n[0]:n[1]} for n in zip(l1,l2)])

複製代碼

31、求結果

複製代碼
v = dict.fromkeys(['k1', 'k2'], [])
v['k1'].append(666) print(v) v['k1'] = 777 print(v) 

結果:
{‘k1’: [666], ‘k2’: [666]}
{‘k1’: 777, ‘k2’: [666]}

解釋:
Python 字典(Dictionary) fromkeys() 函數用於創建一個新字典,以序列seq中元素做字典的鍵,value爲字典所有鍵對應的初始值,默認爲None。

v1 = dict.fromkeys([‘k1’, ‘k2’])
print(v1) # {‘k1’: None, ‘k2’: None}

v2 = dict.fromkeys([‘k1’, ‘k2’], [])
print(v2) # {‘k1’: [], ‘k2’: []}

複製代碼

32、列舉常見的內置函數

abs()

返回數字的絕對值

map

複製代碼
根據函數對指定序列做映射
map()函數接收兩個參數,一個是函數,一個是可迭代對象,map將傳入的函數依次作用到序列的每個元素,並把結果作爲新的list返回。

返回值:
  Python2 返回列表
  Python3 返回迭代器

例子1: def mul(x): return x*x n=[1,2,3,4,5] res=list(map(mul,n)) print(res) #[1, 4, 9, 16, 25]

例子2:abs() 返回數字的絕對值
ret = map(abs,[-1,-5,6,-7])
print(list(ret))
# [1, 5, 6, 7]
複製代碼

filter

複製代碼
filter()函數接收一個函數 f(函數)和一個list(可迭代對象),這個函數 f的作用是對每個元素進行判斷,返回 True或 False,
filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。
def is_odd(x):
    return x % 2 == 1 

v=list(filter(is_odd, [1, 4, 6, 7, 9, 12, 17]))
print(v) #[1, 7, 9, 17]

複製代碼

map與filter總結

複製代碼
# filter 與 map 總結
# 參數: 都是一個函數名 + 可迭代對象
# 返回值: 都是返回可迭代對象
# 區別:
# filter 是做篩選的,結果還是原來就在可迭代對象中的項
# map 是對可迭代對象中每一項做操作的,結果不一定是原來就在可迭代對象中的項
複製代碼

isinstance\type

複製代碼
isinstance() 函數來判斷一個對象是否是一個已知的類型,類似 type()。
isinstance() 與 type() 區別:
type() 不會認爲子類是一種父類類型,不考慮繼承關係。
isinstance() 會認爲子類是一種父類類型,考慮繼承關係。
如果要判斷兩個類型是否相同推薦使用 isinstance()。
# 例一
a = 2
print(isinstance(a,int)) # True
print(isinstance(a,str)) # False

type() 與 isinstance() 區別

class A:
pass

class B(A):
pass

print(「isinstance」,isinstance(A(),A)) # isinstance True
print(「type」,type(A()) == A) # type True

print(‘isinstance’,isinstance(B(),A) ) # isinstance True
print(‘type’,type(B()) == A) # type False

複製代碼

zip 拉鍊函數

複製代碼
# zip 拉鍊函數,
# 將對象中對應的元素打包成一個個元組,
# 然後返回由這些元組組成的列表迭代器。
# 如果各個迭代器的元素個數不一致,則返回列表長度與最短的對象相同。
print(list(zip([0,1,3],[5,6,7],['a','b']))) # [(0, 5, 'a'), (1, 6, 'b')]
複製代碼
複製代碼
zip() 函數用於將可迭代的對象作爲參數,將對象中對應的元素打包成一個個元組,然後返回由這些元組組成的列表。
>>>a = [1,2,3] >>> b = [4,5,6] >>> c = [4,5,6,7,8] >>> zipped = zip(a,b) # 打包爲元組的列表 [(1, 4), (2, 5), (3, 6)] >>> zip(a,c) # 元素個數與最短的列表一致 [(1, 4), (2, 5), (3, 6)] >>> zip(*zipped) # 與 zip 相反,可理解爲解壓,返回二維矩陣式 [(1, 2, 3), (4, 5, 6)]
複製代碼

reduce

複製代碼
'''
reduce()  函數
reduce() 函數會對參數序列中元素進行累積
函數將一個數據集合(鏈表、元組等)中的所有數據進行下列操作
'''

注意:
Python3已經將reduce() 函數從全局名字空間裏移除了,它現在被放置在 fucntools 模塊裏,如果想要使用它,則需要通過引入 functools 模塊來調用 reduce() 函數:

from functools import reduce
def add(x,y):
return x + y

print(reduce(add,[1,2,3,4,5]))

15

print(reduce(lambda x, y: x+y, [1,2,3,4,5])) # 15

print(reduce(add,range(1,101)))

5050

複製代碼

33. filter、map、reduce的作用?

內置函數:map、reduce、filter的用法和區別

map:根據函數對指定序列做映射

複製代碼
map
參數
接收兩個參數:一個是函數,一個是序列(可迭代對象)
返回值
Python2 返回列表
Python3 返回迭代器

例子:

abs() 函數返回數字的絕對值

新的內容的個數等於原內容的個數

ret = map(abs,[-1,-5,6,-7])

print(list(ret))

[1, 5, 6, 7]

複製代碼

filter:過濾函數 新的內容少於等於原內容的時候。才能使用filter

複製代碼
filter() 函數用於過濾序列,過濾不符合條件的元素,返回由符合條件元素組成的心列表

參數:
function 函數
iterable 可迭代對象
返回值:
返回列表

篩選大於10的數

def is_odd(x):
if x>10:
return True

ret = filter(is_odd,[1,4,5,7,8,9,76]) # 爲迭代器
print(list(ret))

[76]

複製代碼

reduce:對於序列內所有元素進行累計操作

複製代碼
'''
reduce()  函數
reduce() 函數會對參數序列中元素進行累積
函數將一個數據集合(鏈表、元組等)中的所有數據進行下列操作
'''

from functools import reduce
def add(x,y):
return x + y

print(reduce(add,[1,2,3,4,5]))

15

print(reduce(lambda x, y: x+y, [1,2,3,4,5])) # 15

print(reduce(add,range(1,101)))

5050

複製代碼

34、 一行代碼實現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)]))

35. 如何安裝第三方模塊?以及用過哪些第三方模塊?

複製代碼
1:pip包管理器
2:源碼下載 -下載 -解壓 -python setup.py build -python setup.py install
複製代碼

用過的第三方模塊:requests,pymysql,DbUtils,SQLAlchemy等

36、 常用模塊都有那些?

re模塊,os模塊,json模塊,time模塊,

爬蟲裏面的requests/beautifulsoup4(bs4)

37. re的match和search區別?

re.match 嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,match()就返回none。

re.search 掃描整個字符串並返回第一個成功的匹配。

38. 什麼是正則的貪婪匹配?

匹配一個字符串沒有節制,能匹配多少就去匹配多少,知道沒有匹配的爲止

39. 求結果:

a. [ i % 2 for i in range(10) ]

print([ i % 2 for i in range(10) ])  # [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
print([ i  for i in range(10) ])     # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print([ 10 % 2])   # [0]
# %是個運算符。

b. ( i % 2 for i in range(10) )

複製代碼
print(( i % 2 for i in range(10) ))
#  <generator object <genexpr> at 0x00000000020CEEB8> 生成器
# 在Python中,有一種自定義迭代器的方式,稱爲生成器(Generator)。
# 定義生成器的兩種方式:
# 1.創建一個generator,只要把一個列表生成式的[]改成(),就創建了一個generator:
# generator保存的是算法,每次調用next(),就計算出下一個元素的值,直到計算到最後一個元素,
沒有更多的元素時,拋出StopIteration的錯誤。 # 2.定義generator的另一種方法。如果一個函數定義中包含yield關鍵字,那麼這個函數就不再是一個普通函數,
而是一個generator
複製代碼

40. 求結果:

a. 1 or 2
b. 1 and 2
c. 1 < (2==2)
d. 1 < 2 == 2

複製代碼
>>> 1 or 2
1
>>> 1 and 2
2
>>> 1 < (2==2)
False
>>> 1 < 2 == 2 True
複製代碼

 41、def func(a,b=[]) 這種寫法有什什麼坑?

複製代碼
def func(a,b = []):
    b.append(1)
    print(a,b)

func(a=2)
func(2)
func(2)

‘’’
2 [1]
2 [1, 1]
2 [1, 1, 1]
函數的默認參數是一個list 當第一次執行的時候實例化了一個list
第二次執行還是用第一次執行的時候實例化的地址存儲
所以三次執行的結果就是 [1, 1, 1] 想每次執行只輸出[1] ,默認參數應該設置爲None
‘’’

複製代碼

42、如何實現 「1,2,3」 變成 [‘1’,’2’,’3’]

list("1,2,3".split(','))

43. 如何實現[‘1’,’2’,’3’]變成[1,2,3]

複製代碼
[int(x) for x in ['1','2','3']]

python 裏如何把[‘1’,‘2’,‘3’] 變成[1,2,3]

a = [‘1’,‘2’,‘3’]
b = [int(i) for i in a]
print(b)

[1, 2, 3]

複製代碼

44. a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的區別?

 補充:

 
 
複製代碼
a=[1,2,3,4,5],b=a和b=a[:],有區別麼?

a = [1,2,3,4,5]
b = a
b1 = a[:]
print(b) # [1, 2, 3, 4, 5]

print(b) # [1, 2, 3, 4, 5]

b.append(6) print("a",a) # a [1, 2, 3, 4, 5, 6] print("b",b) # b [1, 2, 3, 4, 5, 6] 傳遞引用 print("b1",b1) # b1 [1, 2, 3, 4, 5] 拷貝
複製代碼
# 一個列表A=[2,3,4],Python如何將其轉換成B=[(2,3),(3,4),(4,2)]?
# B = zip(A, A[1:]+A[:1])

45. 如何用一行代碼生成[1,4,9,16,25,36,49,64,81,100]

[i*i for i in range(1,11)]

46. 一行代碼實現刪除列表中重複的值

list(set([1, 2, 3, 4, 45, 1, 2, 343, 2, 2]))

47. 如何在函數中設置一個全局變量

python中的global語句是被用來聲明全局變量的。

複製代碼
x = 2
def func():
    global x
    x = 1
    return x
func()
print(x)  # 1
複製代碼

48. logging模塊的作用?以及應用場景?

複製代碼
logging 
模塊定義的函數和類爲應用程序和庫的開發實現了一個靈活的事件日誌系統

作用:可以瞭解程序運行情況,是否正常
    在程序的出現故障快速定位出錯地方及故障分析

複製代碼

49. 請用代碼簡答實現stack

  • Stack() 創建一個新的空棧
  • push(item) 添加一個新的元素item到棧頂
  • pop() 彈出棧頂元素
  • peek() 返回棧頂元素
  • is_empty() 判斷棧是否爲空
  • size() 返回棧的元素個數
複製代碼
# 實現一個棧stack,後進先出

‘’’
class Stack:
def init(self):
self.items = []

def is_empty(self):
    # 判斷是否爲空
    return self.items == []

def push(self,item):
    # 加入元素
    self.items.append(item)

def pop(self):
    # 彈出元素
    return self.items.pop()

def peek(self):
    # 返回棧頂元素
    return self.items[len(self.items)-1]

def size(self):
    # 返回棧的大小
    return len(self.items)

if name == 「main」:
stack = Stack()
stack.push(「H」)
stack.push(「E」)
stack.push(「L」)
print(stack.size()) # 3
print(stack.peek()) # L
print(stack.pop()) # L
print(stack.pop()) # E
print(stack.pop()) # H
‘’’

複製代碼

50. 常用字符串格式化哪幾種?

1.佔位符%

%d 表示那個位置是整數;%f 表示浮點數;%s 表示字符串。

print('Hello,%s' % 'Python')
print('Hello,%d%s%.2f' % (666, 'Python', 9.99)) # 打印:Hello,666Python10.00

2.format

print('{k} is {v}'.format(k='python', v='easy'))  # 通過關鍵字
print('{0} is {1}'.format('python', 'easy'))      # 通過關鍵字

51. 簡述 生成器、迭代器、可迭代對象 以及應用場景?

迭代器

含有__iter__和__next__方法 (包含__next__方法的可迭代對象就是迭代器)

生成器

:包括含有yield這個關鍵字,生成器也是迭代器,調動next把函數變成迭代器。

複製代碼
應用場景:
range/xrange - py2: range(1000000) ,會立即創建,xrange(1000000)生成器 - py3:range(10000000)生成器 

- redis獲取值
conn = Redis(...)

    def hscan_iter(self, name, match=None, count=None):
      """
      Make an iterator using the HSCAN command so that the client doesn't
      need to remember the cursor position.

      ``match`` allows for filtering the keys by pattern

      ``count`` allows for hint the minimum number of returns
      """
      cursor = '0'
      while cursor != 0:
        # 去redis中獲取數據:12
        # cursor,下一次取的位置
        # data:本地獲取的12條數數據
        cursor, data = self.hscan(name, cursor=cursor,match=match, count=count)
        for item in data.items():
          yield item

stark組件

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

 
複製代碼

可迭代對象

 一個類內部實現__iter__方法且返回一個迭代器。

複製代碼
應用場景: 
    - 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=<span>widgets.PasswordInput(),
            render_kw={'<span>class<span>': <span>'<span>form-control<span>'}
        )

    
    form =<span> LoginForm()
    for item <span>in form:
        print(item)
        
- 列表、字典、元組</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
複製代碼

裝飾器

複製代碼
 裝飾器:
能夠在不修改原函數代碼的基礎上,在執行前後進行定製操作,閉包函數的一種應用
場景:
   - flask路由系統 - flask before_request - csrf - django內置認證 - django緩存 # 手寫裝飾器; import functools def wrapper(func): @functools.wraps(func) #不改變原函數屬性 def inner(*args, **kwargs): 執行函數前 return func(*args, **kwargs) 執行函數後 return inner 1. 執行wapper函數,並將被裝飾的函數當做參數。 wapper(index) 2. 將第一步的返回值,重新賦值給 新index = wapper(老index) @wrapper #index=wrapper(index) def index(x): return x+100
複製代碼

調用裝飾器其實是一個閉包函數,爲其他函數添加附加功能,不修改被修改的源代碼和不修改被修飾的方式,裝飾器的返回值也是一個函數對象。
比如:插入日誌、性能測試、事物處理、緩存、權限驗證等,有了裝飾器,就可以抽離出大量與函數功能本身無關的雷同代碼並繼續重用。

 52. 用Python實現一個二分查找的函數。

二分查找算法:簡單的說,就是將一個列表先排序好,比如按照從小到大的順序排列好,當給定一個數據,比如3,查找3在列表中的位置時,可以先找到列表中間的數li[middle]和3進行比較,當它比3小時,那麼3一定是在列表的右邊,反之,則3在列表的左邊,比如它比3小,則下次就可以只比較[middle+1, end]的數,繼續使用二分法,將它一分爲二,直到找到3這個數返回或者列表全部遍歷完成(3不在列表中) 

優點:效率高,時間複雜度爲O(logN); 
缺點:數據要是有序的,順序存儲。

複製代碼
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def search(someone, li):
l = -1
h = len(li)

while l + 1 !=<span> h:
    m = int((l + h) / 2<span>)
    if li[m] &lt;<span> someone:
        l =<span> m
    else<span>:
        h =<span> m
p =<span> h
if p &gt;= len(li) or li[p] !=<span> someone:
    print("元素不存在"<span>)
else<span>:
    str = "元素索引爲%d" %<span> p
    print(str)

search(3, li) # 元素索引爲2

複製代碼

53. 談談你對閉包的理解?

複製代碼
ef foo():
    m=3 n=5 def bar(): a=4 return m+n+a return bar 

>>>bar = foo()
>>>bar()
12

複製代碼

說明:
bar在foo函數的代碼塊中定義。我們稱bar是foo的內部函數。
在bar的局部作用域中可以直接訪問foo局部作用域中定義的m、n變量。
簡單的說,這種內部函數可以使用外部函數變量的行爲,就叫閉包。

閉包的意義與應用

54. os和sys模塊的作用?

os模塊負責程序與操作系統的交互,提供了訪問操作系統底層的接口;
sys模塊負責程序與python解釋器的交互,提供了一系列的函數和變量,用於操控python的運行時環境。

複製代碼
os與sys模塊的官方解釋如下:
os: This module provides a portable way of using operating system dependent functionality. 這個模塊提供了一種方便的使用操作系統函數的方法。 sys: This module provides access to some variables used or maintained by the interpreter and to 
functions that interact strongly with the interpreter. 這個模塊可供訪問由解釋器使用或維護的變量和與解釋器進行交互的函數。 os 常用方法 os.remove() 刪除文件 os.rename() 重命名文件 os.walk() 生成目錄樹下的所有文件名 os.chdir() 改變目錄 os.mkdir/makedirs 創建目錄/多層目錄 os.rmdir/removedirs 刪除目錄/多層目錄 os.listdir() 列出指定目錄的文件 os.getcwd() 取得當前工作目錄 os.chmod() 改變目錄權限 os.path.basename() 去掉目錄路徑,返回文件名 os.path.dirname() 去掉文件名,返回目錄路徑 os.path.join() 將分離的各部分組合成一個路徑名 os.path.split() 返回( dirname(), basename())元組 os.path.splitext() 返回 (filename, extension) 元組 os.path.getatime\ctime\mtime 分別返回最近訪問、創建、修改時間 os.path.getsize() 返回文件大小 os.path.exists() 是否存在 os.path.isabs() 是否爲絕對路徑 os.path.isdir() 是否爲目錄 os.path.isfile() 是否爲文件 sys 常用方法 sys.argv 命令行參數List,第一個元素是程序本身路徑 sys.modules.keys() 返回所有已經導入的模塊列表 sys.exc_info() 獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback當前處理的異常詳細信息 sys.exit(n) 退出程序,正常退出時exit(0) sys.hexversion 獲取Python解釋程序的版本值,16進制格式如:0x020403F0 sys.version 獲取Python解釋程序的版本信息 sys.maxint 最大的Int值 sys.maxunicode 最大的Unicode值 sys.modules 返回系統導入的模塊字段,key是模塊名,value是模塊 sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 sys.platform 返回操作系統平臺名稱 sys.stdout 標準輸出 sys.stdin 標準輸入 sys.stderr 錯誤輸出 sys.exc_clear() 用來清除當前線程所出現的當前的或最近的錯誤信息 sys.exec_prefix 返回平臺獨立的python文件安裝的位置 sys.byteorder 本地字節規則的指示器,big-endian平臺的值是'big',little-endian平臺的值是'little' sys.copyright 記錄python版權相關的東西 sys.api_version 解釋器的C的API版本 總結: os模塊負責程序與操作系統的交互,提供了訪問操作系統底層的接口;
sys模塊負責程序與python解釋器的交互,提供了一系列的函數和變量,用於操控python的運行時環境。
複製代碼

55. 如何生成一個隨機數?

import random

print(random.random()) # 用於生成一個0到1的隨機符點數: 0 <= n < 1.0
print(random.randint(1, 1000)) # 用於生成一個指定範圍內的整數

56. 如何使用python刪除一個文件?

複製代碼
import os
file = r'D:\test.txt'
if os.path.exists(file): os.remove(file) print('delete success') else: print('no such file:%s' % file)
複製代碼

57. 談談你對面向對象的理解

三大特性以及解釋?

面對對象是一種編程思想,以類的眼光來來看待事物的一種方式。將有共同的屬性和方法的事物封裝到同一個類下面。

繼承:將多個類的共同屬性和方法封裝到一個父類下面,然後在用這些類來繼承這個類的屬性和方法

封裝:將有共同的屬性和方法封裝到同一個類下面

  • 第一層面:創建類和對象會分別創建二者的名稱空間,我們只能用類名.或者obj.的方式去訪問裏面的名字,這本身就是一種封裝
  • 第二層面:類中把某些屬性和方法隱藏起來(或者說定義成私有的),只在類的內部使用、外部無法訪問,或者留下少量接口(函數)供外部訪問。

多態:Python天生是支持多態的。指的是基類的同一個方法在不同的派生類中有着不同的功能

58. Python面向對象中的繼承有什麼特點

複製代碼
繼承概念的實現方式主要有2類:實現繼承、接口繼承。

實現繼承是指使用基類的屬性和方法而無需額外編碼的能力;
     接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力(子類重構爹類方法);

python 兩種類:經典類 新式類
python3 新式類 —— 都默認繼承object class Animal(object): == class Animal:
python2 經典類和新式類 並存
class Animal: 經典類 —— 繼承順序 個別使用方法
class Animal(object): 新式類

繼承分爲單繼承和多繼承
Python是支持多繼承的
如果沒有指定基類,python的類會默認繼承object類,object是所有python類的基類,它提供了一些常見方法(如__str__)的實現。

複製代碼

補充繼承的應用(面試題)

複製代碼
1、對象可以調用自己本類和父類的所有方法和屬性, 先調用自己的 自己沒有才調父類的。誰(對象)調用方法,方法中的self就指向誰

class Foo:
def init(self):
self.func()

def<span> func(self):
    print('Foo.func'<span>)

class Son(Foo):
def func(self):
print(‘Son.func’)

s = Son()

Son.func

========================================================
class A:
def get(self):
self.say()

def<span> say(self):
    print('AAAAA'<span>)

class B(A):
def say(self):
print(‘BBBBB’)

b = B()
b.get() #輸出結果爲:BBBBB

複製代碼

59. 面向對象深度優先和廣度優先是什麼?

Python的類可以繼承多個類,Python的類如果繼承了多個類,那麼其尋找方法的方式有兩種
當類是經典類時,多繼承情況下,會按照深度優先方式查找  py3
當類是新式類時,多繼承情況下,會按照廣度優先方式查找  py2
簡單點說就是:經典類是縱向查找,新式類是橫向查找
經典類和新式類的區別就是,在聲明類的時候,新式類需要加上object關鍵字。在python3中默認全是新式類

60. 面向對象中super的作用?

用於子類繼承基類的方法
複製代碼
class FooParent(object):
    def __init__(self): self.parent = 'I\'m the parent.' print('Parent') print('1111') 

def<span> bar(self, message):
    print("%s from Parent" %<span> message)

class FooChild(FooParent):
def init(self):
# super(FooChild,self) 首先找到 FooChild 的父類(就是類 FooParent),然後把類B的對象 FooChild 轉換爲類 FooParent 的對象
super(FooChild, self).init()
print(‘Child’)

# def bar(self, message):
#     # super(FooChild, self).bar(message)
#     print('Child bar fuction')
#     print(self.parent)

if name == ‘main:
fooChild = FooChild()
fooChild.bar(‘HelloWorld’)

複製代碼

61. 是否使用過functools中的函數?其作用是什麼?

用於修復裝飾器

複製代碼
import functools

def deco(func):
@functools.wraps(func) # 加在最內層函數正上方
def wrapper(*args, **kwargs):
return func(*args, **kwargs)

return<span> wrapper

@deco
def index():
‘’‘哈哈哈哈’’’
x = 10
print(‘from index’)

print(index.name)
print(index.doc)

加@functools.wraps

index

哈哈哈哈

不加@functools.wraps

wrapper

None

複製代碼

62. 列舉面向對象中帶雙下劃線的特殊方法,如:__new__、__init__

  • __new__:生成實例
  • __init__:生成實例的屬性
  • __call__:實例對象加( )會執行def __call__:... 方法裏邊的內容。

    __del__:析構方法,當對象在內存中被釋放時,自動觸發執行。如當 del obj 或者應用程序運行完畢時,執行該方法裏邊的內容。

    __enter__和__exit__:出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變量;with中代碼塊執行完畢時執行__exit__裏邊的內容。

    __module__:表示當前操作的對象在那個模塊   obj.__module__
    __class__ :表示當前操作的對象的類是什麼     obj.__class__

    __doc__:類的描述信息,該描述信息無法被繼承

    __str__:改變對象的字符串顯示 print函數 --->obj.__str__()
    __repr__:改變對象的字符串顯示 交互式解釋器 --->obj.__repr__()
    __format__:自定製格式化字符串

    __slots__:一個類變量 用來限制實例可以添加的屬性的數量和類型  

    __setitem__,__getitem,__delitem__:

複製代碼
class Foo:
    def __init__(self,name):
        self.name=name 

def __getitem__(self, item):
    print(self.__dict__[item])

def __setitem__(self, key, value):
    self.__dict__[key]=<span>value
def __delitem__(self, key):
    print('del obj[key]時,我執行'<span>)
    self.__dict__.pop(key)
def __delattr__(self, item):
    print('del obj.key時,我執行'<span>)
    self.__dict__.pop(item)

f1=Foo(‘sb’)
f1[‘age’]=18
f1[‘age1’]=19
del f1.age1
del f1[‘age’]
f1[‘name’]=‘alex’
print(f1.dict)

複製代碼

__get__():調用一個屬性時,觸發
__set__():爲一個屬性賦值時,觸發
__delete__():採用del刪除屬性時,觸發

__setattr__,__delattr__,__getattr__ :

63. 如何判斷是函數還是方法?

看他的調用者是誰,如果是類,就需要傳入一個參數self的值,這時他就是一個函數,

如果調用者是對象,就不需要給self傳入參數值,這時他就是一個方法

print(isinstance(obj.func, FunctionType))   # False

print(isinstance(obj.func, MethodType))    # True

複製代碼
class Foo(object):
    def __init__(self):
        self.name = 'lcg' 

def func(self):
    print(self.name)

obj = Foo()
print(obj.func) # <bound method Foo.func of <main.Foo object at 0x000001ABC0F15F98>>

print(Foo.func) # <function Foo.func at 0x000001ABC1F45BF8>

------------------------FunctionType, MethodType------------#

from types import FunctionType, MethodType

obj = Foo()
print(isinstance(obj.func, FunctionType)) # False
print(isinstance(obj.func, MethodType)) # True

print(isinstance(Foo.func, FunctionType)) # True
print(isinstance(Foo.func, MethodType)) # False

------------------------------------------------------------#

obj = Foo()
Foo.func(obj) # lcg

obj = Foo()
obj.func() # lcg

「」"
注意:
方法,無需傳入self參數
函數,必須手動傳入self參數
「」"

複製代碼

64. 靜態方法和類方法區別?

儘管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明顯的區別。classmethod 必須有一個指向類對象的引用作爲第一個參數,而 staticmethod 可以沒有任何參數。

舉個栗子:

複製代碼
class Num:
    # 普通方法:能用Num調用而不能用實例化對象調用   
    def one():  
        print ('1') 

# 實例方法:能用實例化對象調用而不能用Num調用
def two(self):
    print ('2'<span>)

# 靜態方法:能用Num和實例化對象調用
@staticmethod 
def three():  
    print ('3'<span>)

# 類方法:第一個參數cls長什麼樣不重要,都是指Num類本身,調用時將Num類作爲對象隱式地傳入方法   
@classmethod 
def go(cls): 
    cls.three()

Num.one() #1
#Num.two() #TypeError: two() missing 1 required positional argument: ‘self’
Num.three() #3
Num.go() #3

i=Num()
#i.one() #TypeError: one() takes 0 positional arguments but 1 was given
i.two() #2
i.three() #3
i.go() #3

複製代碼

65. 列舉面向對象中的特殊成員以及應用場景

複製代碼
__call__

new

init

doc

class

del

dict

str

在falsk源碼用到…

複製代碼

66. 1、2、3、4、5 能組成多少個互不相同且無重複的三位數

60個

題意理解:組成後的數值不相同,且組合的三個位數之間數字不重複。

使用python內置的排列組合函數(不放回抽樣排列)

product 笛卡爾積  (有放回抽樣排列)

permutations 排列  (不放回抽樣排列)

combinations 組合,沒有重複  (不放回抽樣組合)

combinations_with_replacement 組合,有重複  (有放回抽樣組合)

import itertools

print(len(list(itertools.permutations(‘12345’, 3)))) # 60

67. 什麼是反射?以及應⽤用場景?

反射的核心本質就是以字符串的形式去導入個模塊,利用字符串的形式去執行函數。

Django中的 CBV就是基於反射實現的。

68. metaclass作用?以及應用場景?

metaclass用來指定類是由誰創建的。

類的metaclass 默認是type。我們也可以指定類的metaclass值。在python3中:

複製代碼
class MyType(type):
    def __call__(self, *args, **kwargs): return 'MyType' 

class Foo(object, metaclass=MyType):
def init(self):
return ‘init’

def __new__(cls, *args, **<span>kwargs):
    return<span> cls.__init__(cls)

def __call__(self, *args, **<span>kwargs):
    return 'call'<span>

obj = Foo()
print(obj) # MyType

複製代碼

 

69. 用盡量多的方法實現單例模式。

複製代碼
1:使用模塊
Python的模塊就是天然的單例模式。
因爲模塊在第一次導入時,會生成 .pyc 文件,當第二次導入時,就會直接加載 .pyc 文件,而不會再次執行模塊代碼。
因此,我們只需把相關的函數和數據定義在一個模塊中,就可以獲得一個單例對象了。
例如:
class V1(object): def foo(self) pass V1 = V1() 將上面代碼保存在文件test.py,要使用時,直接在其他文件中導入此文件中的對象,這個對象既是單例模式的對象 

如:from a import V1

2:使用裝飾器
def Singleton(cls):
_instance = {}
def _singleton(*args, **kargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kargs)
return _instance[cls]
return _singleton
@Singleton
class A(object):
a = 1
def init(self, x=0):
self.x = x
a1 = A(2)
a2 = A(3)

3:使用類

4:基於__new__方法實現
當我們實例化一個對象時,是先執行了類的__new__方法
當:(我們沒寫時,默認調用object.new),實例化對象;然後再執行類的__init__方法,對這個對象進行初始化,所有我們可以基於這個,實現單例模式

複製代碼

70. 裝飾器器的寫法以及應用場景。

含義:裝飾器本質就是函數,爲其他函數添加附加功能

原則:

不修改被修飾函數的代碼

不修改被修飾函數的調用方式

應用場景:

無參裝飾器在用戶登錄 認證中常見

有參裝飾器在flask的路由系統中見到過

複製代碼
import functools
def wrapper(func): @functools.wraps(func) def inner(*args, **kwargs): print('我是裝飾器') return func return inner 

@wrapper
def index():
print(‘我是被裝飾函數’)
return None
index()

應用場景

-<span> 高階函數
-<span> 閉包
-<span> 裝飾器 
- functools.wraps(func)</span></span></span></span></span></span></span></span></span></span></span></span></pre>
複製代碼

71. 異常處理寫法以及如何主動跑出異常(應用場景)

複製代碼
# 觸發異常
def temp_convert(var):
    try: return int(var) except ValueError as Argument: print ("參數沒有包含數字%s"%Argument) 

調用函數

temp_convert(「xyz」)

以10爲基數的int()的無效文字:「xyz」


----------------------------------------------------------------------------

raise語法

#raise [Exception [, args [, traceback]]]

語句中 Exception 是異常的類型,args 是自已提供的異常參數。

class Networkerror(RuntimeError):
def init(self, arg):
self.args = arg
try:
raise Networkerror(「Bad hostname」)
except Networkerror as e:
print(e.args)

複製代碼

72、什麼是面向對象的mro

mro就是方法解析順序

73. isinstance作用以及應用場景?

isinstance(對象,類)  判斷這個對象是不是這個類或者這個類的子類的實例化

複製代碼
# # 判斷a 屬不屬於A這個類(可以判斷到祖宗類)
class A:
    pass

class B(A):
pass
a = A()
b = B()
print(isinstance(b,A)) # ===> True 判斷到祖宗類

任何與object都是True,內部都繼承object

class A:pass
a = A() # 實例化
print(isinstance(a,object)) # True

複製代碼

應用場景:rest framework 認證的流程

scrapy-redis

74. 寫代碼並實現

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]

75. json序列化時,可以處理的數據類型有哪些?如何定製支持datetime類型?


76. json序列化時,默認遇到中文會轉換成unicode,如果想要保留中文怎麼辦?

 在序列化時,中文漢字總是被轉換爲unicode碼,在dumps函數中添加參數ensure_ascii=False即可解決。

77. 什麼是斷言?應用場景?

複製代碼
assert 是的作用?斷言
條件成立(布爾值爲True)則繼續往下,否則跑出異常,一般用於:滿足某個條件之後,才能執行,否則應該跑出異常。

寫API的時候,繼承GenericAPIView

class GenericAPIView(views.APIView):
「」"
Base class for all other generic views.
「」"
# You’ll need to either set these attributes,
# or override get_queryset()/get_serializer_class().
# If you are overriding a view method, it is important that you call
# get_queryset() instead of accessing the queryset property directly,
# as queryset will get evaluated only once, and those results are cached
# for all subsequent requests.
queryset = None
serializer_class = None

# If you want to use object lookups other than pk, set 'lookup_field'.
                # For more complex lookup requirements override `get_object()`.
                lookup_field = 'pk'<span>
                lookup_url_kwarg =<span> None

                # The filter backend classes to use for queryset filtering
                filter_backends =<span> api_settings.DEFAULT_FILTER_BACKENDS

                # The style to use for queryset pagination.
                pagination_class =<span> api_settings.DEFAULT_PAGINATION_CLASS

                def<span> get_queryset(self):

                    assert self.queryset is not<span> None, (
                        "'%s' should either include a `queryset` attribute, "
                        "or override the `get_queryset()` method."
                        % self.__class__.__name__<span>
                    )

                    queryset =<span> self.queryset
                    if<span> isinstance(queryset, QuerySet):
                        # Ensure queryset is re-evaluated on each request.
                        queryset =<span> queryset.all()
                    return queryset</span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
複製代碼

78. 有用過with statement嗎?它的好處是什麼?


79. 使用代碼實現查看列舉目錄下的所有文件。


80. 簡述 yield和yield from關鍵字

第二部分 網絡編程和併發

81. 簡述 OSI 七層協議。

 

物理層:主要是基於電器特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0

數據鏈路層:定義了電信號的分組方式

網路層:引入一套新的地址用來區分不同的廣播域/子網,這套地址即網絡地址

傳輸層:建立端口到端口的通信

會話層:建立客戶端與服務端連接

表示層:對來自應用層的命令和數據進行解釋,按照一定格式傳給會話層。如編碼、數據格式轉換、加密解密、壓縮解壓
應用層:規定應用程序的數據格式

82. 什麼是C/S和B/S架構?

c/s架構,就是client(客戶端)與server(服務端)即:客戶端與服務端的架構。

b/s架構,就是brosver(瀏覽器端)與sever(服務端)即:瀏覽器端與服務端架構

優點:統一了所有應用程序的入口、方便、輕量級

83. 簡述 三次握手、四次揮手的流程。

複製代碼
三次握手:
    第一次握手
1:客戶端先向服務端發起一次詢問建立連接的請求,並隨機生成一個值作爲標識 第二次握手 2:服務端向客戶端先回應第一個標識,再重新發一個確認標識 第三次握手 3:客戶端確認標識,建立連接,開始傳輸數據 
複製代碼
複製代碼
四次揮手 ---> 斷開連接
第一次揮手
    客戶端向服務端發起請求斷開連接的請求
第二次揮手
    服務端向客戶端確認請求
第三次揮手
    服務端向客戶端發起斷開連接請求
第四次揮手
    客戶端向服務端確認斷開請求
複製代碼

84. TCP和UDP的區別?

TCP/UDP區別
 TCP協議是面向連接,保證高可靠性傳輸層協議
 UDP:數據丟失,無秩序的傳輸層協議(qq基於udp協議)

85. 爲何基於tcp協議的通信比基於udp協議的通信更可靠?

tcp:可靠,因爲只要對方回了確認收到信息,才發下一個,如果沒收到確認信息就重發
UDP:不可靠,它是一直髮數據,不需要對方迴應
流式協議: TCP協議,可靠傳輸
數據報協議: UDP協議,不可傳輸

86. 什麼是socket?簡述基於tcp協議的套接字通信流程。

複製代碼
Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。
在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,
對用戶來說,一組簡單的接口就是全部。

服務端:
創建socket對象,
綁定ip端口bind(),
設置最大鏈接數listen(),
accept()與客戶端的connect()創建雙向管道,等到聯接,
send(), recv(), 收發數據
close()

客戶端:
創建socket對象,
connect()與服務端accept()創建雙向管道 ,
send(),
recv(),
close()

複製代碼

87. 什麼是粘包? socket 中造成粘包的原因是什什麼? 哪些情況會發生粘包現象?

複製代碼
只有TCP有粘包現象,UDP永遠不會粘包
粘包
:在獲取數據時,出現數據的內容不是本應該接收的數據,如:對方第一次發送hello,第二次發送world,
  我方接收時,應該收兩次,一次是hello,一次是world,但事實上是一次收到helloworld,一次收到空,這種現象叫粘包

原因
粘包問題主要還是因爲接收方不知道消息之間的界限,不知道一次性提取多少字節的數據所造成的。

什麼情況會發生
1、發送端需要等緩衝區滿才發送出去,造成粘包(發送數據時間間隔很短,數據了很小,會合到一起,產生粘包)

2、接收方不及時接收緩衝區的包,造成多個包接收(客戶端發送了一段數據,服務端只收了一小部分,
服務端下次再收的時候還是從緩衝區拿上次遺留的數據,產生粘包)

複製代碼

88. IO多路復的作用?

socketserver,多個客戶端連接,單線程下實現併發效果,就叫多路複用。

與多進程和多線程技術相比,I/O多路複用技術的最大優勢是系統開銷小,系統不必創建進程/線程,也不必維護這些進程/線程,從而大大減小了系統的開銷。

89.select、poll、epoll 模型的區別?(屬於多路複用IO的模型)

複製代碼
都是i/o多路複用的機制,監視多個socket是否發生變化,本質上都是同步i/o
    select,poll實現需要自己不斷輪詢所有監測對象,直到對象發生變化,在這個階段中,
可能要睡眠和喚醒多次交替,而epoll也需要調用epoll_wait不斷輪詢就緒鏈表,但是當對象發生變化時,
會調用回調函數,將變化的對象放入就緒鏈接表中,並喚醒在epoll_wait中進入睡眠的進程。
雖然都會睡眠和喚醒,但是select和poll在被喚醒的時候要遍歷整個監測對象集合,
而epoll只要判斷就緒鏈表是否爲空即可,節省了大量cpu的時間
複製代碼
複製代碼
 select、poll、epoll都是IO多路複用的機制,但select,poll,epoll本質上都是同步I/O,
 因爲他們都需要在讀寫事件就緒後自己負責進行讀寫,也就是說這個讀寫過程是阻塞的.

FD(文件描述符)
select模型
優點:
1:可移植性好,在某些Unix系統不支持poll()
2:對於超時值提供了更好的精度:微妙,而poll是毫秒
缺點:
1:最大併發數限制,因爲一個進程所打開的 FD (文件描述符)是有限制的,由 FD_SETSIZE 設置,默認值是 1024/2048 ,因此 Select 模型的最大併發數就被相應限制了。
2:效率問題,select每次調用都會線性掃描全部的FD集合,所以將FD_SETSIZE 改大,會越慢
3:需要維護一個用來存放大量fd的數據結構,這樣會使得用戶空間和內核空間在傳遞該結構時複製開銷大。

poll本質上和select 沒有區別,它將用戶傳入的數組拷貝到內核空間,
它沒有最大連接數的限制,原因是它基於鏈表來存儲的但是同樣有一個缺點:
大量的fd的數組被整體複製於用戶態和內核地址空間,而不管這樣的複製是不是有意義

複製代碼

90. 什麼是防火牆以及作用?

複製代碼
防火牆是一個分離器、一個限制器,也是一個分析器,有效地監控了內部網和Internet之間的任何活動,保證了內部網絡的安全

作用
防火牆是網絡安全的屏障
可以強化網絡安全策略
對網絡存取和訪問進行監控審計
防止內部信息的外泄
除了安全作用,防火牆還支持具有Internet服務特性的企業內部網絡技術體系v*n(虛擬專用網)。

複製代碼

91. 簡述 進程、線程、協程的區別 以及應用場景?

複製代碼
線程是指進程內的一個執行單元,
# 進程
進程擁有自己獨立的堆和棧,既不共享堆,亦不共享棧,進程由操作系統調度。 # 線程 線程擁有自己獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操作系統調度 # 協程和線程 協程避免了無意義的調度,由此可以提高性能;但同時協程也失去了線程使用多CPU的能力 

進程與線程的區別
(1)地址空間:線程是進程內的一個執行單位,進程內至少有一個線程,他們共享進程的地址空間,而進程有自己獨立的地址空間
(2)資源擁有:進程是資源分配和擁有的單位,同一個進程內線程共享進程的資源
(3)線程是處理器調度的基本單位,但進程不是
(4)二者均可併發執行
(5)每個獨立的線程有一個程序運行的入口

協程與線程
(1)一個線程可以有多個協程,一個進程也可以單獨擁有多個協程,這樣Python中則能使用多核CPU
(2)線程進程都是同步機制,而協程是異步
(3)協程能保留上一次調用時的狀態

複製代碼

92. GIL鎖是什麼?

GIL本質就是一把互斥鎖,既然是互斥鎖,所有互斥鎖的本質都一樣,都是將併發運行變成串行,以此來控制同一時間內共享數據只能被一個任務所修改,進而保證數據安全。

GIL保護的是解釋器級的數據,保護用戶自己的數據則需要自己加鎖處理

複製代碼
應用(總結):
多線程用於IO密集型,如socket,爬蟲,web
多進程用於計算密集型,如金融分析
  1. 每個cpython進程內都有一個GIL 2. GIL導致同一進程內多個進程同一時間只能有一個運行 3. 之所以有GIL,是因爲Cpython的內存管理不是線程安全的 4. 對於計算密集型用多進程,多IO密集型用多線程
複製代碼

93. Python中如何使用線程池和進程池?


94. threading.local的作用?

實現線程局部變量的傳遞。

ThreadLocal 最常用的地方:
爲每個線程綁定一個資源(數據庫連接,HTTP請求,用戶身份信息等),這樣一個線程的所有調用到的處理函數都可以非常方便地訪問這些資源。

95. 進程之間如何進行通信?


96. 什麼是併發和並行?

# 併發:同一時刻只能處理一個任務,但一個時段內可以對多個任務進行交替處理(一個處理器同時處理多個任務)
# 並行:同一時刻可以處理多個任務(多個處理器或者是多核的處理器同時處理多個不同的任務)
# 類比:併發是一個人同時吃三個饅頭,而並行是三個人同時吃三個饅頭。 

97. 進程鎖和線程鎖的作用?


98. 解釋什麼是異步非阻塞?

複製代碼
非阻塞:不等待
即:遇到IO阻塞不等待(setblooking=False),(可能會報錯->捕捉異常) - sk=socket.socket() - sk.setblooking(False) 異步:回調,當達到某個指定的狀態之後,自動調用特定函數 

實例
nb_async.py 實現異步非阻塞的模塊

複製代碼
異步體現在回調上,回調就是有消息返回時告知一聲兒進程進行處理。非阻塞就是不等待,不需要進程等待下去,繼續執行其他操作,不管其他進程的狀態。

99. 路由器和交換機的區別

複製代碼
1:交換機:是負責內網裏面的數據傳遞(arp協議)根據MAC地址尋址
   路由器:在網絡層,路由器根據路由表,尋找該ip的網段
2:路由器可以處理TCP/IP協議 3:路由器可以把一個IP分配給很多個主機使用,這些主機對外只表現出一個IP。 交換機可以把很多主機連起來,這些主機對外各有各的IP。 4:交換機是做端口擴展的,也就是讓局域網可以連進來更多的電腦。 路由器是用來做網絡連接,也就是;連接不同的網絡
複製代碼

100.什麼是域名解析?

在互聯網上,所有的地址都是ip地址,現階段主要是IPv4(比如:110.110.110.110)。
但是這些ip地址太難記了,所以就出現了域名(比如http://baidu.com)。 域名解析就是將域名,轉換爲ip地址的這樣一種行爲。

101.如何修改本地hosts件?

複製代碼
Hosts是一個沒有擴展名的系統文件,可以用記事本等工具打開,其作用就是將一些常用的網址域名與其對應的IP地址建立一個關聯「數據庫」,
當用戶在瀏覽器中輸入一個需要登錄的網址時,系統會首先自動從Hosts文件中尋找對應的IP地址,
一旦找到,系統會立即打開對應網頁,如果沒有找到,則系統會再將網址提交DNS域名解析服務器進行IP地址的解析。

瀏覽器訪問網站,要首先通過DNS服務器把要訪問的網站域名解析成一個唯一的IP地址,之後,瀏覽器才能對此網站進行定位並且訪問其數據。

文件路徑:C:\WINDOWS\system32\drivers\etc。
將127.0.0.1 www.163.com 添加在最下面
修改後用瀏覽器訪問「www.163.com」會被解析到127.0.0.1,導致無法顯示該網頁。

複製代碼

102.生產者消費者模型應用場景及優勢?

複製代碼
生產者與消費者模式是通過一個容器來解決生產者與消費者的強耦合關係,生產者與消費者之間不直接進行通訊,
而是利用阻塞隊列來進行通訊,生產者生成數據後直接丟給阻塞隊列,消費者需要數據則從阻塞隊列獲取,
實際應用中,生產者與消費者模式則主要解決生產者與消費者生產與消費的速率不一致的問題,達到平衡生產者與消費者的處理能力,而阻塞隊列則相當於緩衝區。

應用場景:用戶提交訂單,訂單進入引擎的阻塞隊列中,由專門的線程從阻塞隊列中獲取數據並處理

優勢:
1;解耦
假設生產者和消費者分別是兩個類。如果讓生產者直接調用消費者的某個方法,那麼生產者對於消費者就會產生依賴(也就是耦合)。
將來如果消費者的代碼發生變化,可能會影響到生產者。而如果兩者都依賴於某個緩衝區,兩者之間不直接依賴,耦合也就相應降低了。
2:支持併發
生產者直接調用消費者的某個方法,還有另一個弊端。由於函數調用是同步的(或者叫阻塞的),在消費者的方法沒有返回之前,生產者只能一直等着
而使用這個模型,生產者把製造出來的數據只需要放在緩衝區即可,不需要等待消費者來取

3:支持忙閒不均
緩衝區還有另一個好處。如果製造數據的速度時快時慢,緩衝區的好處就體現出來了。
當數據製造快的時候,消費者來不及處理,未處理的數據可以暫時存在緩衝區中。等生產者的製造速度慢下來,消費者再慢慢處理掉。

複製代碼

103.什麼是cdn?

目的是使用戶可以就近到服務器取得所需內容,解決 Internet網絡擁擠的狀況,提高用戶訪問網站的響應速度。

cdn 即內容分發網絡

104.LVS是什麼及作用?

複製代碼
LVS :Linux虛擬服務器
作用:LVS主要用於多服務器的負載均衡。
它工作在網絡層,可以實現高性能,高可用的服務器集羣技術。
它廉價,可把許多低性能的服務器組合在一起形成一個超級服務器。
它易用,配置非常簡單,且有多種負載均衡的方法。
它穩定可靠,即使在集羣的服務器中某臺服務器無法正常工作,也不影響整體效果。另外可擴展性也非常好。
複製代碼

105.Nginx是什麼及作用?


106.keepalived是什麼及作用?


107.haproxy是什麼以及作用?


108.什麼是負載均衡?


109.什麼是rpc及應用場景?


110.簡述 asynio模塊的作用和應用場景。


111.簡述 gevent模塊的作用和應用場景。


112.twisted框架的使用和應用

數據庫和緩存(46題)

113.列舉常見的關係型數據庫和非關係型都有那些?

複製代碼
關係型數據庫(需要有表結構)
    mysql、oracle 、 spl、server、db2、sybase

非關係型數據庫(是以key-value存儲的,沒有表結構)(NoSQL)
MongoDB
MongoDB 是一個高性能,開源,無模式的文檔型數據庫,開發語言是C++。它在許多場景下可用於替代傳統的關係型數據庫或鍵/值存儲方式。
Redis
Redis 是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。目前由VMware主持開發工作。

複製代碼

114.MySQL常見數據庫引擎及比較?

複製代碼
InnoDB 
支持事務
支持表鎖、行鎖(for update) 表鎖:select * from tb for update 行鎖:select id,name from tb where id=2 for update 

myisam
查詢速度快
全文索引
支持表鎖
表鎖:select * from tb for update

NDB
高可用、 高性能、高可擴展性的數據庫集羣系統

Memory
默認使用的是哈希索引

複製代碼

115.簡述數據庫三大範式?

複製代碼
 數據庫的三大特性:
'實體':表 '屬性':表中的數據(字段) '關係':表與表之間的關係 ---------------------------------------------------- # 數據庫設計三大範式: 1:確保每列保持原子性(即數據庫表中的所有字段值是不可分解的原子值) 

2:確保表中的每列都是和主鍵相關(表中只能保存一種數據,不可以把多種數據保存在同一張表中)—>完全屬於當前表的數據

3:確保每列都和主鍵直接相關,而不是間接相關(在一個數據庫表中保存的數據只能與主鍵相關)----> 消除傳遞依賴(間接)
比如在設計一個訂單數據表的時候,可以將客戶編號作爲一個外鍵和訂單表建立相應的關係。
而不可以在訂單表中添加關於客戶其它信息(比如姓名、所屬公司等)的字段。

複製代碼
複製代碼
數據庫五大約束'
    1.primary KEY:設置主鍵約束;
    2.UNIQUE:設置唯一性約束,不能有重複值; 3.DEFAULT 默認值約束 4.NOT NULL:設置非空約束,該字段不能爲空; 5.FOREIGN key :設置外鍵約束。
複製代碼

116、什麼是事務?MySQL如何支持事務?

複製代碼
事務用於將某些操作的多個SQL作爲原子性操作,一旦有某一個出現錯誤,即可回滾到原來的狀態,從而保證數據庫數據完整性。

事務的特性:
原子性: 確保工作單元內的所有操作都成功完成,否則事務將被中止在故障點,和以前的操作將回滾到以前的狀態。
一致性: 確保數據庫正確地改變狀態後,成功提交的事務。
隔離性: 使事務操作彼此獨立的和透明的。
持久性: 確保提交的事務的結果或效果的系統出現故障的情況下仍然存在。

Mysql實現事務
InnoDB支持事務,MyISAM不支持
# 啓動事務:
# start transaction;
# update from account set money=money-100 where name=‘a’;
# update from account set money=money+100 where name=‘b’;
# commit;
‘start transaction 手動開啓事務,commit 手動關閉事務’

複製代碼

117.簡述數據庫設計中一對多和多對多的應用場景?

FK(一對多)
下拉框裏面的數據就需要用FK關聯另一張表

M2M(多對多)
多選的下拉框,或者checkbox

118.如何基於數據庫實現商城商品計數器?

119.常見SQL(必備)

複製代碼
group by 分組對聚合的條件進行篩選需要通過havhing

SQL的left join 、right join、inner join之間的區別
left join (左連接) 返回包括左表中的所有記錄和右表中聯結字段相等的記錄
right join(右連接) 返回包括右表中的所有記錄1和左表中聯結字段相等的記錄
inner join(內連接): 只返回兩個表中聯結字段相等的行

複製代碼

https://www.cnblogs.com/wupeiqi/articles/5729934.html

120.簡述觸發器、函數、視圖、存儲過程?

複製代碼
觸發器:
對數據庫某張表的增加、刪除,修改前後定義一些操作

函數:(觸發函數是通過select)
聚合函數:max/sum/min/avg
時間格式化:date_format
字符串拼接:concat

存儲過程:
將SQL語句保存到數據庫中,並命名,以後在代碼調用時,直接調用名稱即可
參數類型:
  in 只將參數傳進去
  out 只拿結果
  inout 既可以傳,可以取

函數與存儲過程區別:
本質上沒區別。只是函數有如:只能返回一個變量的限制。而存儲過程可以返回多個。而函數是可以嵌入在sql中使用的,可以在select中調用,而存儲過程不行。

視圖:
視圖是一個虛擬表,不是真實存在的(只能查,不能改)

複製代碼

121.MySQL索引種類

複製代碼
單列
功能
   普通索引:加速查找
   唯一索引:加速查找 + 約束:不能重複(只能有一個空,不然就重複了) 主鍵(primay key):加速查找 + 約束:不能重複 + 不能爲空 多列   聯合索引(多個列創建索引)-----> 相當於單列的普通索引   聯合唯一索引 -----> 相當於單列的唯一索引   ps:聯合索引的特點:遵循最左前綴的規則 其他詞語: ·· - 索引合併,利用多個單例索引查詢;(例如在數據庫查用戶名和密碼,分別給用戶名和密碼建立索引) - 覆蓋索引,在索引表中就能將想要的數據查詢到;
複製代碼

122.索引在什麼情況下遵循最左前綴的規則?

聯合索引

123.主鍵和外鍵的區別?

主鍵是能確定一條記錄的唯一標示。例如,身份證證號

外鍵:用於與另一張表的關聯,是能確定另一張表記錄的字段,用於保持數據的一致性

  主鍵 外鍵
定義 唯一標識一條記錄,不能有重複的,不允許爲空 表的外鍵是另一張表的主鍵,外鍵可以有重複的,可以爲空
作用 用來保證數據完整性 用來與其他表建立聯繫的
個數 主鍵只能有一個 一個表可以有多個外鍵

 

 

 

 

 

124.MySQL常見的函數?

複製代碼
聚合函數
max/sum/min/avg 

時間格式化
date_format

字符串拼接
concat(當拼接了null,則返回null)

截取字符串
substring

返回字節個數
length

複製代碼

125.列舉 創建索引但是無法命中索引的8種情況。

複製代碼
1.- like '%xx'
    select * from tb1 where name like '%cn'; 2.- 使用函數 select * from tb1 where reverse(name) = 'wupeiqi'; 3.- or select * from tb1 where nid = 1 or email = '[email protected]'; 特別的:當or條件中有未建立索引的列才失效,以下會走索引 select * from tb1 where nid = 1 or name = 'seven'; select * from tb1 where nid = 1 or email = '[email protected]' and name = 'alex' 4.- 類型不一致 如果列是字符串類型,傳入條件是必須用引號引起來,不然... select * from tb1 where name = 999; 5.- != select * from tb1 where name != 'alex' 特別的:如果是主鍵,則還是會走索引 select * from tb1 where nid != 123 6.- > select * from tb1 where name > 'alex' 特別的:如果是主鍵或索引是整數類型,則還是會走索引 select * from tb1 where nid > 123 select * from tb1 where num > 123 7.- order by select email from tb1 order by name desc; 當根據索引排序時候,選擇的映射如果不是索引,則不走索引 特別的:如果對主鍵排序,則還是走索引: select * from tb1 order by nid desc; 

8.- 組合索引最左前綴
如果組合索引爲:(name,email)
name and email – 使用索引
name – 使用索引
email – 不使用索引

複製代碼

126.如何開啓慢日誌查詢?

複製代碼
修改配置文件
slow_query_log = OFF 是否開啓慢日誌記錄 long_query_time = 2 時間限制,超過此時間,則記錄 slow_query_log_file = /usr/slow.log 日誌文件 log_queries_not_using_indexes = OFF 爲使用索引的搜索是否記錄 

下面是開啓
slow_query_log = ON
long_query_time = 2
log_queries_not_using_indexes = OFF
log_queries_not_using_indexes = ON

注:查看當前配置信息:
   show variables like ‘%query%’
修改當前配置:
    set global 變量名 = 值

複製代碼

127.數據庫導入導出命令(結構+數據)?

複製代碼
導出現有數據庫數據:(當有提示出入密碼。-p就不用加密碼)
  mysqldump -u用戶名 -p密碼 數據庫名稱 >導出文件路徑           # 結構+數據
  mysqldump -u用戶名 -p密碼 -d 數據庫名稱 >導出文件    路徑       # 結構 
 導入現有數據庫數據: mysqldump -uroot -p密碼 數據庫名稱 < 文件路徑 
複製代碼

128.數據庫優化方案?

複製代碼
1、創建數據表時把固定長度的放在前面()
2、將固定數據放入內存: 例如:choice字段 (django中有用到,數字1、2、3…… 對應相應內容) 3、char 和 varchar 的區別(char可變, varchar不可變 )    4、聯合索引遵循最左前綴(從最左側開始檢索) 5、避免使用 select * 6、讀寫分離     - 實現:兩臺服務器同步數據     - 利用數據庫的主從分離:主,用於刪除、修改、更新;從,用於查; 讀寫分離:利用數據庫的主從進行分離:主,用於刪除、修改更新;從,用於查 7、分庫     - 當數據庫中的表太多,將某些表分到不同的數據庫,例如:1W張表時     - 代價:連表查詢 8、分表     - 水平分表:將某些列拆分到另外一張表,例如:博客+博客詳情     - 垂直分表:講些歷史信息分到另外一張表中,例如:支付寶賬單 

9、加緩存
    - 利用redis、memcache (常用數據放到緩存裏,提高取數據速度)

如果只想獲取一條數據
- select * from tb where name=‘alex’ limit 1

複製代碼

129.char和varchar的區別?

char 和 varchar 的區別(char可變, varchar不可變 )

130.簡述MySQL的執行計劃?

查看有沒有命中索引,讓數據庫幫看看運行速度快不快
explain select * from table;

當type爲all時,是爲全表索引

131.在對name做了唯一索引前提下,簡述以下區別:     

    select * from tb where name = ‘Oldboy-Wupeiqi’  
        select * from tb where name = ‘Oldboy-Wupeiqi’ limit 1

複製代碼
是這樣的的,用where條件過濾出符合條件的數據的同時,進行計數,
比如limit 1,那麼在where過濾出第1條數據後,他就會直接把結果select出來返回給你,整個過程就結束了。

沒做唯一索引的話,前者查詢會全表掃描,效率低些
limit 1,只要找到對應一條數據,就不繼續往下掃描.

然而 name 字段添加唯一索引了,加不加limit 1,意義都不大;

複製代碼

132.1000w條數據,使用limit offset 分頁時,爲什麼越往後翻越慢?如何解決?

複製代碼
  答案一:
      先查主鍵,在分頁。
      select * from tb where id in (
          select id from tb where limit 10 offset 30
      )
  答案二:
      按照也無需求是否可以設置只讓用戶看200頁

答案三:
記錄當前頁 數據ID最大值和最小值
在翻頁時,根據條件先進行篩選;篩選完畢之後,再根據limit offset 查詢。

select * from (select * from tb where id &gt; 22222222) as B limit 10 offset 0
  
  如果用戶自己修改頁碼,也可能導致慢;此時對url種的頁碼進行加密(rest framework )</span></pre>
複製代碼

133.什麼是索引合併?

複製代碼
1、索引合併是把幾個索引的範圍掃描合併成一個索引。
2、索引合併的時候,會對索引進行並集,交集或者先交集再並集操作,以便合併成一個索引。
3、這些需要合併的索引只能是一個表的。不能對多表進行索引合併。

簡單的說,索引合併,讓一條sql可以使用多個索引。對這些索引取交集,並集,或者先取交集再取並集。
從而減少從數據表中取數據的次數,提高查詢效率。

複製代碼

134.什麼是覆蓋索引?

在索引表中就能將想要的數據查詢到

135.簡述數據庫讀寫分離?

- 實現:兩臺服務器同步數據
    - 利用數據庫的主從分離:主,用於刪除、修改、更新;從,用於查;
複製代碼
方式一:是視圖裏面用using方式可以進行指定到哪個數據讀寫
from django.shortcuts import render,HttpResponse
from app01 import models
def index(request):

models.UserType.objects.using('db1').create(title='普通用戶')

# 手動指定去某個數據庫取數據
result = models.UserType.objects.all().using(‘db1’)
print(result)

return HttpResponse('...')

方式二:寫配置文件
class Router1:
  # 指定到某個數據庫取數據
def db_for_read(self, model, **hints):
「」"
Attempts to read auth models go to auth_db.
「」"
if model._meta.model_name == ‘usertype’:
return ‘db1’
else:
return ‘default’
   # 指定到某個數據庫存數據
def db_for_write(self, model, **hints):
「」"
Attempts to write auth models go to auth_db.
「」"
return ‘default’
再寫到配置
DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.sqlite3’,
‘NAME’: os.path.join(BASE_DIR, ‘db.sqlite3’),
},
‘db1’: {
‘ENGINE’: ‘django.db.backends.sqlite3’,
‘NAME’: os.path.join(BASE_DIR, ‘db.sqlite3’),
}
}
DATABASE_ROUTERS = [‘db_router.Router1’,]

複製代碼

136.簡述數據庫分庫分表?(水平、垂直)

複製代碼
 1、分庫
    當數據庫中的表太多,將某些表分到不同數據庫,例如:1W張表時
    代價:連表查詢跨數據庫,代碼變多
# 2、分表
    水平分表:將某些列拆分到另一張表,例如:博客+博客詳情 垂直分表:將某些歷史信息,分到另外一張表中,例如:支付寶賬單
複製代碼

137.redis和memcached比較?

複製代碼
區別
1:redis不僅支持簡單的key_value類型,還支持字典,字符串,列表,集合,有序集合類型
2:內存使用效率對比,使用簡單的key-value存儲的話,
Memcached的內存利用率更高而如果Redis採用hash結構來做key-value存儲,由於其組合式的壓縮,其內存利用率會高於Memcached。 3.性能對比:由於Redis只使用單核,而Memcached可以使用多核,.
所以平均每一個核上Redis在存儲小數據時比Memcached性能更高。而在100k以上的數據中,Memcached性能要高於Redis, 4.Redis雖然是基於內存的存儲系統,但是它本身是支持內存數據的持久化的,而且提供兩種主要的持久化策略:RDB快照和AOF日誌。
而memcached是不支持數據持久化操作的。 5.集羣管理不同,Memcached本身並不支持分佈式,因此只能在客戶端通過像一致性哈希這樣的分佈式算法來實現Memcached的分佈式存儲。
複製代碼

138.redis中數據庫默認是多少個db 及作用?

Redis默認支持16個數據庫,可以通過配置databases來修改這一數字。客戶端與Redis建立連接後會自動選擇0號數據庫,不過可以隨時使用SELECT命令更換數據庫

Redis支持多個數據庫,並且每個數據庫的數據是隔離的不能共享,並且基於單機纔有,如果是集羣就沒有數據庫的概念。

139.python操作redis的模塊?

複製代碼
- 連接
- 直接連接:
    import redis 
    r = redis.Redis(host='10.211.55.4', port=6379)
    r.set('foo', 'Bar')
    print r.get('foo')
- 連接池:
    import redis
    pool = redis.ConnectionPool(host='10.211.55.4', port=6379)

r = redis.Redis(connection_pool=pool)
r.set('foo', 'Bar')
print r.get('foo')</span></pre>
複製代碼

140.如果redis中的某個列表中的數據量非常大,如果實現循環顯示每一個值?

複製代碼
    - 如果一個列表在redis中保存了10w個值,我需要將所有值全部循環並顯示,請問如何實現?
       一個一個取值,列表沒有iter方法,但能自定義
     def list_scan_iter(name,count=3):
            start = 0
            while True:
                result = conn.lrange(name, start, start+count-1)
                start += count
                if not result:
                    break
                for item in result:
                    yield item

for val in list_scan_iter('num_list'):
        print(val)

場景:投票系統,script-redis

複製代碼

141.redis如何實現主從複製?以及數據同步機制?

複製代碼
優勢:
    - 高可用
    - 分擔主壓力
注意: 
    - slave設置只讀

從的配置文件添加以下記錄,即可:
slaveof 1.1.1.1 3306

複製代碼

142.redis中的sentinel的作用?

複製代碼
   幫助我們自動在主從之間進行切換
    檢測主從中 主是否掛掉,且超過一半的sentinel檢測到掛了之後才進行進行切換。
    如果主修復好了,再次啓動時候,會變成從。

啓動主redis:
redis-server /etc/redis-6379.conf  啓動主redis
redis-server /etc/redis-6380.conf  啓動從redis
    
在linux中:
    找到 /etc/redis-sentinel-8001.conf  配置文件,在內部:
        - 哨兵的端口 port = 8001
        - 主redis的IP,哨兵個數的一半/1
    
    找到 /etc/redis-sentinel-8002.conf  配置文件,在內部:
        - 哨兵的端口 port = 8002
        - 主redis的IP, 1 

    啓動兩個哨兵   </span></pre>
複製代碼

143.如何實現redis集羣?

複製代碼
 redis集羣、分片、分佈式redis     
    redis-py-cluster
    集羣方案:
        - redis cluster 官方提供的集羣方案。
        - codis,豌豆莢技術團隊。
        - tweproxy,Twiter技術團隊。
    redis cluster的原理?
        - 基於分片來完成。
        - redis將所有能放置數據的地方創建了 16384 個哈希槽。
        - 如果設置集羣的話,就可以爲每個實例分配哈希槽:
            - 192.168.1.20【0-5000】
            - 192.168.1.21【5001-10000】
            - 192.168.1.22【10001-16384】
        - 以後想要在redis中寫值時,
            set k1 123 
將k1通過crc16的算法,將k1轉換成一個數字。然後再將該數字和16384求餘,如果得到的餘數 3000,那麼就將該值寫入到 192.168.1.20 實例中。
複製代碼

144.redis中默認有多少個哈希槽?

16384

145.簡述redis的有哪幾種持久化策略及比較?

複製代碼
RDB:每隔一段時間對redis進行一次持久化。
      - 缺點:數據不完整
      - 優點:速度快
AOF:把所有命令保存起來,如果想到重新生成到redis,那麼就要把命令重新執行一次。
      - 缺點:速度慢,文件比較大
      - 優點:數據完整
複製代碼

146.列舉redis支持的過期策略。

複製代碼
  voltile-lru:    從已設置過期時間的數據集(server.db[i].expires)中挑選最近頻率最少數據淘汰
  volatile-ttl:   從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
  volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰

allkeys-lru: 從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random: 從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據

複製代碼

147.MySQL 裏有 2000w 數據,redis 中只存 20w 的數據,如何保證 redis 中都是熱點數據? 

複製代碼
  相關知識:redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略(回收策略)。redis 提供 6種數據淘汰策略:

volatile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據

複製代碼

148.寫代碼,基於redis的列表實現 先進先出、後進先出隊列、優先級隊列。

複製代碼
 參看script—redis源碼
from scrapy.utils.reqser import request_to_dict, request_from_dict

from . import picklecompat

class Base(object):
「」「Per-spider base queue class」""

def __init__(self, server, spider, key, serializer=None):
      """Initialize per-spider redis queue.

      Parameters
      ----------
      server : StrictRedis
          Redis client instance.
      spider : Spider
          Scrapy spider instance.
      key: str
          Redis key where to put and get messages.
      serializer : object
          Serializer object with ``loads`` and ``dumps`` methods.

      """
      if serializer is None:
          # Backward compatibility.
          # TODO: deprecate pickle.
          serializer = picklecompat
      if not hasattr(serializer, 'loads'):
          raise TypeError("serializer does not implement 'loads' function: %r"
                          % serializer)
      if not hasattr(serializer, 'dumps'):
          raise TypeError("serializer '%s' does not implement 'dumps' function: %r"
                          % serializer)

      self.server = server
      self.spider = spider
      self.key = key % {'spider': spider.name}
      self.serializer = serializer

  def _encode_request(self, request):
      """Encode a request object"""
      obj = request_to_dict(request, self.spider)
      return self.serializer.dumps(obj)

  def _decode_request(self, encoded_request):
      """Decode an request previously encoded"""
      obj = self.serializer.loads(encoded_request)
      return request_from_dict(obj, self.spider)

  def __len__(self):
      """Return the length of the queue"""
      raise NotImplementedError

  def push(self, request):
      """Push a request"""
      raise NotImplementedError

  def pop(self, timeout=0):
      """Pop a request"""
      raise NotImplementedError

  def clear(self):
      """Clear queue/stack"""
      self.server.delete(self.key)

class FifoQueue(Base):
「」「Per-spider FIFO queue」""

def __len__(self):
      """Return the length of the queue"""
      return self.server.llen(self.key)

  def push(self, request):
      """Push a request"""
      self.server.lpush(self.key, self._encode_request(request))

  def pop(self, timeout=0):
      """Pop a request"""
      if timeout &gt; 0:
          data = self.server.brpop(self.key, timeout)
          if isinstance(data, tuple):
              data = data[1]
      else:
          data = self.server.rpop(self.key)
      if data:
          return self._decode_request(data)

class PriorityQueue(Base):
「」「Per-spider priority queue abstraction using redis’ sorted set」""

def __len__(self):
      """Return the length of the queue"""
      return self.server.zcard(self.key)

  def push(self, request):
      """Push a request"""
      data = self._encode_request(request)
      score = -request.priority
      # We don't use zadd method as the order of arguments change depending on
      # whether the class is Redis or StrictRedis, and the option of using
      # kwargs only accepts strings, not bytes.
      self.server.execute_command('ZADD', self.key, score, data)

  def pop(self, timeout=0):
      """
      Pop a request
      timeout not support in this queue class
      """
      # use atomic range/remove using multi/exec
      pipe = self.server.pipeline()
      pipe.multi()
      pipe.zrange(self.key, 0, 0).zremrangebyrank(self.key, 0, 0)
      results, count = pipe.execute()
      if results:
          return self._decode_request(results[0])

class LifoQueue(Base):
「」「Per-spider LIFO queue.」""

def __len__(self):
      """Return the length of the stack"""
      return self.server.llen(self.key)

  def push(self, request):
      """Push a request"""
      self.server.lpush(self.key, self._encode_request(request))

  def pop(self, timeout=0):
      """Pop a request"""
      if timeout &gt; 0:
          data = self.server.blpop(self.key, timeout)
          if isinstance(data, tuple):
              data = data[1]
      else:
          data = self.server.lpop(self.key)

      if data:
          return self._decode_request(data)

TODO: Deprecate the use of these names.

SpiderQueue = FifoQueue
SpiderStack = LifoQueue
SpiderPriorityQueue = PriorityQueue

複製代碼

149.如何基於redis實現消息隊列?

複製代碼
# 通過發佈訂閱模式的PUB、SUB實現消息隊列
# 發佈者發佈消息到頻道了,頻道就是一個消息隊列。
# 發佈者:
import redis
conn = redis.Redis(host='127.0.0.1',port=6379) conn.publish('104.9MH', "hahahahahaha") # 訂閱者: import redis conn = redis.Redis(host='127.0.0.1',port=6379) pub = conn.pubsub() pub.subscribe('104.9MH') while True: msg= pub.parse_response() print(msg) 對了,redis 做消息隊列不合適 業務上避免過度複用一個redis,用它做緩存、做計算,還做任務隊列,壓力太大,不好。
複製代碼

150.如何基於redis實現發佈和訂閱?以及發佈訂閱和消息隊列的區別?

複製代碼
   發佈和訂閱,只要有任務就給所有訂閱者沒人一份
發佈者: import redis

conn = redis.Redis(host='127.0.0.1',port=6379)
  conn.publish('104.9MH', "hahaha")

訂閱者:
import redis

conn = redis.Redis(host='127.0.0.1',port=6379)
  pub = conn.pubsub()
  pub.subscribe('104.9MH')

  while True:
      msg= pub.parse_response()
      print(msg)</span></pre>
複製代碼

151.什麼是codis及作用?

 Codis 是一個分佈式 Redis 解決方案, 對於上層的應用來說, 連接到 Codis Proxy 和連接原生的 Redis Server 沒有明顯的區別 
(不支持的命令列表), 上層應用可以像使用單機的 Redis 一樣使用, Codis 底層會處理請求的轉發, 不停機的數據遷移等工作,
所有後邊的一切事情, 對於前面的客戶端來說是透明的, 可以簡單的認爲後邊連接的是一個內存無限大的 Redis 服務.

152.什麼是twemproxy及作用?

  是 Twtter 開源的一個 Redis 和 Memcache 代理服務器,主要用於管理 Redis 和 Memcached 集羣,
減少與Cache 服務器直接連接的數量。

153.寫代碼實現redis事務操作。

複製代碼
  import redis

pool = redis.ConnectionPool(host=‘10.211.55.4’, port=6379)

conn = redis.Redis(connection_pool=pool)

pipe = r.pipeline(transaction=False)

pipe = conn.pipeline(transaction=True)

開始事務

pipe.multi()

pipe.set(‘name’, ‘bendere’)
pipe.set(‘role’, ‘sb’)

提交

pipe.execute()

注意:諮詢是否當前分佈式redis是否支持事務

複製代碼

154.redis中的watch的命令的作用?

複製代碼
  在Redis的事務中,WATCH命令可用於提供CAS(check-and-set)功能。
假設我們通過WATCH命令在事務執行之前監控了多個Keys,倘若在WATCH之後有任何Key的值發生了變化,
EXEC命令執行的事務都將被放棄,同時返回Null multi-bulk應答以通知調用者事務執行失敗。

面試題:你如何控制剩餘的數量不會出問題?
方式一:- 通過redis的watch實現
import redis
conn = redis.Redis(host=‘127.0.0.1’,port=6379)

# conn.set('count',1000)
      val = conn.get('count')
      print(val)

      with conn.pipeline(transaction=True) as pipe:

          # 先監視,自己的值沒有被修改過
          conn.watch('count')

          # 事務開始
          pipe.multi()
          old_count = conn.get('count')
          count = int(old_count)
          print('現在剩餘的商品有:%s',count)
          input("問媳婦讓不讓買?")
          pipe.set('count', count - 1)

          # 執行,把所有命令一次性推送過去
          pipe.execute()
 方式二 - 數據庫的鎖 </span></pre>
複製代碼

155.基於redis如何實現商城商品數量計數器?

複製代碼
import redis

conn = redis.Redis(host=‘192.168.1.41’,port=6379)

conn.set(‘count’,1000)

with conn.pipeline() as pipe:

# 先監視,自己的值沒有被修改過
conn.watch('count')

# 事務開始
pipe.multi()
old_count = conn.get('count')
count = int(old_count)
if count &gt; 0:  # 有庫存
    pipe.set('count', count - 1)

# 執行,把所有命令一次性推送過去
pipe.execute()</span></pre>
複製代碼

156.簡述redis分佈式鎖和redlock的實現機制。

複製代碼
在不同進程需要互斥地訪問共享資源時,分佈式鎖是一種非常有用的技術手段。 
有很多三方庫和文章描述如何用Redis實現一個分佈式鎖管理器,但是這些庫實現的方式差別很大
,而且很多簡單的實現其實只需採用稍微增加一點複雜的設計就可以獲得更好的可靠性。
用Redis實現分佈式鎖管理器的算法,我們把這個算法稱爲RedLock。

實現

  • 寫值並設置超時時間
  • 超過一半的redis實例設置成功,就表示加鎖完成。
  • 使用:安裝redlock-py
    from redlock import Redlock

dlm = Redlock(
[
{「host」: 「localhost」, 「port」: 6379, 「db」: 0},
{「host」: 「localhost」, 「port」: 6379, 「db」: 0},
{「host」: 「localhost」, 「port」: 6379, 「db」: 0},
]
)

加鎖,acquire

my_lock = dlm.lock(「my_resource_name」,10000)
if my_lock:
# J進行操作
# 解鎖,release
dlm.unlock(my_lock)
else:
print(‘獲取鎖失敗’)

複製代碼
複製代碼
 redis分佈式鎖?
# 不是單機操作,又多了一/多臺機器
# redis內部是單進程、單線程,是數據安全的(只有自己的線程在操作數據)
---------------------------------------------------------------- \A、B、C,三個實例(主) 1、來了一個'隔壁老王'要操作,且不想讓別人操作,so,加鎖; 加鎖:'隔壁老王'自己生成一個隨機字符串,設置到A、B、C裏(xxx=666) 2、來了一個'鄰居老李'要操作A、B、C,一讀發現裏面有字符串,擦,被加鎖了,不能操作了,等着吧~ 3、'隔壁老王'解決完問題,不用鎖了,把A、B、C裏的key:'xxx'刪掉;完成解鎖 4、'鄰居老李'現在可以訪問,可以加鎖了 # 問題: 1、如果'隔壁老王'加鎖後突然掛了,就沒人解鎖,就死鎖了,其他人幹看着沒法用咋辦? 2、如果'隔壁老王'去給A、B、C加鎖的過程中,剛加到A,'鄰居老李'就去操作C了,加鎖成功or失敗? 3、如果'隔壁老王'去給A、B、C加鎖時,C突然掛了,這次加鎖是成功還是失敗? 4、如果'隔壁老王'去給A、B、C加鎖時,超時時間爲5秒,加一個鎖耗時3秒,此次加鎖能成功嗎? # 解決 1、安全起見,讓'隔壁老王'加鎖時設置超時時間,超時的話就會自動解鎖(刪除key:'xxx') 2、加鎖程度達到(1/2)+1個就表示加鎖成功,即使沒有給全部實例加鎖; 3、加鎖程度達到(1/2)+1個就表示加鎖成功,即使沒有給全部實例加鎖; 4、不能成功,鎖還沒加完就過期,沒有意義了,應該合理設置過期時間 # 注意 使用需要安裝redlock-py ---------------------------------------------------------------- from redlock import Redlock dlm = Redlock(     [         {"host": "localhost", "port": 6379, "db": 0},        nbsp; {"host": "localhost", "port": 6379, "db": 0},         {"host": "localhost", "port": 6379, "db": 0},     ] ) # 加鎖,acquire my_lock = dlm.lock("my_resource_name",10000) if my_lock:     # 進行操作     # 解鎖,release     dlm.unlock(my_lock) else:     print('獲取鎖失敗') \通過sever.eval(self.unlock_script)執行一個lua腳本,用來刪除加鎖時的key
複製代碼

157.什麼是一致性哈希?Python中是否有相應模塊?

 一致性哈希
一致性hash算法(DHT)可以通過減少影響範圍的方式,解決增減服務器導致的數據散列問題,從而解決了分佈式環境下負載均衡問題;
如果存在熱點數據,可以通過增添節點的方式,對熱點區間進行劃分,將壓力分配至其他服務器,重新達到負載均衡的狀態。
Python模塊--hash_ring,即Python中的一致性hash

158.如何高效的找到redis中所有以aaa開頭的key?

複製代碼
redis 有一個keys命令。
# 語法:KEYS pattern
# 說明:返回與指定模式相匹配的所用的keys。
該命令所支持的匹配模式如下: 1、?:用於匹配單個字符。例如,h?llo可以匹配hello、hallo和hxllo等; 2、*:用於匹配零個或者多個字符。例如,h*llo可以匹配hllo和heeeello等; 2、[]:可以用來指定模式的選擇區間。例如h[ae]llo可以匹配hello和hallo,但是不能匹配hillo。同時,可以使用「/」符號來轉義特殊的字符 # 注意 KEYS 的速度非常快,但如果數據太大,內存可能會崩掉, 如果需要從一個數據集中查找特定的key,最好還是用Redis的集合結構(set)來代替。
複製代碼

第四部分 前端、框架和其他(155題)

1.談談你對http協議的認識。

複製代碼
  瀏覽器本質,socket客戶端遵循Http協議
  HTTP協議本質:通過\r\n分割的規範+ 請求響應之後斷開鏈接   ==  >  無狀態、 短連接
具體:
  Http協議是建立在tcp之上的,是一種規範,它規範定了發送的數據的數據格式,
然而這個數據格式是通過\r\n 進行分割的,請求頭與請求體也是通過2個\r\n分割的,響應的時候,
響應頭與響應體也是通過\r\n分割,並且還規定已請求已響應就會斷開鏈接   
即--->  短連接、無狀態
複製代碼

2.談談你對websocket協議的認識。

複製代碼
websocket是給瀏覽器新建的一套(類似與http)協議,協議規定:(\r\n分割)瀏覽器和服務器連接之後不斷開,
    以此完成:服務端向客戶端主動推送消息。

websocket協議額外做的一些操作
握手 ----> 連接錢進行校驗
加密 ----> payload_len=127/126/<=125 --> mask key

複製代碼
本質
創建一個連接後不斷開的socket
當連接成功之後:
    客戶端(瀏覽器)會自動向服務端發送消息,包含: Sec-WebSocket-Key: iyRe1KMHi4S4QXzcoboMmw==
    服務端接收之後,會對於該數據進行加密:base64(sha1(swk + magic_string))
    構造響應頭:
            HTTP/1.1 101 Switching Protocols\r\n
            Upgrade:websocket\r\n
            Connection: Upgrade\r\n
            Sec-WebSocket-Accept: 加密後的值\r\n
            WebSocket-Location: ws://127.0.0.1:8002\r\n\r\n        
    發給客戶端(瀏覽器)
建立:雙工通道,接下來就可以進行收發數據
    發送數據是加密,解密,根據payload_len的值進行處理
        payload_len <= 125
        payload_len == 126
        payload_len == 127
    獲取內容:
        mask_key
        數據
        根據mask_key和數據進行位運算,就可以把值解析出來。
複製代碼
複製代碼

 3.什麼是magic string ?

 客戶端向服務端發送消息時,會有一個'sec-websocket-key'和'magic string'的隨機字符串(魔法字符串)
# 服務端接收到消息後會把他們連接成一個新的key串,進行編碼、加密,確保信息的安全性

4.如何創建響應式佈局?

複製代碼
響應式佈局是通過@media實現的
@media (min-width:768px){
     .pg-header{
           background-color:green;
      }      
}
@media   (min-width:992px){
     .pg-header{
            background-color:pink;
     }
}    

代碼
<!DOCTYPE html>
<html lang=「en」>
<head>
<meta charset=「UTF-8」>
<meta http-equiv=「X-UA-Compatible」 content=「IE=edge」>
<meta name=「viewport」 content=「width=device-width, initial-scale=1」>
<title>Title</title>
<style>
body{
margin: 0;
}
.pg-header{
background-color: red;
height: 48px;
}

@media (min-width: 768px) <span>{
        .pg-header{
            background-color<span>: aqua<span>;
        <span>}
    }
    @media (min-width: 992px) <span>{
        .pg-header{
            background-color<span>: blueviolet<span>;
        <span>}
    }
&lt;/style&gt;

</head>
<body>
<div class=「pg-header」></div>
</body>
</html>

複製代碼

5.你曾經使用過哪些前端框架?

jQuery
- BootStrap
- Vue.js(與vue齊名的前端框架React和Angular)

6.什麼是ajax請求?並使用jQuery和XMLHttpRequest對象實現一個ajax請求。

基於原生AJAX - Demo
基於jQueryAjax - Demo

http://www.cnblogs.com/wupeiqi/articles/5703697.html

7.如何在前端實現輪訓?

複製代碼
 輪詢:通過定時器讓程序每隔n秒執行一次操作。

複製代碼
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <h1>請選出最帥的男人</h1>
    <ul>
        {% for k,v in gg.items() %}
            <li>ID:{{ k }}, 姓名:{{ v.name }} ,票數:{{ v.count }}</li> {% endfor %} </ul> 

&lt;script&gt;<span>
    setInterval(function<span> () {
        location.reload();
    },<span>2000<span>)
&lt;/script&gt;

</body>
</html>

複製代碼
複製代碼

8.如何在前端實現長輪訓?

複製代碼
客戶端向服務器發送請求,服務器接到請求後hang住連接,等待30秒,30s過後再重新發起請求,
直到有新消息才返回響應信息並關閉連接,客戶端處理完響應信息後再向服務器發送新的請求。

複製代碼
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <h1>請選出最帥的男人</h1>
    <ul>
        {% for k,v in gg.items() %}
            <li style="cursor: pointer" id="user_{{ k }}" "vote({{ k }});">ID:{{ k }}, 姓名:{{ v.name }} ,票數:<span>{{ v.count }}</span></li> {% endfor %} </ul> 

&lt;script src="/static/jquery-3.3.1.min.js"&gt;&lt;/script&gt;
&lt;script&gt;<span>
    $(function<span> () {
        get_new_count();
    });
    
    function<span> get_new_count() {
        $.ajax({
            url: <span>'<span>/get_new_count<span>'<span>,
            type:<span>'<span>GET<span>'<span>,
            dataType:<span>'<span>JSON<span>'<span>,
            success:function<span> (arg) {
                if<span> (arg.status){
                    // 更新票數
                    var<span> gid <span>= <span>"<span>#user_<span>" <span>+<span> arg.data.gid;
                    $(gid).find(<span>'<span>span<span>'<span>).text(arg.data.count);
                }else<span>{
                    // 10s內沒有人投票

}
get_new_count();

}
        })
    }

    function<span> vote(gid) {
        $.ajax({
            url: <span>'<span>/vote<span>'<span>,
            type:<span>'<span>POST<span>'<span>,
            data:{gid:gid},
            dataType:<span>"<span>JSON<span>"<span>,
            success:function<span> (arg) {

            }
        })
    }
&lt;/script&gt;

</body>
</html>

複製代碼
複製代碼

9.vuex的作用?

複製代碼
多組件之間共享:vuex

補充luffyvue
1:router-link / router-view
2:雙向綁定,用戶綁定v-model
3:循環展示課程:v-for
4:路由系統,添加動態參數
5:cookie操作:vue-cookies
6:多組件之間共享:vuex
7:發送ajax請求:axios (js模塊)

複製代碼

10.vue中的路由的攔截器的作用?

 vue-resource的interceptors攔截器的作用正是解決此需求的妙方。
在每次http的請求響應之後,如果設置了攔截器如下,會優先執行攔截器函數,獲取響應體,然後纔會決定是否把response返回給then進行接收

11.axios的作用?

發送ajax請求:axios (js模塊)

12.列舉vue的常見指令。

複製代碼
 1、v-if指令:判斷指令,根據表達式值得真假來插入或刪除相應的值。
  2、v-show指令:條件渲染指令,無論返回的布爾值是true還是false,元素都會存在在html中,只是false的元素會隱藏在html中,並不會刪除.
  3、v-else指令:配合v-if或v-else使用。
  4、v-for指令:循環指令,相當於遍歷。
  5、v-bind:給DOM綁定元素屬性。
  6、v-on指令:監聽DOM事件。
複製代碼

13.簡述jsonp及實現原理?

JSONP
jsonp是json用來跨域的一個東西。原理是通過script標籤的跨域特性來繞過同源策略。
JSONP的簡單實現模式,或者說是JSONP的原型:創建一個回調函數,然後在遠程服務上調用這個函數並且將JSON 數據形式作爲參數傳遞,
完成回調。 

14.什麼是cors ?

複製代碼
CORS
瀏覽器將CORS請求分成兩類:簡單請求和賦複雜請求

簡單請求(同時滿足以下兩大條件)
(1)請求方法是以下三種方法之一:
HEAD
GET
POST
(2)HTTP的頭信息不超出以下幾種字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type :只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不同時滿足上面兩個條件,就屬於非簡單請求

複製代碼

15.列舉Http請求中常見的請求方式?

複製代碼
GET、POST、
PUT、patch(修改數據) HEAD(類似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭) DELETE

傳值代碼f
Request.QueryString方法針對控件id
Request.Form方法針對控件名稱name
複製代碼

16.列舉Http請求中的狀態碼?

複製代碼
分類:
1**  信息,服務器收到請求,需要請求者繼續執行操作
2**  成功,操作被成功接收並處理
3** 重定向,需要進一步的操作以完成請求
4** 客戶端錯誤,請求包含語法錯誤或無法完成請求
5** 服務器錯誤,服務器在處理請求的過程中發生了錯誤

常見的狀態碼
200 -請求成功
202 -已接受請求,尚未處理
204 -請求成功,且不需返回內容
301 - 資源(網頁等)被永久轉移到其他url
400 - 請求的語義或是參數有錯
403 - 服務器拒絕請求
404 - 請求資源(網頁)不存在

500 - 內部服務器錯誤
502 - 網關錯誤,一般是服務器壓力過大導致連接超時
503 - 由於超載或系統維護,服務器暫時的無法處理客戶端的請求。

複製代碼

17.列舉Http請求中常見的請求頭?

- user-agent
- host
- referer
- cookie 
- content-type 

18.看圖寫結果(js):

 李傑

看圖寫結果(js):

 武沛奇

看圖寫結果:(js)

 老男孩

看圖寫結果:(js)


 undefined

看圖寫結果:(js)

  武沛奇

看圖寫結果:(js)

 Alex

19.django、flask、tornado框架的比較?

複製代碼
對於django,大而全的框架它的內部組件比較多,內部提供:ORM、Admin、中間件、Form、ModelForm、Session、
緩存、信號、CSRF;功能也都挺完善的
  • flask,微型框架,內部組件就比較少了,但是有很多第三方組件來擴展它,
      比如說有那個wtform(與django的modelform類似,表單驗證)、flask-sqlalchemy(操作數據庫的)、
      flask-session、flask-migrate、flask-script、blinker可擴展強,第三方組件豐富。所以對他本身來說有那種短小精悍的感覺
  • tornado,異步非阻塞。

django和flask的共同點就是,他們2個框架都沒有寫socket,所以他們都是利用第三方模塊wsgi。
但是內部使用的wsgi也是有些不同的:django本身運行起來使用wsgiref,而flask使用werkzeug wsgi

還有一個區別就是他們的請求管理不太一樣:django是通過將請求封裝成request對象,再通過參數傳遞,而flask是通過上下文管理機制

Tornado

# 是一個輕量級的Web框架,異步非阻塞+內置WebSocket功能。

'目標':通過一個線程處理N個併發請求(處理IO)。

'內部組件

    #內部自己實現socket

    #路由系統

    #視圖

  #模板

   #cookie

    #csrf

複製代碼

20.什麼是wsgi?

複製代碼
是web服務網關接口,是一套協議。
是通過以下模塊實現了wsgi協議:
    - wsgiref
    - werkzurg
    - uwsgi   關於部署
以上模塊本質:編寫socket服務端,用於監聽請求,當有請求到來,則將請求數據進行封裝,然後交給web框架處理。
複製代碼

21.django請求的生命週期?

用戶請求進來先走到  wsgi   然後將請求交給  jango的中間件   穿過django中間件(方法是process_request)  
接着就是 路由匹配 路由匹配成功之後就執行相應的 視圖函數
在視圖函數中可以調用orm做數據庫操作 再從模板路徑 將模板拿到 然後在後臺進行模板渲染
模板渲染完成之後就變成一個字符串 再把這個字符串經過所有中間件(方法:process_response) 和wsgi 返回給用戶

22.列舉django的內置組件?

複製代碼
form 組件
- 對用戶請求的數據進行校驗
- 生成HTML標籤

PS:

  • form對象是一個可迭代對象。

  • 問題:choice的數據如果從數據庫獲取可能會造成數據無法實時更新
    - 重寫構造方法,在構造方法中重新去數據庫獲取值。
    - ModelChoiceField字段
    from django.forms import Form
    from django.forms import fields
    from django.forms.models import ModelChoiceField
    class UserForm(Form):
    name = fields.CharField(label=‘用戶名’,max_length=32)
    email = fields.EmailField(label=‘郵箱’)
    ut_id = ModelChoiceField(queryset=models.UserType.objects.all())

    依賴:
              class UserType(models.Model):
                  title = models.CharField(max_length=32)
    
                  def __str__(self):
                      return self.title</span></pre>
複製代碼
複製代碼
信號、
django的信號其實就是django內部爲開發者預留的一些自定製功能的鉤子。
只要在某個信號中註冊了函數,那麼django內部執行的過程中就會自動觸發註冊在信號中的函數。
如: 
pre_init # django的modal執行其構造方法前,自動觸發
post_init # django的modal執行其構造方法後,自動觸發
pre_save # django的modal對象保存前,自動觸發
post_save # django的modal對象保存後,自動觸發
場景:
在數據庫某些表中添加數據時,可以進行日誌記錄。

CSRF、
目標:防止用戶直接向服務端發起POST請求。
對所有的post請求做驗證/ 將jango生成的一串字符串發送給我們,一種是從請求體發過來,一種是放在隱藏的標籤裏面用的是process_view 

方案:先發送GET請求時,將token保存到:cookie、Form表單中(隱藏的input標籤),
以後再發送請求時只要攜帶過來即可。


ContentType
contenttype是django的一個組件(app),
爲我們找到django程序中所有app中的所有表並添加到記錄中。
可以使用他再加上表中的兩個字段實現:一張表和N張表創建FK關係。 - 字段:表名稱 - 字段:數據行ID
應用:路飛表結構優惠券和專題課和學位課關聯。
複製代碼
中間件
對所有的請求進行批量處理,在視圖函數執行前後進行自定義操作。
應用:用戶登錄校驗
問題:爲甚麼不使用裝飾器?
如果不使用中間件,就需要給每個視圖函數添加裝飾器,太繁瑣
權限組件:
用戶登錄後,將權限放到session中,然後再每次請求進來在中間件裏,根據當前的url去session中匹配,
判斷當前用戶是否有權限訪問當前url,有權限就繼續訪問,沒有就返回, (檢查的東西就可以放到中間件中進行統一處理)在process_request方法裏面做的,  我們的中間件是放在session後面,因爲中間件需要到session裏面取數據
複製代碼
session
cookie與session區別
(a)cookie是保存在瀏覽器端的鍵值對,而session是保存的服務器端的鍵值對,但是依賴cookie。
(也可以不依賴cookie,可以放在url,或請求頭但是cookie比較方便) (b)以登錄爲例,cookie爲通過登錄成功後,設置明文的鍵值對,並將鍵值對發送客戶端存,明文信息可能存在泄漏,不安全;
  session則是生成隨機字符串,發給用戶,並寫到瀏覽器的cookie中,同時服務器自己也會保存一份。 (c)在登錄驗證時,cookie:根據瀏覽器發送請求時附帶的cookie的鍵值對進行判斷,如果存在,則驗證通過;
  session:在請求用戶的cookie中獲取隨機字符串,根據隨機字符串在session中獲取其對應的值進行驗證
複製代碼
cors跨域(場景:前後端分離時,本地測試開發時使用)
如果網站之間存在跨域,域名不同,端口不同會導致出現跨域,但凡出現跨域,瀏覽器就會出現同源策略的限制
解決:在我們的服務端給我們響應數據,加上響應頭---> 在中間件加的
複製代碼
 
  
緩存/   
常用的數據放在緩存裏面,就不用走視圖函數,請求進來通過所有的process_request,會到緩存裏面查數據,有就直接拿,
        沒有就走視圖函數
      關鍵點:1:執行完所有的process_request纔去緩存取數據
          2:執行完所有的process_response纔將數據放到緩存

關於緩存問題
1:爲什麼放在最後一個process_request纔去緩存 因爲需要驗證完用戶的請求,才能返回數據

2:什麼時候將數據放到緩存中
第一次走中間件,緩存沒有數據,會走視圖函數,取數據庫裏面取數據,
當走完process_response,纔將數據放到緩存裏,因爲,走process_response的時候可能給我們的響應加處理

複製代碼
爲什麼使用緩存
將常用且不太頻繁修改的數據放入緩存。
以後用戶再來訪問,先去緩存查看是否存在,如果有就返回
否則,去數據庫中獲取並返回給用戶(再加入到緩存,以便下次訪問)

23.列舉django中間件的5個方法?以及django中間件的應用場景?

process_request(self,request)  先走request 通過路由匹配返回
process_view(self, request, callback, callback_args, callback_kwargs) 再返回執行view
process_template_response(self,request,response)   當視圖函數的返回值
process_exception(self, request, exception)  當視圖函數的返回值對象中有render方法時,該方法纔會被調用
process_response(self, request, response)

執行流程

24.簡述什麼是FBV和CBV?

複製代碼
FBV 基於函數
# FBV 寫法
# urls.py
 url(r'^login/$',views.login, name="login"),

views.py

def login(request):
if request.method == 「POST」:
print(request.POST)

return render(request,"login.html")

HTML

<!DOCTYPE html>
<html lang=「en」>
<head>
<meta charset=「UTF-8」>
<meta http-equiv=「X-UA-Compatible」 content=「IE=edge」>
<meta name=「viewport」 content=「width=device-width, initial-scale=1」>
<title>登錄頁面</title>
</head>
<body>
<form action="{% url ‘login’ %}" method=「post」 enctype=「multipart/form-data」>
<input type=「text」 name=「user2」>
<input type=「file」 name=「file」>
<input type=「submit」 value=「提交」>

</form>
</body>
</html>

CBV 基於類

urls.py

url(r’^login/$’,views.Login.as_view(), name=「login」),

views.py

from django.views import View
class Login(View): # 類首字母大寫
def get(self,request):
return render(request,「login.html」)
def post(self,request):
print(request.POST)
return HttpResponse(「OK」)

加裝飾器

=================================
class IndexView(View):

# 如果是crsf相關,必須放在此處
def dispach(self,request):
    # 通過反射執行post/get 

@method_decoretor(裝飾器函數)
def get(self,request):
    pass
    
def post(self,request):
    pass

路由:IndexView.as_view()

複製代碼

25.FBV與CBV的區別

- 沒什麼區別,因爲他們的本質都是函數。CBV的.as_view()返回的view函數,view函數中調用類的dispatch方法,
在dispatch方法中通過反射執行get/post/delete/put等方法。D

非要說區別的話:

  • CBV比較簡潔,GET/POST等業務功能分別放在不同get/post函數中。FBV自己做判斷進行區分。

26.django的request對象是在什麼時候創建的?

當請求一個頁面時, Django會建立一個包含請求元數據的 HttpRequest 對象. 
當Django 加載對應的視圖時, HttpRequest對象將作爲視圖函數的第一個參數.
每個視圖會返回一個HttpResponse對象.

27.如何給CBV的程序添加裝飾器?

複製代碼
添加裝飾器
方式一:
from django.views import View
from django.utils.decorators import method_decorator  ---> 需要引入memethod_decorator

def auth(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner

class UserView(View):
@method_decorator(auth)
def get(self,request,*args,**kwargs):
return HttpResponse(’…’)

方式二:

  • csrf的裝飾器要加到dispath前面
    from django.views import View
    from django.utils.decorators import method_decorator
    from django.views.decorators.csrf import csrf_exempt,csrf_protect —> 需要引入 csrf_exempt

class UserView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return HttpResponse(’…’)

或者:
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect

@method_decorator(csrf_exempt,name=‘dispatch’) —> 指定名字
class UserView(View):
def dispatch(self, request, *args, **kwargs):
return HttpResponse(’…’)

複製代碼

28.列舉django orm 中所有的方法(QuerySet對象的所有方法)

複製代碼
返回QuerySet對象的方法有:
      all()
      filter()
      exclude()
      order_by()
      reverse()
      distinct()
  特殊的QuerySet:
      values()       返回一個可迭代的字典序列
      values_list() 返回一個可迭代的元組序列
  返回具體對象的:
      get()
      first()
      last()
  返回布爾值的方法有:
      exists()
  返回數字的方法有:
      count() 
複製代碼

29.only和defer的區別?

複製代碼
 def defer(self, *fields):
    models.UserInfo.objects.defer('username','id')
    或
    models.UserInfo.objects.filter(...).defer('username','id')
    #映射中排除某列數據

def only(self, *fields):
#僅取某個表中的數據
models.UserInfo.objects.only(‘username’,‘id’)

models.UserInfo.objects.filter(…).only(‘username’,‘id’)

複製代碼

30.select_related和prefetch_related的區別?

複製代碼
# 他倆都用於連表查詢,減少SQL查詢次數
\select_related
select_related主要針一對一和多對一關係進行優化,通過多表join關聯查詢,一次性獲得所有數據,
存放在內存中,但如果關聯的表太多,會嚴重影響數據庫性能。
def index(request): obj = Book.objects.all().select_related("publisher") return render(request, "index.html", locals()) \prefetch_related prefetch_related是通過分表,先獲取各個表的數據,存放在內存中,然後通過Python處理他們之間的關聯。 def index(request): obj = Book.objects.all().prefetch_related("publisher") return render(request, "index.html", locals())
複製代碼

 

複製代碼
def select_related(self, *fields)
     性能相關:表之間進行join連表操作,一次性獲取關聯的數據。
     model.tb.objects.all().select_related()
     model.tb.objects.all().select_related('外鍵字段') model.tb.objects.all().select_related('外鍵字段__外鍵字段') 

def prefetch_related(self, *lookups)
性能相關:多表連表操作時速度會慢,使用其執行多次SQL查詢在Python代碼中實現連表操作。
# 獲取所有用戶表
# 獲取用戶類型表where id in (用戶表中的查到的所有用戶ID)
models.UserInfo.objects.prefetch_related(‘外鍵字段’)

from django.db.models import<span> Count, Case, When, IntegerField
        Article.objects.annotate(
            numviews=<span>Count(Case(
                When(readership__what_time__lt=treshold, then=1<span>),
                output_field=<span>CharField(),
            ))
        )

        students = Student.objects.all().annotate(num_excused_absences=<span>models.Sum(
            models.Case(
                models.When(absence__type='Excused', then=1<span>),
            default=<span>0,
            output_field=<span>models.IntegerField()
        )))</span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
複製代碼
複製代碼
# 1次SQL
# select * from userinfo
objs = UserInfo.obejcts.all()
for item in objs: print(item.name) 

n+1次SQL

select * from userinfo

objs = UserInfo.obejcts.all()
for item in objs:
# select * from usertype where id = item.id
print(item.name,item.ut.title)

select_related()

1次SQL

select * from userinfo inner join usertype on userinfo.ut_id = usertype.id

objs = UserInfo.obejcts.all().select_related(‘ut’) 連表查詢
for item in objs:
print(item.name,item.ut.title)

.prefetch_related()
# select * from userinfo where id <= 8
# 計算:[1,2]
# select * from usertype where id in [1,2]
objs = UserInfo.obejcts.filter(id__lte=8).prefetch_related(‘ut’)
for obj in objs:
print(obj.name,obj.ut.title)

複製代碼

31.filter和exclude的區別?

複製代碼
  def filter(self, *args, **kwargs)
      # 條件查詢(符合條件)
       # 查出符合條件
      # 條件可以是:參數,字典,Q

def exclude(self, *args, **kwargs)
# 條件查詢(排除條件)
# 排除不想要的
# 條件可以是:參數,字典,Q

複製代碼

32.列舉django orm中三種能寫sql語句的方法。

複製代碼
原生SQL --->  connection
from django.db import connection, connections
cursor = connection.cursor()  # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..) 
靠近原生SQL-->extra\raw extra - extra def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # 構造額外的查詢條件或者映射,如:子查詢 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) Entry.objects.extra(where=['headline=%s'], params=['Lennon']) Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, s elect_params=(1,), order_by=['-nid'])

- raw
def raw(self, raw_query, params=None, translations=None, using=None):
# 執行原生SQL
models.UserInfo.objects.raw(‘select * from userinfo’)
# 如果SQL是其他表時,必須將名字設置爲當前UserInfo對象的主鍵列名
models.UserInfo.objects.raw(‘select id as nid,name as title from 其他表’)
# 爲原生SQL設置參數
models.UserInfo.objects.raw(‘select id as nid from userinfo where nid>%s’, params=[12,])
# 將獲取的到列名轉換爲指定列名
name_map = {‘first’: ‘first_name’, ‘last’: ‘last_name’, ‘bd’: ‘birth_date’, ‘pk’: ‘id’}
Person.objects.raw(‘SELECT * FROM some_other_table’, translations=name_map)
# 指定數據庫
models.UserInfo.objects.raw(‘select * from userinfo’, using=「default」)

複製代碼

33.django orm 中如何設置讀寫分離?

複製代碼
 方式一:手動使用queryset的using方法
from django.shortcuts import render,HttpResponse from app01 import models def index(request): 

models.UserType.objects.using('db1').create(title='普通用戶'<span>)

# 手動指定去某個數據庫取數據
result = models.UserType.objects.all().using(‘db1’)
print(result)

return HttpResponse('...'<span>)

方式二:寫配置文件
class Router1:
  # 指定到某個數據庫取數據
def db_for_read(self, model, **hints):
「」"
Attempts to read auth models go to auth_db.
「」"
if model._meta.model_name == ‘usertype’:
return ‘db1’
else:
return ‘default’
   # 指定到某個數據庫存數據
def db_for_write(self, model, **hints):
「」"
Attempts to write auth models go to auth_db.
「」"
return ‘default’
再寫到配置
DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.sqlite3’,
‘NAME’: os.path.join(BASE_DIR, ‘db.sqlite3’),
},
‘db1’: {
‘ENGINE’: ‘django.db.backends.sqlite3’,
‘NAME’: os.path.join(BASE_DIR, ‘db.sqlite3’),
}
}
DATABASE_ROUTERS = [‘db_router.Router1’,]

複製代碼

34.F和Q的作用?

複製代碼
  F:主要用來獲取原數據進行計算。
  Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操作。
  修改操作也可以使用F函數,比如將每件商品的價格都在原價格的基礎上增加10
from django.db.models import F
from app01.models import Goods

Goods.objects.update(price=F(「price」)+10) # 對於goods表中每件商品的價格都在原價格的基礎上增加10元
F查詢專門對對象中某列值的操作,不可使用__雙下劃線!

Q:用來進行復雜查詢
    Q查詢可以組合使用 「&」, 「|」 操作符,當一個操作符是用於兩個Q的對象,它產生一個新的Q對象,
  Q對象可以用 「~」 操作符放在前面表示否定,也可允許否定與不否定形式的組合。
  Q對象可以與關鍵字參數查詢一起使用,不過一定要把Q對象放在關鍵字參數查詢的前面。
Q(條件1) | Q(條件2) 或 Q(條件1) & Q(條件2) 且 Q(條件1) & ~Q(條件2) 非
複製代碼

35.values和values_list的區別?

def values(self, *fields):
    # 獲取每行數據爲字典格式

def values_list(self, *fields, **kwargs):
# 獲取每行數據爲元祖

36.如何使用django orm批量創建數據?

複製代碼
def bulk_create(self, objs, batch_size=None):
    # 批量插入
    # batch_size表示一次插入的個數
    objs = [ models.DDD(name='r11'), models.DDD(name='r22') ] models.DDD.objects.bulk_create(objs, 10)
複製代碼

37.django的Form和ModeForm的作用?

複製代碼
 - 作用:
      - 對用戶請求數據格式進行校驗 - 自動生成HTML標籤 - 區別: - Form,字段需要自己手寫。 class Form(Form): xx = fields.CharField(.) xx = fields.CharField(.) xx = fields.CharField(.) xx = fields.CharField(.) - ModelForm,可以通過Meta進行定義 class MForm(ModelForm): class Meta: fields = "__all__" model = UserInfo - 應用:只要是客戶端向服務端發送表單數據時,都可以進行使用,如:用戶登錄註冊
複製代碼

38.django的Form組件中,如果字段中包含choices參數,請使用兩種方式實現數據源實時更新。

複製代碼
 方式一:重寫構造方法,在構造方法中重新去數據庫獲取值
  class UserForm(Form): name = fields.CharField(label='用戶名',max_length=32) email = fields.EmailField(label='郵箱') ut_id = fields.ChoiceField( # choices=[(1,'普通用戶'),(2,'IP用戶')] choices=[] ) 

def __init__(self,*args,**<span>kwargs):
      super(UserForm,self).__init__(*args,**<span>kwargs)

      self.fields['ut_id'].choices = models.UserType.objects.all().values_list('id','title'<span>)


方式二: ModelChoiceField字段
from django.forms import Form
from django.forms import fields
from django.forms.models import ModelChoiceField
class UserForm(Form):
name = fields.CharField(label=‘用戶名’,max_length=32)
email = fields.EmailField(label=‘郵箱’)
ut_id = ModelChoiceField(queryset=models.UserType.objects.all())

依賴:
class UserType(models.Model):
title = models.CharField(max_length=32)

def __str__<span>(self):
          return self.title</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
複製代碼

39.django的Model中的ForeignKey字段中的on_delete參數有什麼作用?

複製代碼
在django2.0後,定義外鍵和一對一關係的時候需要加on_delete選項,此參數爲了避免兩個表裏的數據不一致問題,不然會報錯:

TypeError: init() missing 1 required positional argument: ‘on_delete’

舉例說明:

user=models.OneToOneField(User)

owner=models.ForeignKey(UserProfile)

需要改成:

user=models.OneToOneField(User,on_delete=models.CASCADE) –在老版本這個參數(models.CASCADE)是默認值

owner=models.ForeignKey(UserProfile,on_delete=models.CASCADE) –在老版本這個參數(models.CASCADE)是默認值
參數說明:

on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五個可選擇的值

CASCADE:此值設置,是級聯刪除。
PROTECT:此值設置,是會報完整性錯誤。
SET_NULL:此值設置,會把外鍵設置爲null,前提是允許爲null。
SET_DEFAULT:此值設置,會把設置爲外鍵的默認值。
SET():此值設置,會調用外面的值,可以是一個函數。
一般情況下使用CASCADE就可以了。

複製代碼

40.django中csrf的實現機制?

複製代碼
目的:防止用戶直接向服務端發起POST請求

- 用戶先發送GET獲取csrf token: Form表單中一個隱藏的標籤 + token - 發起POST請求時,需要攜帶之前發送給用戶的csrf token; - 在中間件的process_view方法中進行校驗。

在html中添加{%csrf_token%}標籤

複製代碼

41.django如何實現websocket?

django中可以通過channel實現websocket

42.基於django使用ajax發送post請求時,都可以使用哪種方法攜帶csrf token?

複製代碼
//方式一給每個ajax都加上上請求頭
    function Do1(){
        $.ajax({
            url:"/index/", data:{id:1}, type:'POST',        data:{csrfmiddlewaretoken:'{{ csrf_token }}',name:'alex'} success:function(data){ console.log(data); } }); }  方式二:需要先下載jQuery-cookie,才能去cookie中獲取token function Do1(){ $.ajax({ url:"/index/", data:{id:1}, type:'POST', headers:{ 'X-CSRFToken':$.cookie('csrftoken') // 去cookie中獲取 }, success:function(data){ console.log(data); } }); } 

方式三:搞個函數ajaxSetup,當有多的ajax請求,即會執行這個函數
KaTeX parse error: Expected '}', got 'EOF' at end of input: …("X-CSRFToken",.cookie(‘csrftoken’))
}
});

函數版本
<body>
<input type=「button」 「Do1();」 value=「Do it」/>
<input type=「button」 「Do2();」 value=「Do it」/>
<input type=「button」 「Do3();」 value=「Do it」/>

<script src="/static/jquery-3.3.1.min.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader(「X-CSRFToken」, $.cookie(‘csrftoken’));
}
});

function Do1(){
    $.ajax({
        url:"/index/"<span>,
        data:{id:1<span>},
        type:'POST'<span>,
        success:function(data){
            console.log(data);
        }
    });
}

 function Do2(){
    $.ajax({
        url:"/index/"<span>,
        data:{id:1<span>},
        type:'POST'<span>,
        success:function(data){
            console.log(data);
        }
    });
}

 function Do3(){
    $.ajax({
        url:"/index/"<span>,
        data:{id:1<span>},
        type:'POST'<span>,
        success:function(data){
            console.log(data);
        }
    });
}

</script>
</body>

複製代碼

43.django中如何實現orm表中添加數據時創建一條日誌記錄。

 給信號註冊函數

複製代碼
使用django的信號機制,可以在添加、刪除數據前後設置日誌記錄
pre_init  # Django中的model對象執行其構造方法前,自動觸發
post_init  # Django中的model對象執行其構造方法後,自動觸發
pre_save  # Django中的model對象保存前,自動觸發
post_save  # Django中的model對象保存後,自動觸發
pre_delete  # Django中的model對象刪除前,自動觸發
post_delete  # Django中的model對象刪除後,自動觸發
複製代碼

44.django緩存如何設置?

複製代碼
jango中提供了6種緩存方式:
  開發調試(不加緩存)
  內存
  文件
  數據庫
  Memcache緩存(python-memcached模塊)   Memcache緩存(pylibmc模塊) 

安裝第三方組件支持redis:
  django-redis組件

設置緩存

全站緩存(中間件)

MIDDLEWARE_CLASSES = (
‘django.middleware.cache.UpdateCacheMiddleware’, #第一
‘django.middleware.common.CommonMiddleware’,
‘django.middleware.cache.FetchFromCacheMiddleware’, #最後
)

視圖緩存

from django.views.decorators.cache import cache_page
import time

@cache_page(15) #超時時間爲15秒
def index(request):
t=time.time() #獲取當前時間
return render(request,「index.html」,locals())

模板緩存

{% load cache %}
<h3 style=「color: green」>不緩存:-----{{ t }}</h3>

{% cache 2 ‘name’ %} # 存的key
<h3>緩存:-----:{{ t }}</h3>
{% endcache %}

複製代碼

45.django的緩存能使用redis嗎?如果可以的話,如何配置?

複製代碼
  pip install django-redis  
  apt-get install redis-serv 

在setting添加配置文件
CACHES = {
「default」: {
「BACKEND」: 「django_redis.cache.RedisCache」, # 緩存類型
「LOCATION」: 「127.0.0.1:6379」, # ip端口
「OPTIONS」: {
「CLIENT_CLASS」: 「django_redis.client.DefaultClient」, #
「CONNECTION_POOL_KWARGS」: {「max_connections」: 100} # 連接池最大連接數
# 「PASSWORD」: 「密碼」,
}
}
}

使用
from django.shortcuts import render,HttpResponse
from django_redis import get_redis_connection

def index(request):

根據名字去連接池中獲取連接

conn = get_redis_connection(「default」)
conn.hset(‘n1’,‘k1’,‘v1’) # 存數據
return HttpResponse(’…’)

複製代碼

46.django路由系統中name的作用?

複製代碼
反向解析路由字符串

路由系統中name的作用:反向解析
url(r'^home', views.home, name='home')
在模板中使用:url 'home' %}
在視圖中使用:reverse(「home」)

複製代碼

47.django的模板中filter和simple_tag的區別?

複製代碼
filter : 類似管道,只能接受兩個參數第一個參數是|前的數據

simple_tag : 類似函數

1、模板繼承:%  CACHES = {
「default」: {
「BACKEND」: 「django_redis.cache.RedisCache」, # 緩存類型
「LOCATION」: 「127.0.0.1:6379」, # ip端口
「OPTIONS」: {
「CLIENT_CLASS」: 「django_redis.client.DefaultClient」, #
「CONNECTION_POOL_KWARGS」: {「max_connections」: 100} # 連接池最大連接數
# 「PASSWORD」: 「密碼」,
}
}
}

使用
from django.shortcuts import render,HttpResponse
from django_redis import get_redis_connection

def index(request):

根據名字去連接池中獲取連接

conn = get_redis_connection(「default」)
conn.hset(‘n1’,‘k1’,‘v1’) # 存數據
return HttpResponse(’…’)

複製代碼

46.django路由系統中name的作用?

複製代碼
反向解析路由字符串

路由系統中name的作用:反向解析
url(r'^home', views.home, name='home')
在模板中使用:url 'home' %}
在視圖中使用:reverse(「home」)

複製代碼

47.django的模板中filter和simple_tag的區別?

複製代碼
filter : 類似管道,只能接受兩個參數第一個參數是|前的數據

simple_tag : 類似函數

1、模板繼承:extends 'layouts.html' %}
2、自定義方法
&nbnbsp;   'filter':只能傳遞兩個參數,可以在if、for語句中使用
    'simple_tag':可以無線傳參,不能在if for中使用
    'inclusion_tags':可以使用模板和後端數據
3、防xss攻擊: '|safe''mark_safe'

 
  
複製代碼

48.django-debug-toolbar的作用?

一、查看訪問的速度、數據庫的行爲、cache命中等信息。 
二、尤其在Mysql訪問等的分析上大有用處(sql查詢速度)

49.django中如何實現單元測試?

對於每一個測試方法都會將setUp()和tearDown()方法執行一遍
會單獨新建一個測試數據庫來進行數據庫的操作方面的測試,默認在測試完成後銷燬。
在測試方法中對數據庫進行增刪操作,最後都會被清除。也就是說,在test_add中插入的數據,在test_add測試結束後插入的數據會被清除。
django單元測試時爲了模擬生產環境,會修改settings中的變量,例如, 把DEBUG變量修改爲True, 把ALLOWED_HOSTS修改爲[*]。

50.解釋orm中 db first 和 code first的含義?

db first: 先創建數據庫,再更新表模型
code first:先寫表模型,再更新數據庫

https://www.cnblogs.com/jassin-du/p/8988897.html

51.django中如何根據數據庫表生成model中的類?

1、修改seting文件,在setting裏面設置要連接的數據庫類型和名稱、地址
2、運行下面代碼可以自動生成models模型文件 - python manage.py inspectdb 3、創建一個app執行下下面代碼: - python manage.py inspectdb > app/models.py 

52.使用orm和原生sql的優缺點?

複製代碼
SQL:
# 優點:
執行速度快 # 缺點: 編寫複雜,開發效率不高 --------------------------------------------------------------------------- ORM: # 優點: 讓用戶不再寫SQL語句,提高開發效率 可以很方便地引入數據緩存之類的附加功能 # 缺點: 在處理多表聯查、where條件複雜查詢時,ORM的語法會變得複雜。 沒有原生SQL速度快
複製代碼

53.簡述MVC和MTV

MVC:model、view(模塊)、controller(視圖)
MTV:model、tempalte、view 

54.django的contenttype組件的作用?

contenttype是django的一個組件(app),它可以將django下所有app下的表記錄下來
可以使用他再加上表中的兩個字段,實現一張表和N張表動態創建FK關係。
   - 字段:表名稱 - 字段:數據行ID 應用:路飛表結構優惠券和專題課和學位課關聯

55.談談你對restfull 規範的認識?

複製代碼
restful其實就是一套編寫接口的'協議',規定如何編寫以及如何設置返回值、狀態碼等信息。
# 最顯著的特點:
# 用restful: 
 給用戶一個url,根據method不同在後端做不同的處理 比如:post創建數據、get獲取數據、put和patch修改數據、delete刪除數據。 # 不用restful: 給調用者很多url,每個url代表一個功能,比如:add_user/delte_user/edit_user/ # 當然,還有協議其他的,比如: '版本'來控制讓程序有多個版本共存的情況,版本可以放在 url、請求頭(accept/自定義)、GET參數 '狀態碼'200/300/400/500 'url中儘量使用名詞'restful也可以稱爲「面向資源編程」 'api標示' api.luffycity.com www.luffycity.com/api/
複製代碼

56.接口的冪等性是什麼意思?

複製代碼
'一個接口通過1次相同的訪問,再對該接口進行N次相同的訪問時,對資源不造影響就認爲接口具有冪等性。'
    GET,  #第一次獲取結果、第二次也是獲取結果對資源都不會造成影響,冪等。
    POST, #第一次新增數據,第二次也會再次新增,非冪等。
    PUT,  #第一次更新數據,第二次不會再次更新,冪等。
    PATCH,#第一次更新數據,第二次不會再次更新,非冪等。
    DELTE,#第一次刪除數據,第二次不在再刪除,冪等。
複製代碼

57.什麼是RPC?

'遠程過程調用協議'
是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。
進化的順序: 現有的RPC,然後有的RESTful規範

58.Http和Https的區別?

複製代碼
#Http: 80端口
#https: 443端口
# http信息是明文傳輸,https則是具有安全性的ssl�tp和Https的區別?

    
    
複製代碼
#Http: 80端口
#https: 443端口
# http信息是明文傳輸,https則是具有安全性的ssl加密傳輸協議。
#- 自定義證書 
    - 服務端:創建一對證書
    - 客戶端:必須攜帶證書 #- 購買證書 - 服務端: 創建一對證書,。。。。 - 客戶端: 去機構獲取證書,數據加密後發給咱們的服務單 - 證書機構:公鑰給改機構
複製代碼

59.爲什麼要使用django rest framework框架?

複製代碼
# 在編寫接口時可以不使用django rest framework框架,
# 不使用:也可以做,可以用django的CBV來實現,開發者編寫的代碼會更多一些。
# 使用:內部幫助我們提供了很多方便的組件,我們通過配置就可以完成相應操作,如:
    '序列化'可以做用戶請求數據校驗+queryset對象的序列化稱爲json
    '解析器'獲取用戶請求數據request.data,會自動根據content-type請求頭的不能對數據進行解析 '分頁'將從數據庫獲取到的數據在頁面進行分頁顯示。 # 還有其他組件: '認證'、'權限'、'訪問頻率控制 
複製代碼

60.django rest framework框架中都有那些組件?

複製代碼
#- 路由,自動幫助開發者快速爲一個視圖創建4個url
        www.oldboyedu.com/api/v1/student/$
        www.oldboyedu.com/api/v1/student(?P<format>\w+)$ www.oldboyedu.com/api/v1/student/(?P<pk>\d+)/$ www.oldboyedu.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$ #- 版本處理 - 問題:版本都可以放在那裏? - url - GET - 請求頭 #- 認證 - 問題:認證流程? #- 權限 - 權限是否可以放在中間件中?以及爲什麼? #- 訪問頻率的控制  匿名用戶可以真正的防止?無法做到真正的訪問頻率控制,只能把小白拒之門外。 如果要封IP,使用防火牆來做。 登錄用戶可以通過用戶名作爲唯一標示進行控制,如果有人註冊很多賬號,則無法防止。 #- 視圖 #- 解析器 ,根據Content-Type請求頭對請求體中的數據格式進行處理。request.data #- 分頁 #- 序列化 - 序列化 - source - 定義方法 - 請求數據格式校驗 #- 渲染器 
複製代碼

61.django rest framework框架中的視圖都可以繼承哪些類

複製代碼
a. 繼承APIView(最原始)但定製性比較強
    這個類屬於rest framework中的頂層類,內部幫助我們實現了只是基本功能:認證、權限、頻率控制,
但凡是數據庫、分頁等操作都需要手動去完成,比較原始。
    class GenericAPIView(APIView) def post(...): pass 

b.繼承GenericViewSet(ViewSetMixin,generics.GenericAPIView)
  首先他的路由就發生變化
如果繼承它之後,路由中的as_view需要填寫對應關係
  在內部也幫助我們提供了一些方便的方法:
  get_queryset
  get_object
  get_serializer
  get_serializer_class
  get_serializer_context
  filter_queryset
注意:要設置queryset字段,否則會拋出斷言的異常。

代碼
只提供增加功能 只繼承GenericViewSet

class TestView(GenericViewSet):
  serialazer_class = xxx
  def creat(self,*args,**kwargs):
    pass # 獲取數據並對數據

c. 繼承 modelviewset --> 快速快發
    -ModelViewSet(增刪改查全有+數據庫操作)
    -mixins.CreateModelMixin(只有增),GenericViewSet
    -mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet
  對數據庫和分頁等操作不用我們在編寫,只需要繼承相關類即可。
  
示例:只提供增加功能
class TestView(mixins.CreateModelMixin,GenericViewSet):
    serializer_class = XXXXXXX
***
  modelviewset --> 快速開發,複雜點的genericview、apiview

複製代碼

62.簡述 django rest framework框架的認證流程。

複製代碼
- 如何編寫?寫類並實現authenticators
  請求進來認證需要編寫一個類,類裏面有一個authenticators方法,我們可以自定義這個方法,可以定製3類返回值。
  成功返回元組,返回none爲匿名用戶,拋出異常爲認證失敗。

源碼流程:請求進來先走dispatch方法,然後封裝的request對象會執行user方法,由user觸發authenticators認證流程
- 方法中可以定義三種返回值:
- (user,auth),認證成功
- None , 匿名用戶
- 異常 ,認證失敗
- 流程:
- dispatch
- 再去request中進行認證處理

複製代碼

63.django rest framework如何實現的用戶訪問頻率控制? 

複製代碼
# 對匿名用戶,根據用戶IP或代理IP作爲標識進行記錄,爲每個用戶在redis中建一個列表
    {
        throttle_1.1.1.1:[1526868876.497521,152686885.497521...], throttle_1.1.1.2:[1526868876.497521,152686885.497521...], throttle_1.1.1.3:[1526868876.497521,152686885.497521...], } 每個用戶再來訪問時,需先去記錄中剔除過期記錄,再根據列表的長度判斷是否可以繼續訪問。 '如何封IP':在防火牆中進行設置 -------------------------------------------------------------------------- # 對註冊用戶,根據用戶名或郵箱進行判斷。  { throttle_xxxx1:[1526868876.497521,152686885.497521...], throttle_xxxx2:[1526868876.497521,152686885.497521...], throttle_xxxx3:[1526868876.497521,152686885.497521...], } 每個用戶再來訪問時,需先去記錄中剔除過期記錄,再根據列表的長度判斷是否可以繼續訪問。 \如1分鐘:40次,列表長度限制在40,超過40則不可訪問
複製代碼/(?P<pk>\d+)/$ www.oldboyedu.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$ #- 版本處理 - 問題:版本都可以放在那裏? - url - GET - 請求頭 #- 認證 - 問題:認證流程? #- 權限 - 權限是否可以放在中間件中?以及爲什麼? #- 訪問頻率的控制 匿名用戶可以真正的防止?無法做到真正的訪問頻率控制,只能把小白拒之門外。 如果要封IP,使用防火牆來做。 登錄用戶可以通過用戶名作爲唯一標示進行控制,如果有人註冊很多賬號,則無法防止。 #- 視圖 #- 解析器 ,根據Content-Type請求頭對請求體中的數據格式進行處理。request.data #- 分頁 #- 序列化 - 序列化 - source - 定義方法 - 請求數據格式校驗 #- 渲染器 
複製代碼

61.django rest framework框架中的視圖都可以繼承哪些類

複製代碼
a. 繼承APIView(最原始)但定製性比較強
    這個類屬於rest framework中的頂層類,內部幫助我們實現了只是基本功能:認證、權限、頻率控制,
但凡是數據庫、分頁等操作都需要手動去完成,比較原始。
    class GenericAPIView(APIView) def post(...): pass 

b.繼承GenericViewSet(ViewSetMixin,generics.GenericAPIView)
  首先他的路由就發生變化
如果繼承它之後,路由中的as_view需要填寫對應關係
  在內部也幫助我們提供了一些方便的方法:
  get_queryset
  get_object
  get_serializer
  get_serializer_class
  get_serializer_context
  filter_queryset
注意:要設置queryset字段,否則會拋出斷言的異常。

代碼
只提供增加功能 只繼承GenericViewSet

class TestView(GenericViewSet):
  serialazer_class = xxx
  def creat(self,*args,**kwargs):
    pass # 獲取數據並對數據

c. 繼承 modelviewset --> 快速快發
    -ModelViewSet(增刪改查全有+數據庫操作)
    -mixins.CreateModelMixin(只有增),GenericViewSet
    -mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet
  對數據庫和分頁等操作不用我們在編寫,只需要繼承相關類即可。
  
示例:只提供增加功能
class TestView(mixins.CreateModelMixin,GenericViewSet):
    serializer_class = XXXXXXX
***
  modelviewset --> 快速開發,複雜點的genericview、apiview

複製代碼

62.簡述 django rest framework框架的認證流程。

複製代碼
- 如何編寫?寫類並實現authenticators
  請求進來認證需要編寫一個類,類裏面有一個authenticators方法,我們可以自定義這個方法,可以定製3類返回值。
  成功返回元組,返回none爲匿名用戶,拋出異常爲認證失敗。

源碼流程:請求進來先走dispatch方法,然後封裝的request對象會執行user方法,由user觸發authenticators認證流程
- 方法中可以定義三種返回值:
- (user,auth),認證成功
- None , 匿名用戶
- 異常 ,認證失敗
- 流程:
- dispatch
- 再去request中進行認證處理

複製代碼

63.django rest framework如何實現的用戶訪問頻率控制? 

複製代碼
# 對匿名用戶,根據用戶IP或代理IP作爲標識進行記錄,爲每個用戶在redis中建一個列表
    {
        throttle_1.1.1.1:[1526868876.497521,152686885.497521...], throttle_1.1.1.2:[1526868876.497521,152686885.497521...], throttle_1.1.1.3:[1526868876.497521,152686885.497521...], } 每個用戶再來訪問時,需先去記錄中剔除過期記錄,再根據列表的長度判斷是否可以繼續訪問。 '如何封IP':在防火牆中進行設置 -------------------------------------------------------------------------- # 對註冊用戶,根據用戶名或郵箱進行判斷。  { throttle_xxxx1:[1526868876.497521,152686885.497521...], throttle_xxxx2:[1526868876.497521,152686885.497521...], throttle_xxxx3:[1526868876.497521,152686885.497521...], } 每個用戶再來訪問時,需先去記錄中剔除過期記錄,再根據列表的長度判斷是否可以繼續訪問。 \如1分鐘:40次,列表長度限制在40,超過40則不可訪問
複製代碼

64.Flask框架的優勢?

Flask自由、靈活,可擴展性強,透明可控,第三方庫的選擇面廣,
開發時可以結合最流行最強大的Python庫,

65.Flask框架依賴組件

# 依賴jinja2模板引擎
# 依賴werkzurg協議

66.Flask藍圖的作用

# blueprint把實現不同功能的module分開.也就是把一個大的App分割成各自實現不同功能的module.
# 在一個blueprint中可以調用另一個blueprint的視圖函數, 但要加相應的blueprint名.

67.列舉使用的Flask第三方組件?

複製代碼
# Flask組件
    flask-session  session放在redis
    flask-SQLAlchemy 如django裏的ORM操作 flask-migrate 數據庫遷移 flask-script 自定義命令 blinker 信號-觸發信號 # 第三方組件  Wtforms 快速創建前端標籤、文本校驗 dbutile 創建數據庫連接池 gevnet-websocket 實現websocket # 自定義Flask組件  自定義auth認證 參考flask-login組件
複製代碼

68.簡述Flask上下文管理流程?

複製代碼
# a、簡單來說,falsk上下文管理可以分爲三個階段:
  1、'請求進來時':將請求相關的數據放入上下問管理中
  2、'在視圖函數中':要去上下文管理中取值   3、'請求響應':要將上下文管理中的數據清除 # b、詳細點來說:   1、'請求剛進來':         將request,session封裝在RequestContext類中         app,g封裝在AppContext類中         並通過LocalStack將requestcontext和appcontext放入Local類中   2、'視圖函數中':         通過localproxy--->偏函數--->localstack--->local取值   3、'請求響應時':         先執行save.session()再各自執行pop(),將local中的數據清除
複製代碼

69.Flask中的g的作用?

# g是貫穿於一次請求的全局變量,當請求進來將g和current_app封裝爲一個APPContext類,
# 再通過LocalStack將Appcontext放入Local中,取值時通過偏函數在LocalStack、local中取值;
# 響應時將local中的g數據刪除:

Flask中上下文管理主要涉及到了那些相關的類?並描述類主要作用?

RequestContext  #封裝進來的請求(賦值給ctx)
AppContext      #封裝app_ctx
LocalStack      #將local對象中的數據維護成一個棧(先進後出)
Local  
相關文章
相關標籤/搜索