1. 程式人生 > 實用技巧 >Fluid 0.4 新版本正式釋出:支援資料預熱,優化小檔案場景

Fluid 0.4 新版本正式釋出:支援資料預熱,優化小檔案場景

閱讀目錄

參考地址

目錄

正文

回到頂部

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

當我們從Python官方網站下載並安裝好Python 3.6後,我們就直接獲得了一個官方版本的直譯器:CPython。這個直譯器是用C語言開發的,所以叫CPython。在命令列下執行python就是啟動CPython直譯器。

CPython是使用最廣的Python直譯器。教程的所有程式碼也都在CPython下執行。

IPython

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

CPython用>>>作為提示符,而IPython用In [序號]:作為提示符。

PyPy

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

絕大部分Python程式碼都可以在PyPy下執行,但是PyPy和CPython有一些是不同的,這就導致相同的Python程式碼在兩種直譯器下執行可能會有不同的結果。如果你的程式碼要放到PyPy下執行,就需要了解PyPy和CPython的不同點。

Jython

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

IronPython

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

小結:

  Python的直譯器很多,但使用最廣泛的還是CPython。如果要和Java或.Net平臺互動,最好的辦法不是用Jython或IronPython,而是通過網路呼叫來互動,確保各程式之間的獨
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            000010103            000000119            0000100112            00001100

再將以上二進位制拼接起來計算十進位制結果: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

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

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

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

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

6. 求結果: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 大小寫翻轉
20for 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(b[1](1))
# 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():
    returnlambda 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)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}",
                                      message='密碼至少8個字元,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字元')

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

        
        form = LoginForm()
        for item in form:
            print(item)
            
    - 列表、字典、元組

裝飾器

 裝飾器:
能夠在不修改原函式程式碼的基礎上,在執行前後進行定製操作,閉包函式的一種應用
場景:
   - 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 != h:
        m = int((l + h) / 2)
        if li[m] < someone:
            l = m
        else:
            h = m
    p = h
    if p >= len(li) or li[p] != someone:
        print("元素不存在")
    else:
        str = "元素索引為%d" % 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 func(self):
        print('Foo.func')

class Son(Foo):
    def func(self):
        print('Son.func')

s = Son()
 # Son.func

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

    def say(self):
        print('AAAAA')

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 bar(self, message):
        print("%s from Parent" % 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 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]=value
    def __delitem__(self, key):
        print('del obj[key]時,我執行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key時,我執行')
        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')
 
    # 靜態方法:能用Num和例項化物件呼叫
    @staticmethod 
    def three():  
        print ('3')
 
    # 類方法:第一個引數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, **kwargs):
        return cls.__init__(cls)
  
    def __call__(self, *args, **kwargs):
        return 'call'
  
  
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()

# 應用場景
    - 高階函式
    - 閉包
    - 裝飾器 
    - functools.wraps(func)

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, returnindicesof the two numbers such that they add up to a
specific target.You may assume that each input would haveexactlyone solution, and you may
not use thesameelement 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'
                    lookup_url_kwarg = None

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

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

                    def get_queryset(self):

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

                        queryset = self.queryset
                        if isinstance(queryset, QuerySet):
                            # Ensure queryset is re-evaluated on each request.
                            queryset = queryset.all()
                        return queryset

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服務特性的企業內部網路技術體系VPN(虛擬專用網)。

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出來返回給你,整個過程就結束了。

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

然而 name欄位新增唯一索引了,加不加limit1,意義都不大;

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 > 22222222) as B limit 10 offset 0
      
      如果使用者自己修改頁碼,也可能導致慢;此時對url種的頁碼進行加密(rest framework )

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

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 
    
        啟動兩個哨兵   

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

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() 方式二 - 資料庫的鎖

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 > 0:  # 有庫存
        pipe.set('count', count - 1)

    # 執行,把所有命令一次性推送過去
    pipe.execute()

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},
{"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) {
            .pg-header{
                background-color: aqua;
            }
        }
        @media (min-width: 992px) {
            .pg-header{
                background-color: blueviolet;
            }
        }
    </style>
</head>
<body>
    <div class="pg-header"></div>
</body>
</html>

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

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

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

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>XMLHttpRequest - Ajax請求</h1>
    <input type="button" onclick="XmlGetRequest();" value="Get傳送請求" />
    <input type="button" onclick="XmlPostRequest();" value="Post傳送請求" />

    <script src="/statics/jquery-1.12.4.js"></script>
    <script type="text/javascript">

        function GetXHR(){
            var xhr = null;
            if(XMLHttpRequest){
                xhr = new XMLHttpRequest();
            }else{
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            }
            return xhr;

        }

        function XhrPostRequest(){
            var xhr = GetXHR();
            // 定義回撥函式
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已經接收到全部響應資料,執行以下操作
                    var data = xhr.responseText;
                    console.log(data);
                }
            };
            // 指定連線方式和地址----檔案方式
            xhr.open('POST', "/test/", true);
            // 設定請求頭
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            // 傳送請求
            xhr.send('n1=1;n2=2;');
        }

        function XhrGetRequest(){
            var xhr = GetXHR();
            // 定義回撥函式
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已經接收到全部響應資料,執行以下操作
                    var data = xhr.responseText;
                    console.log(data);
                }
            };
            // 指定連線方式和地址----檔案方式
            xhr.open('get', "/test/", true);
            // 傳送請求
            xhr.send();
        }

    </script>

</body>
</html>
基於原生AJAX - Demo
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="XmlSendRequest();" value='Ajax請求' />
    </p>


    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>

        function JqSendRequest(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'GET',
                dataType: 'text',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>
基於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>

    <script>
        setInterval(function () {
            location.reload();
        },2000)
    </script>
</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 }}" ondblclick="vote({{ k }});">ID:{{ k }}, 姓名:{{ v.name }} ,票數:<span>{{ v.count }}</span></li>
        {% endfor %}
    </ul>

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

                }
            })
        }

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

                }
            })
        }
    </script>
</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
訊號、
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 Count, Case, When, IntegerField
            Article.objects.annotate(
                numviews=Count(Case(
                    When(readership__what_time__lt=treshold, then=1),
                    output_field=CharField(),
                ))
            )

            students = Student.objects.all().annotate(num_excused_absences=models.Sum(
                models.Case(
                    models.When(absence__type='Excused', then=1),
                default=0,
                output_field=models.IntegerField()
            )))
# 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='普通使用者')
  # 手動指定去某個資料庫取資料
    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',]

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,**kwargs):
          super(UserForm,self).__init__(*args,**kwargs)

          self.fields['ut_id'].choices = models.UserType.objects.all().values_list('id','title')
  
方式二: 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

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請求,即會執行這個函式
        $.ajaxSetup({
           beforeSend:function (xhr,settings) {
               xhr.setRequestHeader("X-CSRFToken",$.cookie('csrftoken'))
           } 
        });

函式版本
<body>
<input type="button" onclick="Do1();"  value="Do it"/>
<input type="button" onclick="Do2();"  value="Do it"/>
<input type="button" onclick="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/",
            data:{id:1},
            type:'POST',
            success:function(data){
                console.log(data);
            }
        });
    }

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

     function Do3(){
        $.ajax({
            url:"/index/",
            data:{id:1},
            type:'POST',
            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、模板繼承:{ % extends 'layouts.html' %}
2、自定義方法
'filter':只能傳遞兩個引數,可以在iffor語句中使用
'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加密傳輸協議。
#- 自定義證書 
    - 服務端:建立一對證書
    - 客戶端:必須攜帶證書
#- 購買證書
    - 服務端: 建立一對證書,。。。。
    - 客戶端: 去機構獲取證書,資料加密後發給咱們的服務單
    - 證書機構:公鑰給改機構

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則不可訪問

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        #儲存請求上下文物件和app上下文物件

為什麼要Flask把Local物件中的的值stack 維護成一個列表?

# 因為通過維護成列表,可以實現一個棧的資料結構,進棧出棧時只取一個數據,巧妙的簡化了問題。
# 還有,在多app應用時,可以實現資料隔離;列表裡不會加資料,而是會生成一個新的列表
# local是一個字典,字典裡key(stack)是唯一標識,value是一個列表

Flask中多app應用是怎麼完成?

請求進來時,可以根據URL的不同,交給不同的APP處理。藍圖也可以實現。
#app1 = Flask('app01')
#app2 = Flask('app02')
#@app1.route('/index')
#@app2.route('/index2')
原始碼中在DispatcherMiddleware類裡呼叫app2.__call__,
  原理其實就是URL分割,然後將請求分發給指定的app。
之後app也按單app的流程走。就是從app.__call__走

在Flask中實現WebSocket需要什麼元件?

 gevent-websocket

wtforms元件的作用?

#快速建立前端標籤、文字校驗;如django的ModelForm

Flask框架預設session處理機制?

# 前提:
    不熟的話:記不太清了,應該是……分兩個階段吧   
# 建立:
    當請求剛進來的時候,會將request和session封裝成一個RequestContext()物件,
    接下來把這個物件通過LocalStack()放入內部的一個Local()物件中;
   因為剛開始 Local 的ctx中session是空的;
   所以,接著執行open_session,將cookie 裡面的值拿過來,重新賦值到ctx中
    (Local實現對資料隔離,類似threading.local) 
# 銷燬:
    最後返回時執行 save_session() 將ctx 中的session讀出來進行序列化,寫到cookie
    然後給使用者,接著把 ctx pop掉

解釋Flask框架中的Local物件和threading.local物件的區別?

# a.threading.local
作用:為每個執行緒開闢一塊空間進行資料儲存(資料隔離)。

問題:自己通過字典建立一個類似於threading.local的東西。
storage = {
   4740: {val: 0},
   4732: {val: 1},
   4731: {val: 3},
   }

# b.自定義Local物件
作用:為每個執行緒(協程)開闢一塊空間進行資料儲存(資料隔離)。
class Local(object):
   def __init__(self):
      object.__setattr__(self, 'storage', {})
   def __setattr__(self, k, v):
      ident = get_ident()
      if ident in self.storage:
         self.storage[ident][k] = v
      else:
         self.storage[ident] = {k: v}
   def __getattr__(self, k):
      ident = get_ident()
      return self.storage[ident][k]
obj = Local()
def task(arg):
   obj.val = arg
   obj.xxx = arg
   print(obj.val)
for i in range(10):
   t = Thread(target=task, args=(i,))
   t.start()

Flask中 blinker 是什麼?

# flask中的訊號blinker
訊號主要是讓開發者可是在flask請求過程中定製一些行為。
或者說flask在列表裡面預留了幾個空列表,在裡面存東西。
簡言之,訊號允許某個'傳送者'通知'接收者'有事情發生了

@before_request返回值,blinker沒有返回值

# 10個訊號

request_started = _signals.signal('request-started') #請求到來前執行

request_finished = _signals.signal('request-finished') #請求結束後執行

before_render_template = _signals.signal('before-render-template')#模板渲染前執行

template_rendered = _signals.signal('template-rendered')#模板渲染後執行

got_request_exception = _signals.signal('got-request-exception') #請求執行出現異常時執行

request_tearing_down = _signals.signal('request-tearing-down')#請求執行完畢後自動執行(無論成功與否)

appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 請求上下文執行完畢後自動執行(無論成功與否)

appcontext_pushed = _signals.signal('appcontext-pushed') #請求app上下文push時執行

appcontext_popped = _signals.signal('appcontext-popped') #請求上下文pop時執行

message_flashed = _signals.signal('message-flashed')#呼叫flask在其中新增資料時,自動觸發

SQLAlchemy中的 session和scoped_session 的區別?

# Session:
由於無法提供執行緒共享功能,開發時要給每個執行緒都建立自己的session
列印sesion可知他是sqlalchemy.orm.session.Session的物件
# scoped_session:
為每個執行緒都建立一個session,實現支援執行緒安全
在整個程式執行的過程當中,只存在唯一的一個session物件。
建立方式:
   通過本地執行緒Threading.Local()
   # session=scoped_session(Session)
   建立唯一標識的方法(參考flask請求原始碼)

SQLAlchemy如何執行原生SQL?

# 使用execute方法直接操作SQL語句(匯入create_engin、sessionmaker)
engine=create_engine('mysql://root:*****@127.0.0.1/database?charset=utf8')
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
session.execute('alter table mytablename drop column mycolumn ;')

ORM的實現原理?

# ORM的實現基於一下三點
對映類:描述資料庫表結構,
對映檔案:指定資料庫表和對映類之間的關係
資料庫配置檔案:指定與資料庫連線時需要的連線資訊(資料庫、登入使用者名稱、密碼or連線字串)

DBUtils模組的作用?

# 資料庫連線池
使用模式:
1、為每個執行緒建立一個連線,連線不可控,需要控制執行緒數
2、建立指定數量的連線在連線池,當執行緒訪問的時候去取,不夠了執行緒排隊,直到有人釋放(推薦)
---------------------------------------------------------------------------
兩種寫法:
1、用靜態方法裝飾器,通過直接執行類的方法來連線使用資料庫
2、通過例項化物件,通過物件來呼叫方法執行語句
https://www.cnblogs.com/ArmoredTitan/p/Flask.html

以下SQLAlchemy的欄位是否正確?如果不正確請更正:

fromdatetimeimportdatetime

fromsqlalchemy.ext.declarative

importdeclarative_base

fromsqlalchemyimportColumn, Integer, String, DateTime





Base=declarative_base()



classUserInfo(Base):


__tablename__='userinfo'

id=Column(Integer, primary_key=True, autoincrement=True)


name=Column(String(64), unique=True)


ctime=Column(DateTime, default=datetime.now())

from datetime import datetime
from sqlalchemy.ext.declarative
import declarative_base
from sqlalchemy import Column, Integer, String, DateTime

Base = declarative_base()
class UserInfo(Base):
    __tablename__ = 'userinfo'   
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), unique=True)
ctime = Column(DateTime, default=datetime.now())
-----------------------------------------------------------------------
不正確:
    Ctime欄位中引數應為’default=datetime.now’
    now 後面不應該加括號,加了的話,欄位不會實時更新。

SQLAchemy中如何為表設定引擎和字元編碼?

sqlalchemy設定編碼字符集,一定要在資料庫訪問的URL上增加'charset=utf8'
否則資料庫的連線就不是'utf8'的編碼格式

eng=create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)
1. 設定引擎編碼方式為utf8。

    engine = create_engine("mysql+pymysql://root:[email protected]:3306/sqldb01?charset=utf8")
2. 設定資料庫表編碼方式為utf8

class UserType(Base):
    __tablename__ = 'usertype'
    id = Column(Integer, primary_key=True)
    caption = Column(String(50), default='管理員')
    # 新增配置設定編碼
    __table_args__ = {
        'mysql_charset':'utf8'
    }

這樣生成的SQL語句就自動設定資料表編碼為utf8了,__table_args__還可設定儲存引擎、外來鍵約束等等資訊。

SQLAchemy中如何設定聯合唯一索引?

通過'UniqueConstraint'欄位來設定聯合唯一索引
__table_args=(UniqueConstraint('h_id','username',name='_h_username_uc'))
#h_id和username組成聯合唯一約束

簡述Tornado框架的特點。

非同步非阻塞+websocket

簡述Tornado框架中Future物件的作用?

# 實現非同步非阻塞
檢視函式yield一個futrue物件,futrue物件預設:
    self._done = False   ,請求未完成
    self._result = None  ,請求完成後返回值,用於傳遞給回撥函式使用。

tornado就會一直去檢測futrue物件的_done是否已經變成True。

如果IO請求執行完畢,自動會呼叫future的set_result方法:
            self._result = result
            self._done = True
參考:http://www.cnblogs.com/wupeiqi/p/6536518.html(自定義非同步非阻塞web框架)

Tornado框架中如何編寫WebSocket程式?

Tornado在websocket模組中提供了一個WebSocketHandler類。
這個類提供了和已連線的客戶端通訊的WebSocket事件和方法的鉤子。
當一個新的WebSocket連線開啟時,open方法被呼叫,
而on_message和on_close方法,分別在連線、接收到新的訊息和客戶端關閉時被呼叫。

此外,WebSocketHandler類還提供了write_message方法用於向客戶端傳送訊息,close方法用於關閉連線。

Tornado中靜態檔案是如何處理的?
如: <link href="{{static_url("commons.css")}}" rel="stylesheet" />

# settings.py
settings = {
    "static_path": os.path.join(os.path.dirname(__file__), "static"),
   # 指定了靜態檔案的位置在當前目錄中的"static"目錄下
    "cookie_secret": "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
    "login_url": "/login",
    "xsrf_cookies": True,
}

經上面配置後
static_url()自動去配置的路徑下找'commons.css'檔案

Tornado操作MySQL使用的模組?

torndb
torndb是基於mysqldb的再封裝,所以使用時要先安裝myqldb

Tornado操作redis使用的模組?

tornado-redis

簡述Tornado框架的適用場景?

web聊天室,線上投票

git常見命令作用:

# git init
    初始化,當前所在的資料夾可以被管理且以後版本相關的資料都會儲存到.git檔案中
# git status
    檢視當前資料夾以及子目錄中檔案是否發生變化:
    內容修改/新增檔案/刪除,已經變化的檔案會變成紅色,已經add的檔案會變成綠色
# git add .
    給發生變化的檔案(貼上一個標籤)或 將發生變化的檔案放到某個地方,
    只寫一個句點符就代表把git status中紅色的檔案全部打上標籤
# git commit -m
    新增使用者登入認證功能以及xxx功能將“綠色”檔案新增到版本中
# git log
    檢視所有版本提交記錄,可以獲取版本號
# git reset --hard 版本號   
    將最新的版本回退到更早的版本
# git reflog   
    回退到之前版本後悔了,再更新到最新或者最新之前的版本
# git reset --hard 版本 回退

簡述以下git中stash命令作用以及相關其他命令。

'git stash':將當前工作區所有修改過的內容儲存到“某個地方”,將工作區還原到當前版本未修改過的狀態
'git stash list':檢視“某個地方”儲存的所有記錄
'git stash clear':清空“某個地方”
'git stash pop':將第一個記錄從“某個地方”重新拿到工作區(可能有衝突)
'git stash apply':編號, 將指定編號記錄從“某個地方”重新拿到工作區(可能有衝突) 
'git stash drop':編號,刪除指定編號的記錄

git 中 merge 和 rebase命令 的區別。

merge:
會將不同分支的提交合併成一個新的節點,之前的提交分開顯示,
注重歷史資訊、可以看出每個分支資訊,基於時間點,遇到衝突,手動解決,再次提交
rebase:
將兩個分支的提交結果融合成線性,不會產生新的節點;
注重開發過程,遇到衝突,手動解決,繼續操作

公司如何基於git做的協同開發?

1、你們公司的程式碼review分支怎麼做?誰來做?
答:組長建立review分支,我們小功能開發完之後,合併到review分支交給老大(小組長)來看,
1.1、你組長不開發程式碼嗎?
        他開發程式碼,但是它只開發核心的東西,任務比較少。
        或者抽出時間,我們一起做這個事情
2、你們公司協同開發是怎麼協同開發的?
每個人都有自己的分支,階段性程式碼完成之後,合併到review,然後交給老大看
--------------------------------------------------------------------------
# 大致工作流程
公司:
    下載程式碼
        git clone https://gitee.com/wupeiqi/xianglong.git
        或建立目錄 
        cd 目錄 
        git init 
        git remote add origin https://gitee.com/wupeiqi/xianglong.git
        git pull origin maste 
    建立dev分支
        git checkout dev 
        git pull origin dev 
        繼續寫程式碼
        git add . 
        git commit -m '提交記錄'
        git push origin dev 
回家: 
    拉程式碼:
        git pull origin dev 
    繼續寫:
        繼續寫程式碼
        git add . 
        git commit -m '提交記錄'
        git push origin dev 

如何基於git實現程式碼review?

https://blog.csdn.net/june_y/article/details/50817993

git如何實現v1.0 、v2.0 等版本的管理?

在命令列中,使用“git tag –a tagname –m “comment”可以快速建立一個標籤。
需要注意,命令列建立的標籤只存在本地Git庫中,還需要使用Git push –tags指令釋出到伺服器的Git庫中

什麼是gitlab

gitlab是公司自己搭建的專案程式碼託管平臺

github和gitlab的區別?

1、gitHub是一個面向開源及私有軟體專案的託管平臺
(建立私有的話,需要購買,最低階的付費為每月7刀,支援5個私有專案)
2、gitlab是公司自己搭建的專案託管平臺

如何為github上牛逼的開源專案貢獻程式碼?

1、fork需要協作專案
2、克隆/關聯fork的專案到本地
3、新建分支(branch)並檢出(checkout)新分支
4、在新分支上完成程式碼開發
5、開發完成後將你的程式碼合併到master分支
6、新增原作者的倉庫地址作為一個新的倉庫地址
7、合併原作者的master分支到你自己的master分支,用於和作者倉庫程式碼同步
8、push你的本地倉庫到GitHub
9、在Github上提交 pull requests
10、等待管理員(你需要貢獻的開源專案管理員)處理

git中 .gitignore檔案的作用

一般來說每個Git專案中都需要一個“.gitignore”檔案,
這個檔案的作用就是告訴Git哪些檔案不需要新增到版本管理中。

實際專案中,很多檔案都是不需要版本管理的,比如Python的.pyc檔案和一些包含密碼的配置檔案等等。

什麼是敏捷開發?

'敏捷開發':是一種以人為核心、迭代、循序漸進的開發方式。

它並不是一門技術,而是一種開發方式,也就是一種軟體開發的流程。
它會指導我們用規定的環節去一步一步完成專案的開發。
因為它採用的是迭代式開發,所以這種開發方式的主要驅動核心是人

簡述 jenkins 工具的作用?

'Jenkins'是一個可擴充套件的持續整合引擎。

主要用於:
   持續、自動地構建/測試軟體專案。
   監控一些定時執行的任務。

公司如何實現程式碼釋出?

nginx+uwsgi+django

簡述 RabbitMQ、Kafka、ZeroMQ的區別?

https://blog.csdn.net/zhailihua/article/details/7899006

RabbitMQ如何在消費者獲取任務後未處理完前就掛掉時,保證資料不丟失?

為了預防訊息丟失,rabbitmq提供了ack
即工作程序在收到訊息並處理後,傳送ack給rabbitmq,告知rabbitmq這時候可以把該訊息從佇列中刪除了。
如果工作程序掛掉 了,rabbitmq沒有收到ack,那麼會把該訊息 重新分發給其他工作程序。
不需要設定timeout,即使該任務需要很長時間也可以處理。

ack預設是開啟的,工作程序顯示指定了no_ack=True

RabbitMQ如何對訊息做持久化?

1、建立佇列和傳送訊息時將設定durable=Ture,如果在接收到訊息還沒有儲存時,訊息也有可能丟失,就必須配置publisher confirm
    channel.queue_declare(queue='task_queue', durable=True)

2、返回一個ack,程序收到訊息並處理完任務後,發給rabbitmq一個ack表示任務已經完成,可以刪除該任務

3、映象佇列:將queue映象到cluster中其他的節點之上。
在該實現下,如果叢集中的一個節點失效了,queue能自動地切換到映象中的另一個節點以保證服務的可用性

RabbitMQ如何控制訊息被消費的順序?

預設訊息佇列裡的資料是按照順序被消費者拿走,
例如:消費者1 去佇列中獲取奇數序列的任務,消費者2去佇列中獲取偶數序列的任務。

channel.basic_qos(prefetch_count=1) 
表示誰來誰取,不再按照奇偶數排列(同時也保證了公平的消費分發)

以下RabbitMQ的exchange type分別代表什麼意思?如:fanout、direct、topic。

amqp協議中的核心思想就是生產者和消費者隔離,生產者從不直接將訊息傳送給佇列。
生產者通常不知道是否一個訊息會被髮送到佇列中,只是將訊息傳送到一個交換機。
先由Exchange來接收,然後Exchange按照特定的策略轉發到Queue進行儲存。
同理,消費者也是如此。Exchange 就類似於一個交換機,轉發各個訊息分發到相應的佇列中。
--------------------------------------------------
type=fanout 類似釋出者訂閱者模式,會為每一個訂閱者建立一個佇列,而釋出者釋出訊息時,會將訊息放置在所有相關佇列中
type=direct 佇列繫結關鍵字,傳送者將資料根據關鍵字傳送到訊息exchange,exchange根據 關鍵字 判定應該將資料傳送至指定佇列。
type=topic  佇列繫結幾個模糊的關鍵字,之後傳送者將資料傳送到exchange,exchange將傳入”路由值“和 ”關鍵字“進行匹配,匹配成功,
則將資料傳送到指定佇列。
--------------------------------------------------- 傳送者路由值 佇列中 old.boy.python old.* -- 不匹配 *表示匹配一個 old.boy.python old.# -- 匹配 #表示匹配0個或多個

簡述 celery 是什麼以及應用場景?

# Celery是由Python開發的一個簡單、靈活、可靠的處理大量任務的分發系統,
# 它不僅支援實時處理也支援任務排程。
# http://www.cnblogs.com/wupeiqi/articles/8796552.html

簡述celery執行機制。

celery如何實現定時任務?

# celery實現定時任務
啟用Celery的定時任務需要設定CELERYBEAT_SCHEDULE 。 
CELERYBEAT_SCHEDULE='djcelery.schedulers.DatabaseScheduler'#定時任務
'建立定時任務'
# 通過配置CELERYBEAT_SCHEDULE:
#每30秒呼叫task.add
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
    'add-every-30-seconds': {
        'task': 'tasks.add',
        'schedule': timedelta(seconds=30),
        'args': (16, 16)
    },
}

簡述 celery多工結構目錄

pro_cel
    ├── celery_tasks     # celery相關資料夾
    │   ├── celery.py    # celery連線和配置相關檔案
    │   └── tasks.py     #  所有任務函式
    ├── check_result.py  # 檢查結果
    └── send_task.py     # 觸發任務

celery中裝飾器 @app.task 和 @shared_task的區別?

# 一般情況使用的是從celeryapp中引入的app作為的裝飾器:@app.task
# django那種在app中定義的task則需要使用@shared_task

簡述 requests模組的作用及基本使用?

# 作用:
使用requests可以模擬瀏覽器的請求
# 常用引數:
   url、headers、cookies、data
   json、params、proxy
# 常用返回值:
   content
   iter_content
   text 
   encoding="utf-8"
   cookie.get_dict()

簡述 beautifulsoup模組的作用及基本使用?

# BeautifulSoup
用於從HTML或XML檔案中提取、過濾想要的資料形式
#常用方法
解析:html.parser 或者 lxml(需要下載安裝) 
   find、find_all、text、attrs、get 

簡述 seleninu模組的作用及基本使用?

Selenium是一個用於Web應用程式測試的工具,
他的測試直接執行在瀏覽器上,模擬真實使用者,按照程式碼做出點選、輸入、開啟等操作

爬蟲中使用他是為了解決requests無法解決javascript動態問題

scrapy框架中各元件的工作流程?

#1、生成初始的Requests來爬取第一個URLS,並且標識一個回撥函式
第一個請求定義在start_requests()方法內預設從start_urls列表中獲得url地址來生成Request請求,
預設的回撥函式是parse方法。回撥函式在下載完成返回response時自動觸發
#2、在回撥函式中,解析response並且返回值
返回值可以4種:
    a、包含解析資料的字典
    b、Item物件
    c、新的Request物件(新的Requests也需要指定一個回撥函式)
    d、或者是可迭代物件(包含Items或Request)
#3、在回撥函式中解析頁面內容
通常使用Scrapy自帶的Selectors,但很明顯你也可以使用Beutifulsoup,lxml或其他你愛用啥用啥。
#4、最後,針對返回的Items物件將會被持久化到資料庫
    通過Item Pipeline元件存到資料庫
    或者匯出到不同的檔案(通過Feed exports)
http://www.cnblogs.com/wupeiqi/articles/6229292.html

在scrapy框架中如何設定代理(兩種方法)?

方式一:內建新增代理功能
# -*- coding: utf-8 -*-
import os
import scrapy
from scrapy.http import Request

class ChoutiSpider(scrapy.Spider):
    name = 'chouti'
    allowed_domains = ['chouti.com']
    start_urls = ['https://dig.chouti.com/']

    def start_requests(self):
        os.environ['HTTP_PROXY'] = "http://192.168.11.11"

        for url in self.start_urls:
            yield Request(url=url,callback=self.parse)

    def parse(self, response):
        print(response)

方式二:自定義下載中介軟體
import random
import base64
import six
def to_bytes(text, encoding=None, errors='strict'):
    """Return the binary representation of `text`. If `text`
    is already a bytes object, return it as-is."""
    if isinstance(text, bytes):
        return text
    if not isinstance(text, six.string_types):
        raise TypeError('to_bytes must receive a unicode, str or bytes '
                        'object, got %s' % type(text).__name__)
    if encoding is None:
        encoding = 'utf-8'
    return text.encode(encoding, errors)
    
class MyProxyDownloaderMiddleware(object):
    def process_request(self, request, spider):
        proxy_list = [
            {'ip_port': '111.11.228.75:80', 'user_pass': 'xxx:123'},
            {'ip_port': '120.198.243.22:80', 'user_pass': ''},
            {'ip_port': '111.8.60.9:8123', 'user_pass': ''},
            {'ip_port': '101.71.27.120:80', 'user_pass': ''},
            {'ip_port': '122.96.59.104:80', 'user_pass': ''},
            {'ip_port': '122.224.249.122:8088', 'user_pass': ''},
        ]
        proxy = random.choice(proxy_list)
        if proxy['user_pass'] is not None:
            request.meta['proxy'] = to_bytes("http://%s" % proxy['ip_port'])
            encoded_user_pass = base64.encodestring(to_bytes(proxy['user_pass']))
            request.headers['Proxy-Authorization'] = to_bytes('Basic ' + encoded_user_pass)
        else:
            request.meta['proxy'] = to_bytes("http://%s" % proxy['ip_port'])



配置:
    DOWNLOADER_MIDDLEWARES = {
       # 'xiaohan.middlewares.MyProxyDownloaderMiddleware': 543,
    }

scrapy框架中如何實現大檔案的下載?

from twisted.web.client import Agent, getPage, ResponseDone, PotentialDataLoss
from twisted.internet import defer, reactor, protocol
from twisted.web._newclient import Response
from io import BytesIO

class _ResponseReader(protocol.Protocol):
    def __init__(self, finished, txresponse, file_name):
        self._finished = finished
        self._txresponse = txresponse
        self._bytes_received = 0
        self.f = open(file_name, mode='wb')
    def dataReceived(self, bodyBytes):
        self._bytes_received += len(bodyBytes)
        # 一點一點的下載
        self.f.write(bodyBytes)
        self.f.flush()
    def connectionLost(self, reason):
        if self._finished.called:
            return
        if reason.check(ResponseDone):
            # 下載完成
            self._finished.callback((self._txresponse, 'success'))
        elif reason.check(PotentialDataLoss):
            # 下載部分
            self._finished.callback((self._txresponse, 'partial'))
        else:
            # 下載異常
            self._finished.errback(reason)
        self.f.close()

scrapy中如何實現限速?

http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/autothrottle.html

scrapy中如何實現暫停爬蟲?

# 有些情況下,例如爬取大的站點,我們希望能暫停爬取,之後再恢復執行。
# Scrapy通過如下工具支援這個功能:
一個把排程請求儲存在磁碟的排程器
一個把訪問請求儲存在磁碟的副本過濾器[duplicates filter]
一個能持續保持爬蟲狀態(鍵/值對)的擴充套件
Job 路徑
要啟用持久化支援,你只需要通過 JOBDIR 設定 job directory 選項。
這個路徑將會儲存所有的請求資料來保持一個單獨任務的狀態(例如:一次spider爬取(a spider run))。
必須要注意的是,這個目錄不允許被不同的spider 共享,甚至是同一個spider的不同jobs/runs也不行。
也就是說,這個目錄就是儲存一個 單獨 job的狀態資訊。

scrapy中如何進行自定製命令

在spiders同級建立任意目錄,如:commands
在其中建立'crawlall.py'檔案(此處檔名就是自定義的命令)
from scrapy.commands import ScrapyCommand
    from scrapy.utils.project import get_project_settings
    class Command(ScrapyCommand):
        requires_project = True
        def syntax(self):
            return '[options]'
        def short_desc(self):
            return 'Runs all of the spiders'
        def run(self, args, opts):
            spider_list = self.crawler_process.spiders.list()
            for name in spider_list:
                self.crawler_process.crawl(name, **opts.__dict__)
            self.crawler_process.start()
在'settings.py'中新增配置'COMMANDS_MODULE = '專案名稱.目錄名稱''
在專案目錄執行命令:'scrapy crawlall' 

scrapy中如何實現的記錄爬蟲的深度?

'DepthMiddleware'是一個用於追蹤每個Request在被爬取的網站的深度的中介軟體。 
其可以用來限制爬取深度的最大深度或類似的事情。
'DepthMiddleware'可以通過下列設定進行配置(更多內容請參考設定文件):

'DEPTH_LIMIT':爬取所允許的最大深度,如果為0,則沒有限制。
'DEPTH_STATS':是否收集爬取狀態。
'DEPTH_PRIORITY':是否根據其深度對requet安排優先

scrapy中的pipelines工作原理?

Scrapy 提供了 pipeline 模組來執行儲存資料的操作。
在建立的 Scrapy 專案中自動建立了一個 pipeline.py 檔案,同時建立了一個預設的 Pipeline 類。
我們可以根據需要自定義 Pipeline 類,然後在 settings.py 檔案中進行配置即可

scrapy的pipelines如何丟棄一個item物件?

通過raise DropItem()方法

簡述scrapy中爬蟲中介軟體和下載中介軟體的作用?1

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

scrapy-redis元件的作用?

實現了分散式爬蟲,url去重、排程器、資料持久化
'scheduler'排程器
'dupefilter'URL去重規則(被排程器使用)
'pipeline'資料持久化

scrapy-redis元件中如何實現的任務的去重?

a. 內部進行配置,連線Redis
b.去重規則通過redis的集合完成,集合的Key為:
key = defaults.DUPEFILTER_KEY % {'timestamp': int(time.time())}
預設配置:
DUPEFILTER_KEY = 'dupefilter:%(timestamp)s'
c.去重規則中將url轉換成唯一標示,然後在redis中檢查是否已經在集合中存在
from scrapy.utils import request
from scrapy.http import Request
req = Request(url='http://www.cnblogs.com/wupeiqi.html')
result = request.request_fingerprint(req)
print(result) # 8ea4fd67887449313ccc12e5b6b92510cc53675c

scrapy和scrapy-redis的去重規則(原始碼)
1. scrapy中去重規則是如何實現?
class RFPDupeFilter(BaseDupeFilter):
    """Request Fingerprint duplicates filter"""

    def __init__(self, path=None, debug=False):
        self.fingerprints = set()
        

    @classmethod
    def from_settings(cls, settings):
        debug = settings.getbool('DUPEFILTER_DEBUG')
        return cls(job_dir(settings), debug)

    def request_seen(self, request):
        # 將request物件轉換成唯一標識。
        fp = self.request_fingerprint(request)
        # 判斷在集合中是否存在,如果存在則返回True,表示已經訪問過。
        if fp in self.fingerprints:
            return True
        # 之前未訪問過,將url新增到訪問記錄中。
        self.fingerprints.add(fp)

    def request_fingerprint(self, request):
        return request_fingerprint(request)

        
2. scrapy-redis中去重規則是如何實現?
class RFPDupeFilter(BaseDupeFilter):
    """Redis-based request duplicates filter.

    This class can also be used with default Scrapy's scheduler.

    """

    logger = logger

    def __init__(self, server, key, debug=False):
        
        # self.server = redis連線
        self.server = server
        # self.key = dupefilter:123912873234
        self.key = key
        

    @classmethod
    def from_settings(cls, settings):
        
        # 讀取配置,連線redis
        server = get_redis_from_settings(settings)

        #  key = dupefilter:123912873234
        key = defaults.DUPEFILTER_KEY % {'timestamp': int(time.time())}
        debug = settings.getbool('DUPEFILTER_DEBUG')
        return cls(server, key=key, debug=debug)

    @classmethod
    def from_crawler(cls, crawler):
        
        return cls.from_settings(crawler.settings)

    def request_seen(self, request):
        
        fp = self.request_fingerprint(request)
        # This returns the number of values added, zero if already exists.
        # self.server=redis連線
        # 新增到redis集合中:1,新增工程;0,已經存在
        added = self.server.sadd(self.key, fp)
        return added == 0

    def request_fingerprint(self, request):
        
        return request_fingerprint(request)

    def close(self, reason=''):
        
        self.clear()

    def clear(self):
        """Clears fingerprints data."""
        self.server.delete(self.key)

scrapy-redis的排程器如何實現任務的深度優先和廣度優先?....

簡述 vitualenv 及應用場景?

'vitualenv'是一個獨立的python虛擬環境
如:
   當前專案依賴的是一個版本,但是另一個專案依賴的是另一個版本,這樣就會造成依賴衝突,
   而virtualenv就是解決這種情況的,virtualenv通過建立一個虛擬化的python執行環境,
   將我們所需的依賴安裝進去的,不同專案之間相互不干擾

簡述 pipreqs 及應用場景?

可以通過對專案目錄掃描,自動發現使用了那些類庫,並且自動生成依賴清單。

pipreqs ./ 生成requirements.txt

在Python中使用過什麼程式碼檢查工具?

1)PyFlakes:靜態檢查Python程式碼邏輯錯誤的工具。
2)Pep8: 靜態檢查PEP8編碼風格的工具。
3)NedBatchelder’s McCabe script:靜態分析Python程式碼複雜度的工具。
Python程式碼分析工具:PyChecker、Pylint

簡述 saltstack、ansible、fabric、puppet工具的作用?

B Tree和B+ Tree的區別?

1.B樹中同一鍵值不會出現多次,並且有可能出現在葉結點,也有可能出現在非葉結點中。
  而B+樹的鍵一定會出現在葉結點中,並有可能在非葉結點中重複出現,以維持B+樹的平衡。
2.因為B樹鍵位置不定,且在整個樹結構中只出現一次,

請列舉常見排序並通過程式碼實現任意三種。

冒泡/選擇/插入/快排

https://www.cnblogs.com/Liqiongyu/p/5911613.html

http://www.cnblogs.com/feixuelove1009/p/6143539.html

請列舉常見查詢並通過程式碼實現任意三種。

無序查詢、二分查詢、插值查詢

請列舉你熟悉的設計模式

工廠模式/單例模式等

有沒有刷過leetcode?

leetcode是個題庫,裡面有多很程式設計題目,可以線上編譯執行。

https://leetcode-cn.com/problemset/all/

列舉熟悉的的Linux命令。

1建立目錄
mkdir /data
cd /
mkdir data


2:檢視目錄
ls 
ls -l  顯示詳細資訊

公司線上伺服器是什麼系統?

Linux/Centos

解釋 PV、UV 的含義?

PV訪問量(Page View),即頁面訪問量,每開啟一次頁面PV計數+1,重新整理頁面也是。
UV訪問數(Unique Visitor)指獨立訪客訪問數,一臺電腦終端為一個訪客。

解釋 QPS的含義?

'QPS(Query Per Second)'
每秒查詢率,是對一個特定的查詢伺服器在規定時間內所處理流量多少的衡量標準

uwsgi和wsgi的區別?

wsgi是一種通用的介面標準或者介面協議,實現了python web程式與伺服器之間互動的通用性。

uwsgi:同WSGI一樣是一種通訊協議
uwsgi協議是一個'uWSGI伺服器'自有的協議,它用於定義傳輸資訊的型別,
'uWSGI'是實現了uwsgi和WSGI兩種協議的Web伺服器,負責響應python的web請求。

supervisor的作用?

# Supervisor:
是一款基於Python的程序管理工具,可以很方便的管理伺服器上部署的應用程式。
是C/S模型的程式,其服務端是supervisord服務,客戶端是supervisorctl命令

# 主要功能:
1 啟動、重啟、關閉包括但不限於python程序。
2 檢視程序的執行狀態。
3 批量維護多個程序。

什麼是反向代理?

正向代理代理客戶端(客戶端找喲個代理去訪問伺服器,伺服器不知道你的真實IP)
反向代理代理伺服器(伺服器找一個代理給你響應,你不知道伺服器的真實IP)

簡述SSH的整個過程。

SSH 為 'Secure Shell' 的縮寫,是建立在應用層基礎上的安全協議。
SSH 是目前較可靠,為遠端登入會話和其他網路服務提供的安全性協議。
利用 SSH 協議可以有效防止遠端管理過程中的資訊洩露問題。

有問題都去那些找解決方案?

起初是百度,發現搜到的答案不精準,淨廣告
轉戰谷歌,但牆了;搗鼓怎麼FQ

還會去知乎、stackoverfloow、必應、思否(segmentfault)

是否有關注什麼技術類的公眾號?

python之禪(主要專注Python相關知識,作者:劉志軍)
碼農翻身(主要是Java的,但不光是java,涵蓋面很廣,作者:劉欣)
實驗樓(線上練專案)
and so on

最近在研究什麼新技術?

Numpy
pandas(金融量化分析、聚寬)
百度AI
圖靈API
智慧玩具

是否瞭解過領域驅動模型

Domain-Driven Design

回到頂部

回到頂部

二進位制與十進位制之間的轉換

1、十進位制 與 二進位制之間的轉換
(1)、十進位制轉換為二進位制,分為整數部分和小數部分

整數部分

方法:除2取餘法,即每次將整數部分除以2,餘數為該位權上的數,而商繼續除以2,餘數又為上一個位權上的數。
這個步驟一直持續下去,直到商為0為止,最後讀數時候,從最後一個餘數讀起,一直到最前面的一個餘數。下面舉例:

例:將十進位制的168轉換為二進位制
得出結果 將十進位制的168轉換為二進位制,(10101000)2
168 / 2 = 84 -- 0
84 / 2 = 42 -- 0
42 / 2 = 21 -- 0
21 / 2 = 10 -- 1
10 / 2 = 5 -- 0
 5 / 2 = 2 -- 1
2 / 2 = 1 -- 0
1 / 2 = 0 -- 1
二進位制(從後往前讀): 10101000

小數部分

方法:乘2取整法,即將小數部分乘以2,然後取整數部分,剩下的小數部分繼續乘以2,然後取整數部分,
剩下的小數部分又乘以2,一直取到小數部分為零為止。如果永遠不能為零,就同十進位制數的四捨五入一樣,
按照要求保留多少位小數時,就根據後面一位是0還是1,取捨,如果是零,舍掉,如果是1,向入一位。
換句話說就是0舍1入。讀數要從前面的整數讀到後面的整數
 例1:將0.125換算為二進位制 
得出結果:將0.125換算為二進位制(0.001)2 
分析:第一步,將0.125乘以2,得0.25,則整數部分為0,小數部分為0.25; 
第二步, 將小數部分0.25乘以2,得0.5,則整數部分為0,小數部分為0.5; 
第三步, 將小數部分0.5乘以2,得1.0,則整數部分為1,小數部分為0.0;
第四步,讀數,從第一位讀起,讀到最後一位,即為0.001。 
取整數位 
0.125 * 2 = 0.25 -- 0 
0.25 * 2 = 0.5 -- 0 
0.5 * 2 = 1.0 -- 1 
二進位制:0.001 
例2:將0.45轉換為二進位制(保留到小數點第四位) 
0.45 保留小數點4第四位 
0.45 * 2 = 0.9 -- 0 
0.9 * 2 = 1.8 -- 1
0.8 * 2 = 1.6 -- 1 
0.6 * 2 = 1.2 -- 1
 二進位制(從前往後讀):0.0111
小數部分

二進位制轉換為十進位制 (不分整數和小數部分)

方法:按權相加法,即將二進位制每位上的數乘以權,然後相加之和即是十進位制數。

例:將二進位制數101.101轉換為十進位制數。 
得出結果:(101.101)2=(5.625)10 
在做二進位制轉換成十進位制需要注意的是 
1)要知道二進位制每位的權值 
2)要能求出每位的值 101.101 轉換為十進位制 
整數部分:2^2 + 2^0 = 5 
小數部分:2^(-1) + 2^(-3) = 1/2 + 1/8 = 0.5 + 0.125 = 0.625 
十進位制: 2^2 + 2^0 + 2^(-1) + 2^(-3) = 5.625