Python基礎知識資料收集庫

對於開始想輸出 “Hello 世界”  的用戶,以下資料值得珍藏^~^

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,而是通過網絡調用來交互,確保各程序之間的獨
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中多個庫,
空格的使用

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

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


# 十進制轉換成二進制--->bin
v2 = 18
print(bin(int(v2)))
# 0b10010

# 八進制轉換成十進制
v3 = "011"
print(int(v3))
# 11

# 十進制轉換成八進制:---> oct
v4 = 30
print(oct(int(v4)))
# 0o36

# 十六進制轉換成十進制:
v5 = "0x12"
print(int(v5,16))
# 18

# 十進制轉換成十六進制:---> hex
v6 = 87
print(hex(int(v6)))
# 0x57

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

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

         3            00000011

         9            00001001

        12            00001100

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

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():
    return (lambda x:i*x for i in range(4))         #返回一個生成器表達式
print([m(2) for m in multipliers()])
-面試題2:
現有兩個元組(('a'),('b')),(('c'),('d')),請使用python中匿名函數生成列表[{'a':'c'},{'b':'d'}]

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

31、求結果

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

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

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

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

32、列舉常見的內置函數

abs()

返回數字的絕對值

map

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

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

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

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

filter

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

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

map與filter總結

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

isinstance\type

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

# type() 與 isinstance() 區別
class A:
    pass

class B(A):
    pass

print("isinstance",isinstance(A(),A))   # isinstance True
print("type",type(A())  == A)    # type True

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

zip 拉鍊函數

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

reduce

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

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

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

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

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

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

33. filter、map、reduce的作用?

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

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

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

# 例子:
# abs() 函數返回數字的絕對值
# 新的內容的個數等於原內容的個數
# ret = map(abs,[-1,-5,6,-7])
# print(list(ret))
# [1, 5, 6, 7]

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

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

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

# 篩選大於10的數
def is_odd(x):
    if x>10:
        return True

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

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

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

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

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

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

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

34、 一行代碼實現9*9乘法表

print('\n'.join([' '.join(['%s*%s=%-2s' % (j, i, i * j) for j in range(1, i + 1)]) for i in range(1, 10)]))

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

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

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

36、 常用模塊都有那些?

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

爬蟲裏面的requests/beautifulsoup4(bs4)

37. re的match和search區別?

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

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

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

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

39. 求結果:

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

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

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

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

40. 求結果:

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

>>> 1 or 2
1
>>> 1 and 2
2
>>> 1 < (2==2)
False
>>> 1 < 2 == 2
True

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

def func(a,b = []):
    b.append(1)
    print(a,b)

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


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

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

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

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

[int(x) for x in ['1','2','3']]


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

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

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

 補充:


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


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

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

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

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

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

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

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

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

x = 2
def func():
    global x
    x = 1
    return x
func()
print(x)  # 1

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

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

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

49. 請用代碼簡答實現stack

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

'''
class Stack:
    def __init__(self):
        self.items = []

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

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

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

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

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

if __name__ == "__main__":
    stack = Stack()
    stack.push("H")
    stack.push("E")
    stack.push("L")
    print(stack.size())  # 3
    print(stack.peek())  # L 
    print(stack.pop())   # L
    print(stack.pop())   # E
    print(stack.pop())   # H
'''

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

1.佔位符%

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

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

2.format

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

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

迭代器

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

生成器

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

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

可迭代對象

 一個類內部實現__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, return indices of the two numbers such that they add up to a specific target.You may assume that each input would have exactly one solution, and you may not use the same element twice. Example: Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1]

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

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

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

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

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

寫API的時候,繼承GenericAPIView

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

                    # If you want to use object lookups other than pk, set 'lookup_field'.
                    # For more complex lookup requirements override `get_object()`.
                    lookup_field = 'pk'
                    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出來返回給你,整個過程就結束了。

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 

 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" οnclick="XmlGetRequest();" value="Get發送請求" />
    <input type="button" οnclick="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>
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" οnclick="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>

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

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

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

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

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

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

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是通過上下文管理機制

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 
中間件
對所有的請求進行批量處理,在視圖函數執行前後進行自定義操作。
應用:用戶登錄校驗
問題:爲甚麼不使用裝飾器?
如果不使用中間件,就需要給每個視圖函數添加裝飾器,太繁瑣
權限組件:
用戶登錄後,將權限放到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跨域(場景:前後端分離時,本地測試開發時使用)
如果網站之間存在跨域,域名不同,端口不同會導致出現跨域,但凡出現跨域,瀏覽器就會出現同源策略的限制
解決:在我們的服務端給我們響應數據,加上響應頭---> 在中間件加的

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

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

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請求

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" οnclick="Do1();"  value="Do it"/>
<input type="button" οnclick="Do2();"  value="Do it"/>
<input type="button" οnclick="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的作用?

反向解析路由字符串

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

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

simple_tag : 類似函數

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在列表裏面預留了幾個空列表,在裏面存東西。
簡言之,信號允許某個'發送者'通知'接收者'有事情發生了

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的字段是否正確?如果不正確請更正:

fromdatetime importdatetime

fromsqlalchemy.ext.declarative

importdeclarative_base

fromsqlalchemy importColumn, 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章