一、爲何學習Python?javascript
# 由於python相對其餘語言很是優雅簡潔,有着豐富的第三方庫,我感受很強大、很方便; # 還有就是,我感受python簡單易學,生態圈龐大,例如:web開發、爬蟲、人工智能等,並且將來發展趨勢也很不錯。
二、經過什麼途徑學習的Python?php
# 在系裏社團經過學長了解到python 根據我的狀況而定…………
三、Python和Java、PHP、C、C#、C++等其餘語言的對比?css
# Python、PHP是解釋型語言,代碼運行期間逐行翻譯成目標機器碼,下次執行時逐行解釋 # 而C、Java是編譯型語言,編譯後再執行。
一、c,它是現代編輯語言的老一輩了,在現代應用中使用很少,全部大部分語言,寫法都和c語言差很少,經常被用做學習其餘語言的基礎html
二、PHP語言主要適用於網頁編輯,而python適合與各個領域前端
三、c++是面向對象的c語言,因爲偏底層,因此性能很是高,主要用在一個要求高性能的領域vue
四、學習起來python要比java簡單快捷的多,java從c++的系統語言中繼承了許多語法和複雜型,而python的語法很是簡潔,大大提升編寫效率;java
五、python是解釋性語言,不須要額外的編譯過程,而c#必須編譯後才能執行python
六、python程序是開源的,但c#卻不是,python能夠跨平臺 mysql
七、python比c++等這類語言,更容易學習,語法規則簡單,語意化,易讀易懂,容易維護
--------------------- react
四、簡述解釋型和編譯型編程語言?
# 解釋型:邊解釋邊執行(python、PHP) # 編譯型:編譯後再執行(c、Java、C#)
五、Python解釋器種類以及特色?
# CPython:C語言開發的,官方推薦,最經常使用 # IPython:基於CPython之上的交互式解釋器,只是在交互上有加強 # JPython:Java寫的解釋器 # Pypy:Python寫的解釋器,目前執行速度最快的解釋器,採用JIT技術,對Python進行動態編譯 # IronPython:C#寫的解釋器
六、位和字節的關係?
#1字節=8位 #1byte=8bit (數據存儲以字節(Byte)爲單位)
七、b、B、KB、MB、GB 的關係?
1B=8bit 1KB=1024B 1MB=1024KB 1G=1024MB 1T=1024G
八、請至少列舉5個 PEP8 規範(越多越好)。
#一、空格使用 a 各類右括號前不要加空格。 b 逗號、冒號、分號前不要加空格。 c 函數的左括號前不要加空格。如Func(1)。 d 序列的左括號前不要加空格。如list[2]。 e 操做符左右各加一個空格,不要爲了對齊增長空格。 f 函數默認參數使用的賦值符左右省略空格。 g 不要將多句語句寫在同一行,儘管使用‘;’容許。 8 if/for/while語句中,即便執行語句只有一句,也必須另起一行。
六、類的方法第一個參數必須是self,而靜態方法第一個參數必須是cls #二、代碼編排 a 縮進,4個空格,而不是tab鍵 b 每行長度79,換行可以使用反斜槓,最好使用圓括號。 c 類與類之間空兩行 d 方法之間空一行
九、經過代碼實現以下轉換:
二進制轉換成十進制:v = 「0b1111011」 十進制轉換成二進制:v = 18 八進制轉換成十進制:v = 「011」 十進制轉換成八進制:v = 30 十六進制轉換成十進制:v = 「0x12」 十進制轉換成十六進制:v = 87 ################################ v = 0b1111011 print(int(v)) v = 18 print(bin(v)) v = '011' print(int(v)) v = 30 print(oct(v)) v = 0x12 print(int(v)) v = 87 print(hex(v))
十、請編寫一個函數實現將IP地址轉換成一個整數。
如 10.3.9.12 轉換規則爲: 10 00001010 3 00000011 9 00001001 12 00001100 再將以上二進制拼接起來計算十進制結果:00001010 00000011 00001001 00001100 = ?
ip_addr = '192.168.2.10' # transfer ip to int def ip2long(ip): ip_list = ip.split('.') result = 0 for i in range(4): # 0,1,2,3 result = result + int(ip_list[i]) * 256 ** (3 - i) return result long = 3232236042 # transfer int to ip def long2ip(long): floor_list = [] yushu = long for i in reversed(range(4)): # 3,2,1,0 res = divmod(yushu, 256 ** i) floor_list.append(str(res[0])) yushu = res[1] return '.'.join(floor_list) a = long2ip(long) print(a)
十一、python遞歸的最大層數?
Python中默認的遞歸層數約爲998左右(會報錯) 和計算機性能有關係,個人最大數字在3210 - 3220之間浮動
十二、求結果:
v1 = 1 or 3 -- 1 v2 = 1 and 3 -- 3 v3 = 0 and 2 and 1 -- 0 v4 = 0 and 2 or 1 -- 1 v5 = 0 and 2 or 1 or 4 -- 1 v6 = 0 or Flase and 1 -- False ######################## and:先後爲真才爲真 or:有一爲真就爲真 優先級:()>not>and>or 同等優先級下,從左向右
1三、ascii、unicode、utf-八、gbk 區別?
#Ascii: 1個字節 支持英文 #unicode :全部字符(不管中文、英文等)1個字符:4個字節 #gbk : 1個字符,英文1個字節,中文2個字節。 #utf-8 :英文1個字節,歐洲字符:2個字節, 亞洲: 3個字節。
1四、字節碼和機器碼的區別?
- C代碼被編譯成機器碼(二進制),在機器上直接執行。 - Cpython編譯你的python源代碼,生成字節碼。 - 機器碼快的多,字節碼更易遷移,也安全。
字節碼:字節碼是一種中間狀態(中間碼)的二進制代碼(文件)。須要直譯器轉譯後才能成爲機器碼。
機器碼:機器碼就是計算機能夠直接執行,而且執行速度最快的代碼。
1五、三元運算規則以及應用場景?
# 三元運算符就是在賦值變量的時候,能夠直接加判斷,而後賦值
三元運算符的功能與'if....else'流程語句一致,它在一行中書寫,代碼很是精煉,執行效率更高 a = 1 b = 2 c = a if a > 1 else b # 若是a大於1的話,c=a,不然c=b
1六、列舉 Python2和Python3的區別?
'Print': py2--print; py3--print()函數 '編碼': py2默認是ascii碼; py3默認是utf-8 '字符串': py2中分ascii(8位)、unicode(16位); py3中全部字符串都是unicode字符串 'True和False': py2中是兩個全局變量(1和0)能夠從新賦值; py3中爲兩個關鍵字,不可從新賦值 '迭代': py2:xrange; py3:range 'Nonlocal': py3專有的(聲明爲非局部變量) '經典類&新式類': py2:經典類和新式類並存; py3:新式類都默認繼承object 'yield': py2:yield py3:yield/yield from '文件操做': py2:readliens()讀取文件的全部行,返回一個列表,包含全部行的結束符 xreadliens()返回一個生成器,循環取值 py3: 只有readlines()
1七、用一行代碼實現數值交換:
a = 1 b = 2 ########### a, b = b, a print(a, b)
1八、Python3和Python2中 int 和 long的區別?
py3中沒有long整型,統一使用int,大小和py2的long相似。 py2中int最大不能超過sys.maxint,根據不一樣平臺大小不一樣; 在int類型數字後加L定義成長整型,範圍比int更大。
1九、xrange和range的區別?
#range產生的是一個列表,xrange產生的是生成器。 #數據較大時xrange比range好。 #Range一下把數據都返回,xrange經過yield每次返回一個。
range: 函數說明,range([start,] stop[, step]),根據start與stop指定的範圍以及step設定的步長,生成一個列表。
xrange:函數說明,xrange 用法與 range 徹底相同,所不一樣的是生成的不是一個list對象,而是一個生成器。
一、range和xrange都是在循環中使用,輸出結果同樣。
二、range返回的是一個list對象,而xrange返回的是一個生成器對象(xrange object)。
三、xrange則不會直接生成一個list,而是每次調用返回其中的一個值,內存空間使用極少,於是性能很是好。
注意:Python 3.x已經去掉xrange,所有用range代替。
20、文件操做時:xreadlines和readlines的區別?
兩者使用時相同,但返回類型不一樣,xreadlines返回的是一個生成器,readlines返回的是list
# Readlines:讀取文件的全部行,返回一個列表,包含全部行的結束符 # Xreadlines:返回一個生成器,循環使用和readlines基本一致 。(py2有,py3沒有)
2一、列舉布爾值爲False的常見值?
# []、{}、None、’’、()、0、False
2二、字符串、列表、元組、字典每一個經常使用的5個方法?
#Str:
Split:分割
Strip:去掉兩邊的空格
Startwith:以什麼開頭
Endwith:以什麼結尾
Lower:小寫
Upper:大寫
#List:
Append:追加
Insert:插入
Reverse:反轉
Index:索引
Copy:拷貝
Pop:刪除指定索引處的值,不指定索引默認刪除最後一個。
#Tuple:
Count:查看某個元素出現的次數
Index:索引
#Dict:
Get:根據key取value
Items:用於循環,取出全部key和value
Keys:取出全部key
Values:取出全部的value
Clear:清空字典
Pop:刪除指定鍵對應的值,有返回值;
2三、lambda表達式格式以及應用場景?
# 格式: 匿名函數:res = lambda x:i*x print(res(2)) # 應用場景: Filter(),map(),reduce(),sorted()函數中常常用到,它們都須要函數形參數; 通常定義調用一次。 (reduce()對參數序列中元素進行累積)
lambda表達式,一般是在須要一個函數,可是又不想費神去命名一個函數的場合下使用,也就是指匿名函數。
add = lambda x, y : x+y
print(add(1,2)) # 結果爲3
應用在函數式編程中 應用在閉包中
2四、pass的做用?
# Pass通常用於站位語句,保持代碼的完整性,不會作任何操做。
一、空語句 do nothing
二、保證格式完整,保證語義完整
三、佔位語句
2五、*arg和**kwarg做用
# 他們是一種動態傳參,通常不肯定須要傳入幾個參數時,能夠使用其定義參數,而後從中取參 '*args':按照位置傳參,將傳入參數打包成一個‘元組’(打印參數爲元組-- tuple) '**kwargs':按照關鍵字傳參,將傳入參數打包成一個‘字典’(打印參數爲字典-- dict)
*args:能夠理解爲只有一列的表格,長度不固定。
**kwargs:能夠理解爲字典,長度也不固定。
一、函數調用裏的*arg和**kwarg:
(1) *arg:元組或列表「出現」
**kwarg:字典「出沒」
(2)分割參數
二、函數定義時傳的*arg /**kwarg:
(1)接收參數
2六、is和==的區別
==:判斷某些值是否同樣,比較的是值 is:比較的是內存地址(引用的內存地址不同,惟一標識:id)
2七、簡述Python的深淺拷貝以及應用場景?
#淺拷貝: 無論多麼複雜的數據結構,只copy對象最外層自己,該對象引用的其餘對象不copy, 內存裏兩個變量的地址是同樣的,一個改變另外一個也改變。 #深拷貝: 徹底複製原變量的全部數據,內存中生成一套徹底同樣的內容;只是值同樣,內存地址不同,一方修改另外一方不受影響
淺拷貝:copy.copy 深拷貝:copy.deepcopy
淺拷貝指僅僅拷貝數據集合的第一層數據,深拷貝指拷貝數據集合的全部層
主要應用在字符串,數字的深淺拷貝
2八、Python垃圾回收機制?
# Python垃圾回收機制 Python垃圾回收機制,主要使用'引用計數'來跟蹤和回收垃圾。 在'引用計數'的基礎上,經過'標記-清除'(mark and sweep)解決容器對象可能產生的循環引用問題. 經過'分代回收'以空間換時間的方法提升垃圾回收效率。 '引用計數' PyObject是每一個對象必有的內容,其中ob_refcnt就是作爲引用計數。 當一個對象有新的引用時,它的ob_refcnt就會增長,當引用它的對象被刪除, 它的ob_refcnt就會減小.引用計數爲0時,該對象生命就結束了。 \優勢:1.簡單 2.實時性 \缺點:1.維護引用計數消耗資源 2.循環引用 '標記-清楚機制' 基本思路是先按需分配,等到沒有空閒內存的時候從寄存器和程序棧上的引用出發, 遍歷以對象爲節點、以引用爲邊構成的圖,把全部能夠訪問到的對象打上標記, 而後清掃一遍內存空間,把全部沒標記的對象釋放。 '分代技術' 分代回收的總體思想是: 將系統中的全部內存塊根據其存活時間劃分爲不一樣的集合,每一個集合就成爲一個「代」, 垃圾收集頻率隨着「代」的存活時間的增大而減少,存活時間一般利用通過幾回垃圾回收來度量。
2九、Python的可變類型和不可變類型?
# 可變類型:列表、字典、集合 # 不可變類型:數字、字符串、元祖 (可變與否指內存中那塊內容value)
30、求結果:
v = dict.fromkeys(['k1', 'k2'], []) # 內存中k1和k2都指向同一個[](內存地址相同),只要指向的[]發生變化,k1和k2都要改變(保持一致) v['k1'].append(666) print(v) # {'k1': [666], 'k2': [666]} v['k1'] = 777 print(v) # {'k1': 777, 'k2': [666]}
3一、求結果:
def num(): return [lambda x: i * x for i in range(4)] #返回一個列表,裏面是四個函數對象 i=3 print([m(2) for m in num()])
3二、列舉常見的內置函數?
# map:遍歷序列,爲每個序列進行操做,返回一個結果列表 l = [1, 2, 3, 4, 5, 6, 7] def pow2(x): return x * x res = map(pow2, l) print(list(res)) #[1, 4, 9, 16, 25, 36, 49] -------------------------------------------------------------- # reduce:對於序列裏面的全部內容進行累計操做 from functools import reduce def add(x, y): return x+y print(reduce(add, [1,2,3,4])) #10 -------------------------------------------------------------- # filter:對序列裏面的元素進行篩選,最終獲取符合條件的序列。 l = [1, 2, 3, 4, 5] def is_odd(x): # 求奇數 return x % 2 == 1 print(list(filter(is_odd, l))) #[1, 3, 5] -------------------------------------------------------------- #zip用於將可迭代的對象做爲參數,將對象中對應的元素打包成一個個元組,而後返回由這些元組組成的列表 a = [1,2,3] b=[4,5,6] c=[4,5,6,7,8] ziped1 = zip(a,b) print('ziped1>>>',list(ziped1)) #[(1, 4), (2, 5), (3, 6)] ziped2 = zip(a,c) print('ziped2>>>',list(ziped2)) #[(1, 4), (2, 5), (3, 6)],以短的爲基準
3三、filter、map、reduce的做用?
# map:遍歷序列,爲每個序列進行操做,獲取一個新的序列 # reduce:對於序列裏面的全部內容進行累計操做 # filter:對序列裏面的元素進行篩選,最終獲取符合條件的序列。
3四、一行代碼實現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)]))
3五、如何安裝第三方模塊?以及用過哪些第三方模塊?
# a、能夠在pycharm的settings裏面手動下載添加第三方模塊 # b、能夠在cmd終端下用pip insatll 安裝 # 用過的第三方模塊:requests、pymysql、DBUtils等
3六、至少列舉8個經常使用模塊都有那些?
re:正則 os:提供了一種方便的使用操做系統函數的方法。 sys:可供訪問由解釋器使用或維護的變量和與解釋器進行交互的函數。 random:隨機數 json:序列化 time:時間
3七、re的match和search區別?
# match:從字符串起始位置開始匹配,若是沒有就返回None # serch:從字符串的起始位置開始匹配,匹配到第一個符合的就不會再去匹配了
3八、什麼是正則的貪婪匹配?
# 匹配一個字符串沒有節制,能匹配多少就匹配多少,直到匹配完爲止
3九、求結果: a. [ i % 2 for i in range(10) ] b. ( i % 2 for i in range(10) )
# a結果是一個列表生成式,結果是一個列表(i % 2爲生成的元素): [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] # b結果是一個生成器
40、求結果: a. 1 or 2 b. 1 and 2 c. 1 < (2==2) d. 1 < 2 == 2
a=1 or 2 #1 b=1 and 2 #2 c=1 < (2==2) #False d=1 < 2 == 2 #True
4一、def func(a,b=[]) 這種寫法有什麼坑?
# 函數傳參爲列表陷阱,列表是可變數據類型,可能會在過程當中修改裏面的值
4二、如何實現 「1,2,3」 變成 [‘1’,’2’,’3’] ?
a = '1,2,3' a=a.replace(',','') res = [i for i in a] print(res)
4三、如何實現[‘1’,’2’,’3’]變成[1,2,3] ?
l = ['1','2','3'] res = [int(i) for i in l] print(res)
4四、比較: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的區別?
前兩個列表內是int 最後一個列表內是元組
4五、如何用一行代碼生成[1,4,9,16,25,36,49,64,81,100] ?
l = [i*i for i in range(1,11)] print(l)
4六、一行代碼實現刪除列表中重複的值 ?
l = [1,1,1,2,2,3,3,3,4,4] print(list(set(l))) # [1, 2, 3, 4]
4七、如何在函數中設置一個全局變量 ?
經過global指定變量,該變量會變成全局變量
4八、logging模塊的做用?以及應用場景?
# 做用: 管理咱們程序的執行日誌,省去用print記錄操做日誌的操做,而且能夠將標準輸入輸出保存到日誌文件 # 場景: 爬蟲爬取數據時,對爬取進行日誌記錄,方便分析、排錯。
4九、請用代碼簡單實現stack 。
class Stack(object): # 初始化棧 def __init__(self): self.items = [] # 判斷棧是否爲空 def is_empty(self): return self.items == [] # 返回棧頂 def peek(self): return self.items[len(self.items) - 1] # 返回棧大小 def size(self): return len(self.items) # 壓棧 def push(self, item): self.items.append(item) # 出棧 def pop(self): return self.items.pop()
50、經常使用字符串格式化哪幾種?
# %佔位符 s = 'I am %s' %'zhugaochao' print(s) #I am zhugaochao # format格式化輸出 i = "i am {}".format('zhugaochao') print(i) #i am zhugaochao
5一、簡述 生成器、迭代器、可迭代對象 以及應用場景?
# 裝飾器: 可以在不修改原函數代碼的基礎上,在執行先後進行定製操做,閉包函數的一種應用 場景: - 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 # --------------------------------------------------------------- # 生成器: 一個函數內部存在yield關鍵字 應用場景: - rang/xrange - redis獲取值 - conn = Redis(......) - v=conn.hscan_iter() # 內部經過yield 來返回值 - stark組件中 - 前端調用後端的yield # --------------------------------------------------------------- # 迭代器: 內部有__next__和__iter__方法的對象,幫助咱們向後一個一個取值,迭代器不必定是生成器 應用場景: - wtforms裏面對form對象進行循環時,顯示form中包含的全部字段 - 列表、字典、元組 (可讓一個對象被for循環)
5二、用Python實現一個二分查找的函數。
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def search(zhi,li,start=0,end=None): end = len(li) if end is None else end zj = (end - start) // 2+start if start<=end: if zhi>li[zj]: return search(3,li,start=zj+1,end=end) elif zhi<li[zj]: return search(3,li,start=start,end=zj-1) else: return zj return '找不到這個值' print(search(2,li))
5三、談談你對閉包的理解?
# 閉包函數就是內部的函數調用外部函數的變量,經常使用於裝飾器。 # 判斷閉包函數的方法:__closure__,輸出的__closure__有cell元素說明是閉包函數 # 閉包的意義與應用:延遲計算:
5四、os和sys模塊的做用?
# os模塊負責程序與操做系統的交互,提供了訪問操做系統底層的接口; # sys模塊負責程序與python解釋器的交互,提供了一系列的函數和變量,用於操控python運行環境
5五、如何生成一個隨機數?
import random print(random.random()) print(random.randint(1, 10))
5六、如何使用python刪除一個文件?
import os os.remove('文件名以及路徑')
5七、談談你對面向對象的理解?
#封裝: 其實就是將不少數據封裝到一個對象中,相似於把不少東西放到一個箱子中, 如:一個函數若是好多參數,起始就能夠把參數封裝到一個對象再傳遞。 #繼承: 若是多個類中都有共同的方法,那麼爲了不反覆編寫,就能夠將方法提取到基類中實現, 讓全部派生類去繼承便可。 #多態: 指基類的同一個方法在不一樣派生類中有着不一樣功能。python天生支持多態。
5八、Python面向對象中的繼承有什麼特色?
#Python3的繼承機制 # 子類在調用某個方法或變量的時候,首先在本身內部查找,若是沒有找到,則開始根據繼承機制在父類裏查找。 # 根據父類定義中的順序,以深度優先的方式逐一查找父類! 繼承參數的書寫有前後順序,寫在前面的被優先繼承。
5九、面向對象深度優先和廣度優先是什麼?
# Python的類能夠繼承多個類,Python的類若是繼承了多個類,那麼其尋找方法的方式有兩種 當類是經典類時,多繼承狀況下,會按照深度優先方式查找 當類是新式類時,多繼承狀況下,會按照廣度優先方式查找 簡單點說就是:經典類是縱向查找,新式類是橫向查找 經典類和新式類的區別就是,在聲明類的時候,新式類須要加上object關鍵字。在python3中默認全是新式類
60、面向對象中super的做用?
主要在子類繼承父類的全部屬性和方法時來使用
6一、是否使用過functools中的函數?其做用是什麼?
在裝飾器中,會用到;functools.wraps()主要在裝飾器中用來裝飾函數 Stark上下文管理源碼中,走到視圖階段時有用到functools中的偏函數,request = LocalProxy(partial(_lookup_req_object, 'request'))
6二、列舉面向對象中帶爽下劃線的特殊方法,如:__new__、__init__
# __getattr__ CBV django配置文件 wtforms中的Form()示例化中 將"_fields中的數據封裝到From類中" # __mro__ wtform中 FormMeta中繼承類的優先級 # __dict__ 是用來存儲對象屬性的一個字典,其鍵爲屬性名,值爲屬性的值 # __new__ 實例化可是沒有給當前對象 wtforms,字段實例化時返回:不是StringField,而是UnboundField est frawork many=Turn 中的序列化 # __call__ flask 請求的入口app.run() 字段生成標籤時:字段.__str__ => 字段.__call__ => 插件.__call__ # __iter__ 循環對象是,自定義__iter__ wtforms中BaseForm中循環全部字段時定義了__iter__ # -metaclass 做用:用於指定當前類使用哪一個類來建立 場景:在類建立以前定製操做 示例:wtforms中,對字段進行排序。
6三、如何判斷是函數仍是方法
# 看他的調用者是誰,若是是類,須要傳入參數self,這時就是一個函數; # 若是調用者是對象,不須要傳入參數值self,這時是一個方法。 (FunctionType/MethodType)
6四、靜態方法和類方法區別?
Classmethod必須有一個指向類對象的引用做爲第一個參數; @classmethod def class_func(cls): """ 定義類方法,至少有一個cls參數 """ print('類方法') --------------------------------------------------------- Staticmethod能夠沒有任何參數。 @staticmethod def static_func(): """ 定義靜態方法 ,無默認參數""" print('靜態方法')
6五、列舉面向對象中的特殊成員以及應用場景
1. __doc__:表示類的描述信息。 2.__module__:表示當前操做的對象在那個模塊; 3.__class__:表示當前操做的對象的類是什麼。 4.__init__:構造方法,經過類建立對象時,自動觸發執行。 5.__call__:對象後面加括號,觸發執行。 6.__dict__:類或對象中的全部成員。 7.__str__:若是一個類中定義了__str__方法,那麼在打印對象時,默認輸出該方法的返回值。 class Foo: def __str__(self): return 'aaa' obj = Foo() print(obj) # 輸出:aaa 8.__getitem__、__setitem__、__delitem__:用於索引操做,如字典。以上分別表示獲取、設置、刪除數據。 9.__iter__:用於迭代器,之因此列表、字典、元組能夠進行for循環,是由於類型內部定義了 __iter__。
6六、一、二、三、四、5 能組成多少個互不相同且無重複的三位數
import itertools print(len(list(itertools.permutations('12345',3)))) #60個
6七、什麼是反射?以及應用場景?
反射就是以字符串的方式導入模塊,以字符串的方式執行函數 # 應用場景: rest framework裏面的CBV
6八、metaclass做用?以及應用場景?
類的metaclass 默認是type。咱們也能夠指定類的metaclass值。 參考:點擊查看
6九、用盡可能多的方法實現單例模式。
# 單例模式 '''單例模式是一種經常使用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例類的特殊類。 經過單例模式能夠保證系統中一個類只有一個實例並且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。 若是但願在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。''' # 1、使用__new__方法 class Singleton(object): def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): orig = super(Singleton, cls) cls._instance = orig.__new__(cls, *args, **kw) return cls._instance class MyClass(Singleton): a = 1 # 2、共享屬性 # 建立實例時把全部實例的__dict__指向同一個字典,這樣它們具備相同的屬性和方法. class Borg(object): _state = {} def __new__(cls, *args, **kw): ob = super(Borg, cls).__new__(cls, *args, **kw) ob.__dict__ = cls._state return ob class MyClass2(Borg): a = 1 # 3、裝飾器版本 def singleton(cls, *args, **kw): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return getinstance @singleton class MyClass: ... # 4、import方法 # 做爲python的模塊是自然的單例模式 # mysingleton.py class My_Singleton(object): def foo(self): pass my_singleton = My_Singleton() # to use from mysingleton import my_singleton my_singleton.foo()
70、裝飾器的寫法以及應用場景。
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)
7一、異常處理寫法以及如何主動拋出異常(應用場景)
while True: try: x = int(input("Please enter a number: ")) break except ValueError: print("Oops! That was no valid number. Try again ") # raise主動拋出一個異常 參考:點擊查看
7二、什麼是面向對象的mro
MRO:方法解析順序 它定義了 Python 中多繼承存在的狀況下,解釋器查找繼承關係的具體順序
7三、isinstance做用以及應用場景?
# 來判斷一個對象是不是一個已知的類型。 # 使用isinstance函數還能夠來判斷'類實例變量'屬於哪個類產生的。
7四、寫代碼並實現:
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]
'''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]''' class Solution: def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ # 用len()方法取得nums列表長度 n = len(nums) # x從0到n取值(不包括n) for x in range(n): a = target - nums[x] # 用in關鍵字查詢nums列表中是否有a if a in nums: # 用index函數取得a的值在nums列表中的索引 y = nums.index(a) # 假如x=y,那麼就跳過,不然返回x,y if x == y: continue else: return x, y break else: continue
7五、json序列化時,能夠處理的數據類型有哪些?如何定製支持datetime類型?
# 可序列化數據類型: 字典、列表、數字、字符串、元組;若是是元組,自動轉成列表(再轉回去的話也是列表) # 自定義時間序列化轉換器 import json from json import JSONEncoder from datetime import datetime class ComplexEncoder(JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.strftime('%Y-%m-%d %H:%M:%S') else: return super(ComplexEncoder,self).default(obj) d = { 'name':'alex','data':datetime.now()} print(json.dumps(d,cls=ComplexEncoder)) # {"name": "alex", "data": "2018-05-18 19:52:05"}
7六、json序列化時,默認遇到中文會轉換成unicode,若是想要保留中文怎麼辦?
import json a=json.dumps({"xxx":"你好"},ensure_ascii=False) print(a) #{"xxx": "你好"}
7七、什麼是斷言?應用場景?
#條件成立則繼續往下,不然拋出異常; #通常用於:知足某個條件以後,才能執行,不然應該拋出異常。 '應用場景':rest framework中GenericAPIView類裏,要設置queryset,不然斷言錯誤
7八、有用過with statement嗎?它的好處是什麼?
with語句適用於對資源進行訪問的場合,確保無論使用過程當中是否發生異常都會執行必要的「清理」操做,
釋放資源,好比文件使用後自動關閉、線程中鎖的自動獲取和釋放等。
7九、使用代碼實現查看列舉目錄下的全部文件。
import os path = os.listdir('.') #查看列舉目錄下的全部文件。 # path = os.listdir(os.getcwd()) print(path)
80、簡述 yield和yield from關鍵字。
一、yield使用 1)函數中使用yield,能夠使函數變成生成器。一個函數若是是生成一個數組,就必須把數據存儲在內存中,若是使用生成器,則在調用的時候才生成數據,能夠節省內存。 2)生成器方法調用時,不會當即執行。須要調用next()或者使用for循環來執行。 二、yield from的使用 1)爲了讓生成器(帶yield函數),能簡易的在其餘函數中直接調用,就產生了yield from。 參考:點擊查看
一、簡述 OSI 七層協議。
物理層:主要基於電器特性發送高低電壓(一、0),設備有集線器、中繼器、雙絞線等,單位:bit 數據鏈路層:定義了電信號的分組方式,設備:交換機、網卡、網橋,單位:幀 網絡層:主要功能是將網絡地址翻譯成對應屋裏地址,設備:路由 傳輸層:創建端口之間的通訊,tcp、udp協議 會話層:創建客戶端與服務端鏈接 表示層:對來自應用層的命令和數據進行解釋,按照必定格式傳給會話層。如編碼、數據格式轉換、加密解密、壓縮解壓 應用層:規定應用程序的數據格式
二、什麼是C/S和B/S架構?
#C/S架構: client端與server端的服務架構 #B/S架構: 隸屬於C/S架構,Broswer端(網頁端)與server端; 優勢:統一了全部應用的入口,方便、輕量級
三、簡述 三次握手、四次揮手的流程。
#三次握手: 1.客戶端(Client)向服務端(Server)發送一次請求 2.服務端確認並回復客戶端 3.客戶端檢驗確認請求,創建鏈接 #四次揮手: 1.客戶端向服務端發一次請求 2.服務端回覆客戶端(斷開客戶端-->服務端) 3.服務端再次向客戶端發請求(告訴客戶端能夠斷開了) 4.客戶端確認請求,鏈接斷開
四、什麼是arp協議?
#ARP(地址解析協議) 其主要用做將IP地址翻譯爲以太網的MAC地址 #在局域網中,網絡中實際傳輸的是「幀」,幀裏面是有目標主機的MAC地址的。 #在以太網中,一個主機要和另外一個主機進行直接通訊,必需要知道目標主機的MAC地址。 #所謂「地址解析」就是主機在發送幀前將目標IP地址轉換成目標MAC地址的過程。 #ARP協議的基本功能就是經過目標設備的IP地址,查詢目標設備的MAC地址,以保證通訊的順利進行。
五、TCP和UDP的區別?
#TCP協議:面向鏈接 - 通訊以前先三次握手 - 斷開以前先四次握手 - 必須先啓動服務端,再啓動客戶端-->鏈接服務端 - 安全、可靠、面向鏈接(不會丟包) #UDP協議:無鏈接 - 傳輸速度快 - 先啓動哪一端均可以 - 不面向鏈接,不能保證數據的完整性(如:QQ聊天)
六、什麼是局域網和廣域網?
局域網和廣域網是按規模大小而劃分的兩種計算機網絡。 #範圍在幾公里之內的計算機網絡統稱爲局域網(LAN、私網、內網); #而鏈接的範圍超過10公里的,則稱爲廣域網,因特網(Intenet)就是目前最大的廣域網(WAN、公網、外網)。
七、爲什麼基於tcp協議的通訊比基於udp協議的通訊更可靠?
由於TCP是面向鏈接的 通訊以前先三次握手,經過握手,確保鏈接成功以後再通訊 斷開以前先四次揮手;雙方互相確認以後再斷開鏈接,這樣一來保證了數據的安全、可靠,避免丟包
八、什麼是socket?簡述基於tcp協議的套接字通訊流程。
#服務端: 建立套接字 綁定IP和端口 監聽 accept等待鏈接 通訊(收recv、發send) #客戶端: 建立套接字 綁定IP和端口 連接服務器 通訊(收revc、發send)
九、什麼是粘包? socket 中形成粘包的緣由是什麼? 哪些狀況會發生粘包現象?
粘包:數據粘在一塊兒,主要由於:接收方不知道消息之間的界限,不知道一次性提取多少字節的數據形成的 數據量比較小,時間間隔比較短,就合併成了一個包,這是底層的一個優化算法(Nagle算法)
十、IO多路複用的做用?
# IO多路複用分爲時間上的複用和空間上的複用, # 空間上的複用是指將內存分爲幾部分,每一部分放一個程序,這樣同一時間內存中就有多道程序; # 時間上的複用是指多個程序須要在一個cpu上運行,不一樣的程序輪流使用cpu, # 當某個程序運行的時間過長或者遇到I/O阻塞,操做系統會把cpu分配給下一個程序, # 保證cpu處於高使用率,實現僞併發。
十一、什麼是防火牆以及做用?
# 什麼是防火牆? 防火牆是一個分離器,一個限制器,也是一個分析器, 有效地監控了內部網和Internet之間的任何活動,保證了內部網絡的安全。 # 做用 防火牆可經過監測、限制、更改跨越防火牆的數據流, 儘量地對外部屏蔽網絡內部的信息、結構和運行情況,以此來實現網絡的安全保護。
十二、select、poll、epoll 模型的區別?
# select本質上是經過設置或者檢查存放fd標誌位的數據結構來進行下一步處理。這樣所帶來的缺點是: # 1.單個進程可監視的fd數量被限制 # 2.須要維護一個用來存放大量fd的數據結構 # 這樣會使得用戶空間和內核空間在傳遞該結構時複製開銷大 # 3.對socket進行掃描時是線性掃描 # poll本質上和select沒有區別,它將用戶傳入的數組拷貝到內核空間, # 它沒有最大鏈接數的限制,緣由是它是基於鏈表來存儲的可是一樣有一個缺點: # 大量的fd的數組被總體複製於用戶態和內核地址空間之間,而無論這樣的複製是否是有意義。 # epoll支持水平觸發和邊緣觸發,最大的特色在於邊緣觸發, # 它只告訴進程哪些fd剛剛變爲就需態,而且只會通知一次。
1三、簡述 進程、線程、協程的區別 以及應用場景?
# 進程 進程擁有本身獨立的堆和棧,既不共享堆,亦不共享棧,進程由操做系統調度。 # 線程 線程擁有本身獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操做系統調度 # 協程和線程的區別 協程避免了無心義的調度,由此能夠提升性能;但同時協程也失去了線程使用多CPU的能力。
1四、GIL鎖是什麼鬼?
# GIL 線程全局鎖(Global Interpreter Lock),即Python爲了保證線程安全而採起的獨立線程運行的限制,說白了就是一個核只能在同一時間運行一個線程. 對於io密集型任務,python的多線程起到做用,但對於cpu密集型任務, python的多線程幾乎佔不到任何優點,還有可能由於爭奪資源而變慢。 解決辦法就是多進程和下面的協程(協程也只是單CPU,可是能減少切換代價提高性能).
1五、Python中如何使用線程池和進程池?
進程池:就是在一個進程內控制必定個數的線程 基於concurent.future模塊的進程池和線程池 (他們的同步執行和異步執行是同樣的) 參考:點擊查看
1六、threading.local的做用?
a.threading.local 做用:爲每一個線程開闢一塊空間進行數據存儲。 問題:本身經過字典建立一個相似於threading.local的東西。 storage = { 4740: {val: 0}, 4732: {val: 1}, 4731: {val: 3}, } b.自定義Local對象 做用:爲每一個線程(協程) 開闢一塊空間進行數據存儲。 try: from greenlet import getcurrent as get_ident except Exception as e: from threading import get_ident from threading import Thread import time 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()
1七、進程之間如何進行通訊?
# 進程間通信有多種方式,包括信號,管道,消息隊列,信號量,共享內存,socket等
1八、什麼是併發和並行?
# 併發:同一時刻只能處理一個任務,但一個時段內能夠對多個任務進行交替處理(一個處理器同時處理多個任務) # 並行:同一時刻能夠處理多個任務(多個處理器或者是多核的處理器同時處理多個不一樣的任務) # 類比:併發是一我的同時吃三個饅頭,而並行是三我的同時吃三個饅頭。
1九、進程鎖和線程鎖的做用?
線程鎖: 你們都不陌生,主要用來給方法、代碼塊加鎖。當某個方法或者代碼塊使用鎖時,那麼在同一時刻至多僅有有一個線程在執行該段代碼。當有多個線程訪問同一對象的加鎖方法 / 代碼塊時,同一時間只有一個線程在執行,其他線程必需要等待當前線程執行完以後才能執行該代碼段。可是,其他線程是能夠訪問該對象中的非加鎖代碼塊的。 進程鎖: 也是爲了控制同一操做系統中多個進程訪問一個共享資源,只是由於程序的獨立性,各個進程是沒法控制其餘進程對資源的訪問的,可是能夠使用本地系統的信號量控制(操做系統基本知識)。 分佈式鎖: 當多個進程不在同一個系統之中時,使用分佈式鎖控制多個進程對資源的訪問。 參考:點擊查看
20、解釋什麼是異步非阻塞?
'非阻塞': 遇到IO阻塞不等待(setblooking=False),(可能會報錯->捕捉異常) - sk=socket.socket() - sk.setblooking(False) '異步': 回調(ajax),當達到某個指定狀態以後,自動調用特定函數
2一、路由器和交換機的區別?
'交換機' 用於在同一網絡內數據快速傳輸轉發,工做在數據鏈路層; 經過MAC尋址,不能動態劃分子網; 只能在一條網絡通路中運行,不能動態分配。 '路由器' 是一個網關設備,內部局域網到公網的一個關卡; 工做在網絡層; 經過IP尋址,能夠劃分子網; 能夠在多條網絡通道中運行,能夠動態分配IP地址。 '簡單說' 交換機就是把一根網線變成多根網線; 路由器就是把一個網絡變成多個網絡; 若是不上外網,只是局域網,交換機便可; 若是上外網,而且給網絡劃分不一樣網段,就必須用路由器。
2二、什麼是域名解析?
# 在網上,全部的地址都是ip地址,但這些ip地址太難記了,因此就出現了域名(好比http://baidu.com)。 # 而域名解析就是將域名,轉換爲ip地址的這樣一種行爲。 # 例如:訪問www.baidu.com,實質是把域名解析成IP。
2三、如何修改本地hosts文件?
'hosts': Hosts就是將一些經常使用的網址域名與其對應的IP地址創建一個關聯「數據庫」 能夠用來屏蔽一些網站,或者指定一些網站(修改hostsFQ) '修改': # windows: 位置:C:\Windows\System32\drivers\etc 也能夠經過第三方軟件,我用的火絨,能夠直接進行編輯hosts # linux: 位置:/etc/hosts 修改:vi /etc/hosts
2四、生產者消費者模型應用場景及優點?
# 處理數據比較消耗時間,線程獨佔,生產數據不須要即時的反饋等。
2五、什麼是cdn?
# 用戶獲取數據時,不須要直接從源站獲取,經過CDN對於數據的分發, # 用戶能夠從一個較優的服務器獲取數據,從而達到快速訪問,並減小源站負載壓力的目的。
2六、LVS是什麼及做用?
# LVS即Linux虛擬服務器,是一個虛擬的四層交換器集羣系統, # 根據目標地址和目標端口實現用戶請求轉發,自己不產生流量,只作用戶請求轉發。
2七、Nginx是什麼及做用?
2八、keepalived是什麼及做用?
Keepalived是Linux下一個輕量級別的高可用解決方案。 高可用,其實兩種不一樣的含義:廣義來說,是指整個系統的高可用行,狹義的來說就是之主機的冗餘和接管, 參考:點擊查看
2九、haproxy是什麼以及做用?
HAProxy提供高可用性、負載均衡以及基於TCP和HTTP應用的代 理,支持虛擬主機,它是免費、快速而且可靠的一種解決方案。 HAProxy特別適用於那些負載特大的web站點,這些站點一般又須要會話保持或七層處理。HAProxy運行在當前的硬件上, 徹底能夠支持數以萬計的併發鏈接。而且它的運行模式使得它能夠很簡單安全的整合進您當前的架中, 同時能夠保護你的web服務器不被暴露到網絡上。 參考:點擊查看
30、什麼是負載均衡?
負載均衡有兩方面的含義: # 首先,大量的併發訪問或數據流量分擔到多臺節點設備上分別處理,減小用戶等待響應的時間; # 其次,單個重負載的運算分擔到多臺節點設備上作並行處理,每一個節點設備處理結束後, 將結果彙總,返回給用戶,系統處理能力獲得大幅度提升。
3一、什麼是rpc及應用場景?
RPC 的全稱是 Remote Procedure Call 是一種進程間通訊方式。 它容許程序調用另外一個地址空間(一般是共享網絡的另外一臺機器上)的過程或函數,而不用程序員顯式編碼這個遠程調用的細節。 即程序員不管是調用本地的仍是遠程的,本質上編寫的調用代碼基本相同 (例如QQ遠程操做) 參考:點擊查看
3二、簡述 asynio模塊的做用和應用場景。
asyncio是Python 3.4版本引入的標準庫,直接內置了對異步IO的支持。 asyncio的異步操做,須要在coroutine中經過yield from完成。 參考:點擊查看
3三、簡述 gevent模塊的做用和應用場景。
Gevent 是一個第三方庫,能夠輕鬆經過gevent實現併發同步或異步編程, 在gevent中用到的主要模式是Greenlet, 它是以C擴展模塊形式接入Python的輕量級協程。 Greenlet所有運行在主程序操做系統進程的內部,但它們被協做式地調度。 參考:點擊查看
3四、twisted框架的使用和應用?
Twisted是一個事件驅動型的網絡模型。 時間驅動模型編程是一種範式,這裏程序的執行流由外部決定。 特色是:包含一個事件循環,當外部事件發生時,使用回調機制來觸發相應的處理。 參考:點擊查看
一、列舉常見的關係型數據庫和非關係型都有那些?
'關係型': # sqllite、db二、oracle、access、SQLserver、MySQL # 注意:sql語句通用,須要有表結構 '非關係型': # mongodb、redis、memcache # 非關係型數據庫是key-value存儲的,沒有表結構。
二、MySQL常見數據庫引擎及比較?
'Myisam': # 支持全文索引 # 查詢速度相對較快 # 支持表鎖 # 表鎖:select * from tb for update;(鎖:for update) 'InnoDB': # 支持事務 # 支持行鎖、表鎖 # 表鎖:select * from tb for update;(鎖:for update) # 行鎖: select id ,name from tb where id=2 for update;(鎖:for update)
三、簡述數據三大範式?
# 數據庫的三大特性: '實體':表 '屬性':表中的數據(字段) '關係':表與表之間的關係 ---------------------------------------------------- # 數據庫設計三大範式: '第一範式(1NF)' 數據表中的每一列(每一個字段),必須是不可拆分的最小單元 也就是確保每一列的原子性。 '第二範式(2NF)' 知足第一範式後(1NF),要求表中的全部列,都必須依賴於主鍵, 而不能有任何一列 與主鍵沒有關係,也就是說一個表只描述一件事。 '第三範式(3NF)' 必須先知足第二範式(2NF) 要求:表中每一列只與主鍵直接相關而不是間接相關(表中每一列只能依賴於主鍵)
四、什麼是事務?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 手動關閉事務'
五、數據庫五大約束
'數據庫五大約束' 1.primary KEY:設置主鍵約束; 2.UNIQUE:設置惟一性約束,不能有重複值; 3.DEFAULT 默認值約束 4.NOT NULL:設置非空約束,該字段不能爲空; 5.FOREIGN key :設置外鍵約束。
六、簡述數據庫設計中一對多和多對多的應用場景?
# 一對一關係示例: 一個學生對應一個學生檔案材料,或者每一個人都有惟一的身份證編號。 # 一對多關係示例:(下拉單選) 一個學生只屬於一個班,可是一個班級有多名學生。 # 多對多關係示例:(下拉多選) 一個學生能夠選擇多門課,一門課也有多名學生。
七、如何基於數據庫實現商城商品計數器?
參考:點擊查看
八、常見SQL(必備)
詳見:點擊查看
九、簡述觸發器、函數、視圖、存儲過程?
'觸發器': 對數據庫某個表進行【增、刪、改】先後,自定義的一些SQL操做 '函數': 在SQL語句中使用的函數 #例如:select sleep(2) 聚合函數:max、sam、min、avg 時間格式化:date_format 字符串拼接:concat 自定製函數:(觸發函數經過 select) '視圖': 對某些表進行SQL查詢,將結果實時顯示出來(是虛擬表),只能查詢不能更新 '存儲過程': 將提早定義好的SQL語句保存到數據庫中並命名;之後在代碼中調用時直接經過名稱便可 參數類型:in、out、inout
十、MySQL索引種類
'主鍵索引(單列)': primary key 加速查找+約束:不能重複、不能爲空 '普通索引(單列)': 加速查找 '惟一索引(單列)': unique 加速查找+約束:不能重複 '聯合索引(多列)': 查詢時根據多列進行查詢(最左前綴) '聯合惟一索引(多列)': 遵循最左前綴規則(命中索引) # 其餘詞語 一、索引合併:利用多個單列索引查詢 二、覆蓋索引:在索引表中就能將想要的數據查詢到
十一、索引在什麼狀況下遵循最左前綴的規則?
你能夠認爲聯合索引是闖關遊戲的設計 例如你這個聯合索引是state/city/zipCode 那麼state就是第一關 city是第二關, zipCode就是第三關 你必須匹配了第一關,才能匹配第二關,匹配了第一關和第二關,才能匹配第三關 你不能直接到第二關的 索引的格式就是第一層是state,第二層纔是city 參考:點擊查看
十二、主鍵和外鍵的區別?
'主鍵' 惟一標識一條記錄 用來保證數據的完整性 主鍵只能有一個 '外鍵' 表的外鍵是另外一個表的主鍵,外鍵能夠有重複的,能夠是空值 用來和其餘表創建聯繫用的 一個表能夠有多個外鍵 '索引' 該字段沒有重複值,但能夠有一個空值 提升查詢速度 一個表能夠有多個惟一索引
1三、MySQL常見的函數?
'當前時間' select now(); '時間格式化' select DATE_FORMAT(NOW(), '%Y(年)-%m(月)-%d(日) %H(時):%i(分):%s(秒)') '日期加減' select DATE_ADD(DATE, INTERVAL expr unit) select DATE_ADD(NOW(), INTERVAL 1 DAY) #當前日期加一天 \expr:正數(加)、負數(減) \unit:支持毫秒microsecond、秒second、小時hour、天day、周week、年year '類型轉換' cast( expr AS TYPE) select CAST(123 AS CHAR) '字符串拼接' concat(str1,str2,……) select concat('hello','2','world') --> hellow2world '聚合函數' avg() #平均值 count() #返回指定列/行的個數 min() #最小值 max() #最大值 sum() #求和 group_concat() #返回屬於一組的列值,鏈接組合而成的結果 '數學函數' abs() #絕對值 bin() #二進制 rand() #隨機數
1四、列舉 建立索引可是沒法命中索引的8種狀況。
#使用'like ‘%xx’' select * from tb1 where name like '%cn'; #使用'函數' select * from tb1 where reverse(name)='zgc'; #使用'or' select * from tb1 where nid=1 or email='zgc@gmial.com'; 特別的:當or條件中有未創建索引的列才失效,一下會走索引 # select * from tb1 where nid=1 or name='zgc'; # select * from tb1 where nid=1 or email='zgc@gmial.com' and name='zgc'; #'類型不一致' 若是列是字符串類型,傳入條件是必須用引號引發來,否則則可能會沒法命中 select * from tb1 where name=666; #含有'!= ' select * from tb1 where name != 'zgc'; 特別的:若是是主鍵,仍是會走索引 # select * from tb1 where nid != 123; #含有'>' select * from tb1 where name > 'zgc'; 特別的:若是是主鍵或者索引是整數類型,則仍是會走索引 # select * from tb1 where nid > 123; # select * from tb1 where name > 123; #含有'order by' select email from tb1 order by name desc; 當根據索引排序時,選擇的映射若是不是索引,則不走索引 特別的:若是對主鍵排序,則仍是走索引: # select * from tb1 order by nid desc; #組合索引最左前綴 若是組合索引爲:(name,email) name and email #使用索引 name #使用索引 email #不使用索引
1五、如何開啓慢日誌查詢?
'能夠經過修改配置文件開啓' slow_query_log=ON #是否開啓慢日誌記錄 long_query_time=2 #時間限制,超過此時間,則記錄 slow_query_log_file=/usr/slow.log #日誌文件 long_queries_not_using_indexes=ON #是否記錄使用索引的搜索
1六、數據庫導入導出命令(結構+數據)?
#導出: mysqldump --no-defaults -uroot -p 數據庫名字 > 導出路徑 '--no-defaults':解決「unknown option --no-beep」報錯 #導入: 一、mysqldump -uroot -p 數據庫名稱 < 路徑 二、進入數據庫; source + 要導入數據庫文件路徑
1七、數據庫優化方案?
一、建立數據表時把固定長度的放在前面 二、將固定數據放入內存:choice字段(django中用到,1,2,3對應相應內容) 三、char不可變,varchar可變 四、聯合索引遵循最左前綴(從最左側開始檢索) 五、避免使用 select * 六、讀寫分離: #利用數據庫的主從分離:主,用於刪除、修改、更新;從,用於查 #實現:兩臺服務器同步數據 \原生SQL:select * from db.tb \ORM:model.User.object.all().using('default') \路由:db router 七、分庫 # 當數據庫中的表太多,將某些表分到不一樣數據庫,例如:1W張表時 # 代價:連表查詢跨數據庫,代碼變多 八、分表 # 水平分表:將某些列拆分到另外一張表,例如:博客+博客詳情 # 垂直分表:將某些歷史信息,分到另一張表中,例如:支付寶帳單 九、加緩存 # 利用redis、memcache(經常使用數據放到緩存裏,提升取數據速度) # 緩存不夠可能會形成雪崩現象 十、若是隻想獲取一條數據 select * from tb where name = 'zgc' limit 1;
1八、char和varchar的區別?
#char類型:定長不可變 存入字符長度大於設置長度時報錯; 存入字符串長度小於設置長度時,用空格填充以達到設置字符串長度; 簡單粗暴,浪費空間,存取速度快。 #varchar類型:可變 存儲數據真實內容,不使用空格填充; 會在真實數據前加1-2Bytes的前綴,用來表示真實數據的bytes字節數; 邊長、精準、節省空間、存取速度慢。
1九、簡述MySQL的執行計劃?
# explain + SQL語句 # SQL在數據庫中執行時的表現狀況,一般用於SQL性能分析,優化等場景。 'explain select * from rbac_userinfo where id=1;'
20、在對name作了惟一索引前提下,簡述如下區別:
select * from tb where name = ‘小明’ select * from tb where name = ‘小明’ limit 1 ------------------------------------------------------------- 沒作惟一索引的話,前者查詢會全表掃描,效率低些 limit 1,只要找到對應一條數據,就不繼續往下掃描. 然而 name 字段添加惟一索引了,加不加limit 1,意義都不大;
2一、1000w條數據,使用limit offset 分頁時,爲何越日後翻越慢?如何解決?
# 例如: #limit 100000,20; 從第十萬條開始日後取二十條, #limit 20 offset 100000; limit後面是取20條數據,offset後面是從第10W條數據開始讀 由於當一個數據庫表過於龐大,LIMIT offset, length中的offset值過大,則SQL查詢語句會很是緩慢 -------------------------------------------------------------------------- '優化一' 先查看主鍵,再分頁: select * from tb where id in (select id from tb where limit 10 offset 30) -------------------------------------------------------------------------- '優化二' 記錄當前頁,數據、ID、最大值和最小值(用於where查詢) 在翻頁時,根據條件進行篩選,篩選完畢後,再根據 limit offset 查詢 select * from(select * from tb where id > 2222) as B limit 10 offset 0; \若是用戶本身修改頁碼,也可能致使變慢,此時能夠對 url 頁碼進行加密,例如rest framework -------------------------------------------------------------------------- '優化三' 能夠按照當前業務需求,看是否能夠設置只容許看前200頁; 通常狀況下,沒人會咔咔看個幾十上百頁的;
2二、什麼是索引合併?
# 索引合併訪問方法能夠在查詢中對一個表使用多個索引,對它們同時掃描,而且合併結果。 # 此訪問方法合併來自單個表的索引掃描; 它不會將掃描合併到多個表中。
2三、什麼是覆蓋索引?
# 解釋一: 就是select的數據列只用從索引中就可以取得,沒必要從數據表中讀取,換句話說查詢列要被所使用的索引覆蓋。 # 解釋二: 索引是高效找到行的一個方法,當能經過檢索索引就能夠讀取想要的數據,那就不須要再到數據表中讀取行了。 若是一個索引包含了(或覆蓋了)知足查詢語句中字段與條件的數據就叫作覆蓋索引。 # 注意:MySQL只能使用B-Tree索引作覆蓋索引
2四、簡述數據庫讀寫分離?
#利用數據庫的主從分離:主,用於刪除、修改、更新;從,用於查 #實現:兩臺服務器同步數據(減輕服務器的壓力) 原生SQL: select * from db.tb ORM:model.User.object.all().using('default') 路由:db router
2五、簡述數據庫分庫分表?(水平、垂直)
# 一、分庫 當數據庫中的表太多,將某些表分到不一樣數據庫,例如:1W張表時 代價:連表查詢跨數據庫,代碼變多 # 二、分表 水平分表:將某些列拆分到另外一張表,例如:博客+博客詳情 垂直分表:將某些歷史信息,分到另一張表中,例如:支付寶帳單
2六、redis和memcached比較?
# 1.存儲容量: memcached超過內存比例會抹掉前面的數據,而redis會存儲在磁盤 # 2.支持數據類型: memcached只支持string; redis支持更多;如:hash、list、集合、有序集合 # 3.持久化: redis支持數據持久化,能夠將內存中的數據保持在磁盤中,memcached無 # 4.主從: 即master-slave模式的數據備份(主從)。 # 5.特性 Redis在不少方面具有數據庫的特徵,或者說就是一個數據庫系統 Memcached只是簡單的K/V緩存
2七、redis中數據庫默認是多少個db 及做用?
#redis默認有16個db,db0~db15(能夠經過配置文件支持更多,無上限) #而且每一個數據庫的數據是隔離的不能共享 #能夠隨時使用SELECT命令更換數據庫:redis> SELECT 1 # 注意: 多個數據庫之間並非徹底隔離的 好比FLUSHALL命令能夠清空一個Redis實例中全部數據庫中的數據。
2八、python操做redis的模塊?
參考:點擊查看
2九、若是redis中的某個列表中的數據量很是大,若是實現循環顯示每個值?
# 經過scan_iter分片取,減小內存壓力 scan_iter(match=None, count=None)增量式迭代獲取redis裏匹配的的值 # match,匹配指定key # count,每次分片最少獲取個數 r = redis.Redis(connection_pool=pool) for key in r.scan_iter(match='PREFIX_*', count=100000): print(key)
30、redis如何實現主從複製?以及數據同步機制?
# 實現主從複製 '建立6379和6380配置文件' redis.conf:6379爲默認配置文件,做爲Master服務配置; redis_6380.conf:6380爲同步配置,做爲Slave服務配置; '配置slaveof同步指令' 在Slave對應的conf配置文件中,添加如下內容: slaveof 127.0.0.1 6379 # 數據同步步驟: (1)Slave服務器鏈接到Master服務器. (2)Slave服務器發送同步(SYCN)命令. (3)Master服務器備份數據庫到文件. (4)Master服務器把備份文件傳輸給Slave服務器. (5)Slave服務器把備份文件數據導入到數據庫中.
3一、redis中的sentinel的做用?
# 幫助咱們自動在主從之間進行切換(哨兵) # 檢測主從中 主是否掛掉,且超過一半的sentinel檢測到掛了以後才進行進行切換。 # 若是主修復好了,再次啓動時候,會變成從。
3二、如何實現redis集羣?
#基於【分片】來完成。 - 集羣是將你的數據拆分到多個Redis實例的過程 - 能夠使用不少電腦的內存總和來支持更大的數據庫。 - 沒有分片,你就被侷限於單機能支持的內存容量。 #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的算法轉換成一個數字,而後再將該數字和16384求餘, - 若是獲得的餘數 3000,那麼就將該值寫入到 192.168.1.20 實例中。 #集羣方案: - redis cluster:官方提供的集羣方案。 - codis:豌豆莢技術團隊。 - tweproxy:Twiter技術團隊。
3三、redis中默認有多少個哈希槽?
#redis中默認有 16384 個哈希槽。
3四、簡述redis的有哪幾種持久化策略及比較?
#RDB:每隔一段時間對redis進行一次持久化。 - 缺點:數據不完整 - 優勢:速度快 #AOF:把全部命令保存起來,若是想從新生成到redis,那麼就要把命令從新執行一次。 - 缺點:速度慢,文件比較大 - 優勢:數據完整
3五、列舉redis支持的過時策略。
# 數據集(server.db[i].expires) a、voltile-lru: #從已設置過時時間的數據集中,挑選最近頻率最少數據淘汰 b、volatile-ttl: #從已設置過時時間的數據集中,挑選將要過時的數據淘汰 c、volatile-random:#從已設置過時時間的數據集中,任意選擇數據淘汰 d、allkeys-lru: #從數據集中,挑選最近最少使用的數據淘汰 e、allkeys-random: #從數據集中,任意選擇數據淘汰 f、no-enviction(驅逐):#禁止驅逐數據
3六、MySQL 裏有 2000w 數據,redis 中只存 20w 的數據,如何保證 redis 中都是熱點數據?
# 限定Redis佔用的內存,根據自身數據淘汰策略,淘汰冷數據,把熱數據加載到內存。 # 計算一下 20W 數據大約佔用的內存,而後設置一下Redis內存限制便可。
3七、寫代碼,基於redis的列表實現 先進先出、後進先出隊列、優先級隊列。???????????????????
3八、如何基於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,用它作緩存、作計算,還作任務隊列,壓力太大,很差。
3九、如何基於redis實現發佈和訂閱?以及發佈訂閱和消息隊列的區別?
# 發佈和訂閱,只要有任務就全部訂閱者每人一份。 發佈者: #發佈一次 import redis conn = redis.Redis(host='127.0.0.1',port=6379) conn.publish('104.9MH', "hahahahahaha") 訂閱者: #'while True'一直在接收 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)
40、什麼是codis及做用?
Codis 是一個分佈式 Redis 解決方案, 對於上層的應用來講, 鏈接到 Codis-Proxy(redis代理服務)和鏈接原生的 Redis-Server 沒有明顯的區別, 上層應用能夠像使用單機的 Redis 同樣使用, Codis 底層會處理請求的轉發, 不停機的數據遷移等工做, 全部後邊的一切事情, 對於前面的客戶端來講是透明的, 能夠簡單的認爲後邊鏈接的是一個內存無限大的 Redis 服務.
4一、什麼是twemproxy及做用?
# 什麼是Twemproxy 是Twtter開源的一個 Redis 和 Memcache 代理服務器, 主要用於管理 Redis 和 Memcached 集羣,減小與Cache服務器直接鏈接的數量。 他的後端是多臺REDIS或memcached因此也能夠被稱爲分佈式中間件。 # 做用 經過代理的方式減小緩存服務器的鏈接數。 自動在多臺緩存服務器間共享數據。 經過配置的方式禁用失敗的結點。 運行在多個實例上,客戶端能夠鏈接到首個可用的代理服務器。 支持請求的流式與批處理,於是可以下降來回的消耗。
4二、寫代碼實現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', 'zgc') pipe.set('role', 'haha') pipe.lpush('roless', 'haha') # 提交 pipe.execute() '注意':諮詢是否當前分佈式redis是否支持事務
4三、redis中的watch的命令的做用?
# 用於監視一個或多個key # 若是在事務執行以前這個/些key被其餘命令改動,那麼事務將被打斷
4四、基於redis如何實現商城商品數量計數器?
'經過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() 數據庫的鎖
4五、簡述redis分佈式鎖和redlock的實現機制。
# redis分佈式鎖? # 不是單機操做,又多了一/多臺機器 # redis內部是單進程、單線程,是數據安全的(只有本身的線程在操做數據) ---------------------------------------------------------------- #A、B、C,三個實例(主) 一、來了一個'隔壁老王'要操做,且不想讓別人操做,so,加鎖; 加鎖:'隔壁老王'本身生成一個隨機字符串,設置到A、B、C裏(xxx=666) 二、來了一個'鄰居老李'要操做A、B、C,一讀發現裏面有字符串,擦,被加鎖了,不能操做了,等着吧~ 三、'隔壁老王'解決完問題,不用鎖了,把A、B、C裏的key:'xxx'刪掉;完成解鎖 四、'鄰居老李'如今能夠訪問,能夠加鎖了 # 問題: 一、若是'隔壁老王'加鎖後忽然掛了,就沒人解鎖,就死鎖了,其餘人幹看着無法用咋辦? 二、若是'隔壁老王'去給A、B、C加鎖的過程當中,剛加到A,'鄰居老李'就去操做C了,加鎖成功or失敗? 三、若是'隔壁老王'去給A、B、C加鎖時,C忽然掛了,此次加鎖是成功仍是失敗? 四、若是'隔壁老王'去給A、B、C加鎖時,超時時間爲5秒,加一個鎖耗時3秒,這次加鎖能成功嗎? # 解決 一、安全起見,讓'隔壁老王'加鎖時設置超時時間,超時的話就會自動解鎖(刪除key:'xxx') 二、加鎖程度達到(1/2)+1個就表示加鎖成功,即便沒有給所有實例加鎖; 三、加鎖程度達到(1/2)+1個就表示加鎖成功,即便沒有給所有實例加鎖; 四、不能成功,鎖還沒加完就過時,沒有意義了,應該合理設置過時時間 # 注意 使用須要安裝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
4六、什麼是一致性哈希?Python中是否有相應模塊?
# 一致性哈希 一致性hash算法(DHT)能夠經過減小影響範圍的方式,解決增減服務器致使的數據散列問題,從而解決了分佈式環境下負載均衡問題; 若是存在熱點數據,能夠經過增添節點的方式,對熱點區間進行劃分,將壓力分配至其餘服務器,從新達到負載均衡的狀態。 # 模塊:hash_ring
4七、如何高效的找到redis中全部以zhugc開頭的key?
redis 有一個keys命令。 # 語法:KEYS pattern # 說明:返回與指定模式相匹配的所用的keys。 該命令所支持的匹配模式以下: 一、?:用於匹配單個字符。例如,h?llo能夠匹配hello、hallo和hxllo等; 二、*:用於匹配零個或者多個字符。例如,h*llo能夠匹配hllo和heeeello等; 二、[]:能夠用來指定模式的選擇區間。例如h[ae]llo能夠匹配hello和hallo,可是不能匹配hillo。同時,能夠使用「/」符號來轉義特殊的字符 # 注意 KEYS 的速度很是快,但若是數據太大,內存可能會崩掉, 若是須要從一個數據集中查找特定的key,最好仍是用Redis的集合結構(set)來代替。
4八、悲觀鎖和樂觀鎖的區別?
# 悲觀鎖 從數據開始更改時就將數據鎖住,直到更改完成才釋放; 會形成訪問數據庫時間較長,併發性很差,特別是長事務。 # 樂觀鎖 直到修改完成,準備提交修改到數據庫時纔會鎖住數據,完成更改後釋放; 相對悲觀鎖,在現實中使用較多。
瀏覽器本質,socket客戶端遵循Http協議 HTTP協議本質:經過\r\n分割的規範+ 請求響應以後斷開連接 == > 無狀態、 短鏈接 具體: Http協議是創建在tcp之上的,是一種規範,它規範定了發送的數據的數據格式, 然而這個數據格式是經過\r\n 進行分割的,請求頭與請求體也是經過2個\r\n分割的,響應的時候, 響應頭與響應體也是經過\r\n分割,而且還規定已請求已響應就會斷開連接 即---> 短鏈接、無狀態
websocket是給瀏覽器新建的一套(相似與http)協議,協議規定:(\r\n分割)瀏覽器和服務器鏈接以後不斷開, 以此完成:服務端向客戶端主動推送消息。 websocket協議額外作的一些操做 握手 ----> 鏈接錢進行校驗 加密 ----> payload_len=127/126/<=125 --> mask key 本質 建立一個鏈接後不斷開的socket 當鏈接成功以後: 客戶端(瀏覽器)會自動向服務端發送消息,包含: Sec-WebSocket-Key: iyRe1KMHi4S4QXzcoboMmw== 服務端接收以後,會對於該數據進行加密:base64(sha1(swk + magic_string)) 構造響應頭: HTTP/1.1 101 Switching Protocols\r\n Upgrade:websocket\r\n Connection: Upgrade\r\n Sec-WebSocket-Accept: 加密後的值\r\n WebSocket-Location: ws://127.0.0.1:8002\r\n\r\n 發給客戶端(瀏覽器) 創建:雙工通道,接下來就能夠進行收發數據 發送數據是加密,解密,根據payload_len的值進行處理 payload_len <= 125 payload_len == 126 payload_len == 127 獲取內容: mask_key 數據 根據mask_key和數據進行位運算,就能夠把值解析出來。
客戶端向服務端發送消息時,會有一個'sec-websocket-key'和'magic string'的隨機字符串(魔法字符串) # 服務端接收到消息後會把他們鏈接成一個新的key串,進行編碼、加密,確保信息的安全性
響應式佈局是經過@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>
jQuery - BootStrap - Vue.js(與vue齊名的前端框架React和Angular)
http://www.cnblogs.com/wupeiqi/articles/5703697.html
輪詢:經過定時器讓程序每隔n秒執行一次操做。
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>請選出最帥的男人</h1> <ul> {% for k,v in gg.items() %} <li>ID:{{ k }}, 姓名:{{ v.name }} ,票數:{{ v.count }}</li> {% endfor %} </ul> <script> setInterval(function () { location.reload(); },2000) </script> </body> </html>
客戶端向服務器發送請求,服務器接到請求後hang住鏈接,等待30秒,30s事後再從新發起請求, 直到有新消息才返回響應信息並關閉鏈接,客戶端處理完響應信息後再向服務器發送新的請求。
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>請選出最帥的男人</h1> <ul> {% for k,v in gg.items() %} <li style="cursor: pointer" id="user_{{ k }}" ondblclick="vote({{ k }});">ID:{{ k }}, 姓名:{{ v.name }} ,票數:<span>{{ v.count }}</span></li> {% endfor %} </ul> <script src="/static/jquery-3.3.1.min.js"></script> <script> $(function () { get_new_count(); }); function get_new_count() { $.ajax({ url: '/get_new_count', type:'GET', dataType:'JSON', success:function (arg) { if (arg.status){ // 更新票數 var gid = "#user_" + arg.data.gid; $(gid).find('span').text(arg.data.count); }else{ // 10s內沒有人投票 } get_new_count(); } }) } function vote(gid) { $.ajax({ url: '/vote', type:'POST', data:{gid:gid}, dataType:"JSON", success:function (arg) { } }) } </script> </body> </html>
多組件之間共享:vuex 補充luffyvue 1:router-link / router-view 2:雙向綁定,用戶綁定v-model 3:循環展現課程:v-for 4:路由系統,添加動態參數 5:cookie操做:vue-cookies 6:多組件之間共享:vuex 7:發送ajax請求:axios (js模塊)
vue-resource的interceptors攔截器的做用正是解決此需求的妙方。
在每次http的請求響應以後,若是設置了攔截器以下,會優先執行攔截器函數,獲取響應體,而後纔會決定是否把response返回給then進行接收
發送ajax請求:axios (js模塊)
一、v-if指令:判斷指令,根據表達式值得真假來插入或刪除相應的值。 二、v-show指令:條件渲染指令,不管返回的布爾值是true仍是false,元素都會存在在html中,只是false的元素會隱藏在html中,並不會刪除. 三、v-else指令:配合v-if或v-else使用。 四、v-for指令:循環指令,至關於遍歷。 五、v-bind:給DOM綁定元素屬性。 六、v-on指令:監聽DOM事件。
JSONP jsonp是json用來跨域的一個東西。原理是經過script標籤的跨域特性來繞過同源策略。 JSONP的簡單實現模式,或者說是JSONP的原型:建立一個回調函數,而後在遠程服務上調用這個函數而且將JSON 數據形式做爲參數傳遞, 完成回調。
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 凡是不一樣時知足上面兩個條件,就屬於非簡單請求
GET、POST、
PUT、patch(修改數據) HEAD(相似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭) DELETE
傳值代碼f
Request.QueryString方法針對控件id
Request.Form方法針對控件名稱name
分類: 1** 信息,服務器收到請求,須要請求者繼續執行操做 2** 成功,操做被成功接收並處理 3** 重定向,須要進一步的操做以完成請求 4** 客戶端錯誤,請求包含語法錯誤或沒法完成請求 5** 服務器錯誤,服務器在處理請求的過程當中發生了錯誤 常見的狀態碼 200 -請求成功
202 -已接受請求,還沒有處理
204 -請求成功,且不需返回內容 301 - 資源(網頁等)被永久轉移到其餘url
400 - 請求的語義或是參數有錯
403 - 服務器拒絕請求 404 - 請求資源(網頁)不存在
500 - 內部服務器錯誤
502 - 網關錯誤,通常是服務器壓力過大致使鏈接超時
503 - 因爲超載或系統維護,服務器暫時的沒法處理客戶端的請求。
- user-agent - host - referer - cookie - content-type
李傑
武沛奇
老男孩
undefined
武沛奇
Alex
對於django,大而全的框架它的內部組件比較多,內部提供:ORM、Admin、中間件、Form、ModelForm、Session、
緩存、信號、CSRF;功能也都挺完善的 - flask,微型框架,內部組件就比較少了,可是有不少第三方組件來擴展它,
好比說有那個wtform(與django的modelform相似,表單驗證)、flask-sqlalchemy(操做數據庫的)、
flask-session、flask-migrate、flask-script、blinker可擴展強,第三方組件豐富。因此對他自己來講有那種短小精悍的感受 - tornado,異步非阻塞。 django和flask的共同點就是,他們2個框架都沒有寫socket,因此他們都是利用第三方模塊wsgi。 可是內部使用的wsgi也是有些不一樣的:django自己運行起來使用wsgiref,而flask使用werkzeug wsgi 還有一個區別就是他們的請求管理不太同樣:django是經過將請求封裝成request對象,再經過參數傳遞,而flask是經過上下文管理機制
Tornado
# 是一個輕量級的Web框架,異步非阻塞+內置WebSocket功能。
'目標':經過一個線程處理N個併發請求(處理IO)。
'內部組件
#內部本身實現socket
#路由系統
#視圖
#模板
#cookie
#csrf
是web服務網關接口,是一套協議。 是經過如下模塊實現了wsgi協議: - wsgiref - werkzurg - uwsgi 關於部署 以上模塊本質:編寫socket服務端,用於監聽請求,當有請求到來,則將請求數據進行封裝,而後交給web框架處理。
用戶請求進來先走到 wsgi 而後將請求交給 jango的中間件 穿過django中間件(方法是process_request)
接着就是 路由匹配 路由匹配成功以後就執行相應的 視圖函數
在視圖函數中能夠調用orm作數據庫操做 再從模板路徑 將模板拿到 而後在後臺進行模板渲染
模板渲染完成以後就變成一個字符串 再把這個字符串通過全部中間件(方法:process_response) 和wsgi 返回給用戶
form 組件 - 對用戶請求的數據進行校驗 - 生成HTML標籤 PS: - form對象是一個可迭代對象。 - 問題:choice的數據若是從數據庫獲取可能會形成數據沒法實時更新 - 重寫構造方法,在構造方法中從新去數據庫獲取值。 - ModelChoiceField字段 from django.forms import Form from django.forms import fields from django.forms.models import ModelChoiceField class UserForm(Form): name = fields.CharField(label='用戶名',max_length=32) email = fields.EmailField(label='郵箱') ut_id = ModelChoiceField(queryset=models.UserType.objects.all()) 依賴: class UserType(models.Model): title = models.CharField(max_length=32) def __str__(self): return self.title
信號、 django的信號其實就是django內部爲開發者預留的一些自定製功能的鉤子。 只要在某個信號中註冊了函數,那麼django內部執行的過程當中就會自動觸發註冊在信號中的函數。 如: pre_init # django的modal執行其構造方法前,自動觸發 post_init # django的modal執行其構造方法後,自動觸發 pre_save # django的modal對象保存前,自動觸發 post_save # django的modal對象保存後,自動觸發 場景: 在數據庫某些表中添加數據時,能夠進行日誌記錄。 CSRF、 目標:防止用戶直接向服務端發起POST請求。
對全部的post請求作驗證/ 將jango生成的一串字符串發送給咱們,一種是從請求體發過來,一種是放在隱藏的標籤裏面用的是process_view
方案:先發送GET請求時,將token保存到:cookie、Form表單中(隱藏的input標籤),
之後再發送請求時只要攜帶過來便可。
ContentType
contenttype是django的一個組件(app),
爲咱們找到django程序中全部app中的全部表並添加到記錄中。
能夠使用他再加上表中的兩個字段實現:一張表和N張表建立FK關係。 - 字段:表名稱 - 字段:數據行ID
應用:路飛表結構優惠券和專題課和學位課關聯。
中間件 對全部的請求進行批量處理,在視圖函數執行先後進行自定義操做。
應用:用戶登陸校驗
問題:爲甚麼不使用裝飾器?
若是不使用中間件,就須要給每一個視圖函數添加裝飾器,太繁瑣
權限組件: 用戶登陸後,將權限放到session中,而後再每次請求進來在中間件裏,根據當前的url去session中匹配,
判斷當前用戶是否有權限訪問當前url,有權限就繼續訪問,沒有就返回, (檢查的東西就能夠放到中間件中進行統一處理)在process_request方法裏面作的, 咱們的中間件是放在session後面,由於中間件須要到session裏面取數據
session cookie與session區別 (a)cookie是保存在瀏覽器端的鍵值對,而session是保存的服務器端的鍵值對,可是依賴cookie。
(也能夠不依賴cookie,能夠放在url,或請求頭可是cookie比較方便) (b)以登陸爲例,cookie爲經過登陸成功後,設置明文的鍵值對,並將鍵值對發送客戶端存,明文信息可能存在泄漏,不安全;
session則是生成隨機字符串,發給用戶,並寫到瀏覽器的cookie中,同時服務器本身也會保存一份。 (c)在登陸驗證時,cookie:根據瀏覽器發送請求時附帶的cookie的鍵值對進行判斷,若是存在,則驗證經過;
session:在請求用戶的cookie中獲取隨機字符串,根據隨機字符串在session中獲取其對應的值進行驗證
cors跨域(場景:先後端分離時,本地測試開發時使用) 若是網站之間存在跨域,域名不一樣,端口不一樣會致使出現跨域,但凡出現跨域,瀏覽器就會出現同源策略的限制 解決:在咱們的服務端給咱們響應數據,加上響應頭---> 在中間件加的
緩存/
經常使用的數據放在緩存裏面,就不用走視圖函數,請求進來經過全部的process_request,會到緩存裏面查數據,有就直接拿,
沒有就走視圖函數
關鍵點:1:執行完全部的process_request纔去緩存取數據
2:執行完全部的process_response纔將數據放到緩存
關於緩存問題 1:爲何放在最後一個process_request纔去緩存 由於須要驗證完用戶的請求,才能返回數據 2:何時將數據放到緩存中 第一次走中間件,緩存沒有數據,會走視圖函數,取數據庫裏面取數據, 當走完process_response,纔將數據放到緩存裏,由於,走process_response的時候可能給咱們的響應加處理
爲何使用緩存 將經常使用且不太頻繁修改的數據放入緩存。 之後用戶再來訪問,先去緩存查看是否存在,若是有就返回 不然,去數據庫中獲取並返回給用戶(再加入到緩存,以便下次訪問)
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)
執行流程
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()
- 沒什麼區別,由於他們的本質都是函數。CBV的.as_view()返回的view函數,view函數中調用類的dispatch方法, 在dispatch方法中經過反射執行get/post/delete/put等方法。D 非要說區別的話: - CBV比較簡潔,GET/POST等業務功能分別放在不一樣get/post函數中。FBV本身作判斷進行區分。
當請求一個頁面時, Django會創建一個包含請求元數據的 HttpRequest 對象.
當Django 加載對應的視圖時, HttpRequest對象將做爲視圖函數的第一個參數.
每一個視圖會返回一個HttpResponse對象.
添加裝飾器 方式一: 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('...')
返回QuerySet對象的方法有: all() filter() exclude() order_by() reverse() distinct() 特殊的QuerySet: values() 返回一個可迭代的字典序列 values_list() 返回一個可迭代的元組序列 返回具體對象的: get() first() last() 返回布爾值的方法有: exists() 返回數字的方法有: count()
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')
# 他倆都用於連表查詢,減小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)
def filter(self, *args, **kwargs) # 條件查詢(符合條件) # 查出符合條件 # 條件能夠是:參數,字典,Q def exclude(self, *args, **kwargs) # 條件查詢(排除條件) # 排除不想要的 # 條件能夠是:參數,字典,Q
原生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")
方式一:手動使用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',]
F:主要用來獲取原數據進行計算。 Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。 修改操做也能夠使用F函數,好比將每件商品的價格都在原價格的基礎上增長10
from django.db.models import F from app01.models import Goods Goods.objects.update(price=F("price")+10) # 對於goods表中每件商品的價格都在原價格的基礎上增長10元
F查詢專門對對象中某列值的操做,不可以使用__雙下劃線!
Q:用來進行復雜查詢
Q查詢能夠組合使用 「&」, 「|」 操做符,當一個操做符是用於兩個Q的對象,它產生一個新的Q對象,
Q對象能夠用 「~」 操做符放在前面表示否認,也可容許否認與不否認形式的組合。
Q對象能夠與關鍵字參數查詢一塊兒使用,不過必定要把Q對象放在關鍵字參數查詢的前面。
Q(條件1) | Q(條件2) 或 Q(條件1) & Q(條件2) 且 Q(條件1) & ~Q(條件2) 非
def values(self, *fields): # 獲取每行數據爲字典格式 def values_list(self, *fields, **kwargs): # 獲取每行數據爲元祖
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)
- 做用: - 對用戶請求數據格式進行校驗 - 自動生成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 - 應用:只要是客戶端向服務端發送表單數據時,均可以進行使用,如:用戶登陸註冊
方式一:重寫構造方法,在構造方法中從新去數據庫獲取值 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
在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就能夠了。
目的:防止用戶直接向服務端發起POST請求
- 用戶先發送GET獲取csrf token: Form表單中一個隱藏的標籤 + token - 發起POST請求時,須要攜帶以前發送給用戶的csrf token; - 在中間件的process_view方法中進行校驗。 在html中添加{%csrf_token%}標籤
django中能夠經過channel實現websocket
//方式一給每一個ajax都加上上請求頭 function Do1(){ $.ajax({ url:"/index/", data:{id:1}, type:'POST', data:{csrfmiddlewaretoken:'{{ csrf_token }}',name:'alex'} success:function(data){ console.log(data); } }); } 方式二:須要先下載jQuery-cookie,才能去cookie中獲取token function Do1(){ $.ajax({ url:"/index/", data:{id:1}, type:'POST', headers:{ 'X-CSRFToken':$.cookie('csrftoken') // 去cookie中獲取 }, success:function(data){ console.log(data); } }); } 方式三:搞個函數ajaxSetup,當有多的ajax請求,即會執行這個函數 $.ajaxSetup({ beforeSend:function (xhr,settings) { xhr.setRequestHeader("X-CSRFToken",$.cookie('csrftoken')) } }); 函數版本 <body> <input type="button" onclick="Do1();" value="Do it"/> <input type="button" onclick="Do2();" value="Do it"/> <input type="button" onclick="Do3();" value="Do it"/> <script src="/static/jquery-3.3.1.min.js"></script> <script src="/static/jquery.cookie.js"></script> <script> $.ajaxSetup({ beforeSend: function(xhr, settings) { xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken')); } }); function Do1(){ $.ajax({ url:"/index/", data:{id:1}, type:'POST', success:function(data){ console.log(data); } }); } function Do2(){ $.ajax({ url:"/index/", data:{id:1}, type:'POST', success:function(data){ console.log(data); } }); } function Do3(){ $.ajax({ url:"/index/", data:{id:1}, type:'POST', success:function(data){ console.log(data); } }); } </script> </body>
給信號註冊函數
使用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對象刪除後,自動觸發
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 %}
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('...')
反向解析路由字符串
路由系統中name的做用:反向解析
url(r'^home', views.home, name='home')
在模板中使用:{ % url 'home' %}
在視圖中使用:reverse(「home」)
filter : 相似管道,只能接受兩個參數第一個參數是|前的數據 simple_tag : 相似函數
一、模板繼承:{ % extends 'layouts.html' %}
二、自定義方法
'filter':只能傳遞兩個參數,能夠在if、for語句中使用
'simple_tag':能夠無線傳參,不能在if for中使用
'inclusion_tags':能夠使用模板和後端數據
三、防xss攻擊: '|safe'、'mark_safe'
1、查看訪問的速度、數據庫的行爲、cache命中等信息。 2、尤爲在Mysql訪問等的分析上大有用處(sql查詢速度)
對於每個測試方法都會將setUp()和tearDown()方法執行一遍 會單獨新建一個測試數據庫來進行數據庫的操做方面的測試,默認在測試完成後銷燬。 在測試方法中對數據庫進行增刪操做,最後都會被清除。也就是說,在test_add中插入的數據,在test_add測試結束後插入的數據會被清除。 django單元測試時爲了模擬生產環境,會修改settings中的變量,例如, 把DEBUG變量修改成True, 把ALLOWED_HOSTS修改成[*]。
db first: 先建立數據庫,再更新表模型 code first:先寫表模型,再更新數據庫
https://www.cnblogs.com/jassin-du/p/8988897.html
一、修改seting文件,在setting裏面設置要鏈接的數據庫類型和名稱、地址 二、運行下面代碼能夠自動生成models模型文件 - python manage.py inspectdb 三、建立一個app執行下下面代碼: - python manage.py inspectdb > app/models.py
SQL: # 優勢: 執行速度快 # 缺點: 編寫複雜,開發效率不高 --------------------------------------------------------------------------- ORM: # 優勢: 讓用戶再也不寫SQL語句,提升開發效率 能夠很方便地引入數據緩存之類的附加功能 # 缺點: 在處理多表聯查、where條件複雜查詢時,ORM的語法會變得複雜。 沒有原生SQL速度快
MVC:model、view(模塊)、controller(視圖) MTV:model、tempalte、view
contenttype是django的一個組件(app),它能夠將django下全部app下的表記錄下來 能夠使用他再加上表中的兩個字段,實現一張表和N張表動態建立FK關係。 - 字段:表名稱 - 字段:數據行ID 應用:路飛表結構優惠券和專題課和學位課關聯
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/
'一個接口經過1次相同的訪問,再對該接口進行N次相同的訪問時,對資源不造影響就認爲接口具備冪等性。' GET, #第一次獲取結果、第二次也是獲取結果對資源都不會形成影響,冪等。 POST, #第一次新增數據,第二次也會再次新增,非冪等。 PUT, #第一次更新數據,第二次不會再次更新,冪等。 PATCH,#第一次更新數據,第二次不會再次更新,非冪等。 DELTE,#第一次刪除數據,第二次不在再刪除,冪等。
'遠程過程調用協議' 是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。 進化的順序: 現有的RPC,而後有的RESTful規範
#Http: 80端口 #https: 443端口 # http信息是明文傳輸,https則是具備安全性的ssl加密傳輸協議。 #- 自定義證書 - 服務端:建立一對證書 - 客戶端:必須攜帶證書 #- 購買證書 - 服務端: 建立一對證書,。。。。 - 客戶端: 去機構獲取證書,數據加密後發給我們的服務單 - 證書機構:公鑰給改機構
# 在編寫接口時能夠不使用django rest framework框架, # 不使用:也能夠作,能夠用django的CBV來實現,開發者編寫的代碼會更多一些。 # 使用:內部幫助咱們提供了不少方便的組件,咱們經過配置就能夠完成相應操做,如: '序列化'能夠作用戶請求數據校驗+queryset對象的序列化稱爲json '解析器'獲取用戶請求數據request.data,會自動根據content-type請求頭的不能對數據進行解析 '分頁'將從數據庫獲取到的數據在頁面進行分頁顯示。 # 還有其餘組件: '認證'、'權限'、'訪問頻率控制
#- 路由,自動幫助開發者快速爲一個視圖建立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 - 定義方法 - 請求數據格式校驗 #- 渲染器
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
- 如何編寫?寫類並實現authenticators 請求進來認證須要編寫一個類,類裏面有一個authenticators方法,咱們能夠自定義這個方法,能夠定製3類返回值。 成功返回元組,返回none爲匿名用戶,拋出異常爲認證失敗。 源碼流程:請求進來先走dispatch方法,而後封裝的request對象會執行user方法,由user觸發authenticators認證流程 - 方法中能夠定義三種返回值: - (user,auth),認證成功 - None , 匿名用戶 - 異常 ,認證失敗 - 流程: - dispatch - 再去request中進行認證處理
# 對匿名用戶,根據用戶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則不可訪問
Flask自由、靈活,可擴展性強,透明可控,第三方庫的選擇面廣, 開發時能夠結合最流行最強大的Python庫,
# 依賴jinja2模板引擎 # 依賴werkzurg協議
# blueprint把實現不一樣功能的module分開.也就是把一個大的App分割成各自實現不一樣功能的module. # 在一個blueprint中能夠調用另外一個blueprint的視圖函數, 但要加相應的blueprint名.
# Flask組件 flask-session session放在redis flask-SQLAlchemy 如django裏的ORM操做 flask-migrate 數據庫遷移 flask-script 自定義命令 blinker 信號-觸發信號 # 第三方組件 Wtforms 快速建立前端標籤、文本校驗 dbutile 建立數據庫鏈接池 gevnet-websocket 實現websocket # 自定義Flask組件 自定義auth認證 參考flask-login組件
# a、簡單來講,falsk上下文管理能夠分爲三個階段: 一、'請求進來時':將請求相關的數據放入上下問管理中 二、'在視圖函數中':要去上下文管理中取值 三、'請求響應':要將上下文管理中的數據清除 # b、詳細點來講: 一、'請求剛進來': 將request,session封裝在RequestContext類中 app,g封裝在AppContext類中 並經過LocalStack將requestcontext和appcontext放入Local類中 二、'視圖函數中': 經過localproxy--->偏函數--->localstack--->local取值 三、'請求響應時': 先執行save.session()再各自執行pop(),將local中的數據清除
# g是貫穿於一次請求的全局變量,當請求進來將g和current_app封裝爲一個APPContext類, # 再經過LocalStack將Appcontext放入Local中,取值時經過偏函數在LocalStack、local中取值; # 響應時將local中的g數據刪除:
RequestContext #封裝進來的請求(賦值給ctx) AppContext #封裝app_ctx LocalStack #將local對象中的數據維護成一個棧(先進後出) Local #保存請求上下文對象和app上下文對象
# 由於經過維護成列表,能夠實現一個棧的數據結構,進棧出棧時只取一個數據,巧妙的簡化了問題。 # 還有,在多app應用時,能夠實現數據隔離;列表裏不會加數據,而是會生成一個新的列表 # local是一個字典,字典裏key(stack)是惟一標識,value是一個列表
請求進來時,能夠根據URL的不一樣,交給不一樣的APP處理。藍圖也能夠實現。 #app1 = Flask('app01') #app2 = Flask('app02') #@app1.route('/index') #@app2.route('/index2') 源碼中在DispatcherMiddleware類裏調用app2.__call__, 原理其實就是URL分割,而後將請求分發給指定的app。 以後app也按單app的流程走。就是從app.__call__走。
gevent-websocket
#快速建立前端標籤、文本校驗;如django的ModelForm
# 前提: 不熟的話:記不太清了,應該是……分兩個階段吧 # 建立: 當請求剛進來的時候,會將request和session封裝成一個RequestContext()對象, 接下來把這個對象經過LocalStack()放入內部的一個Local()對象中; 由於剛開始 Local 的ctx中session是空的; 因此,接着執行open_session,將cookie 裏面的值拿過來,從新賦值到ctx中 (Local實現對數據隔離,相似threading.local) # 銷燬: 最後返回時執行 save_session() 將ctx 中的session讀出來進行序列化,寫到cookie 而後給用戶,接着把 ctx pop掉
# 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請求過程當中定製一些行爲。 或者說flask在列表裏面預留了幾個空列表,在裏面存東西。 簡言之,信號容許某個'發送者'通知'接收者'有事情發生了
@ before_request有返回值,blinker沒有返回值
# 10個信號
request_started = _signals.signal('request-started') #請求到來前執行
request_finished = _signals.signal('request-finished') #請求結束後執行
before_render_template = _signals.signal('before-render-template')#模板渲染前執行
template_rendered = _signals.signal('template-rendered')#模板渲染後執行
got_request_exception = _signals.signal('got-request-exception') #請求執行出現異常時執行
request_tearing_down = _signals.signal('request-tearing-down')#請求執行完畢後自動執行(不管成功與否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 請求上下文執行完畢後自動執行(不管成功與否)
appcontext_pushed = _signals.signal('appcontext-pushed') #請求app上下文push時執行
appcontext_popped = _signals.signal('appcontext-popped') #請求上下文pop時執行
message_flashed = _signals.signal('message-flashed')#調用flask在其中添加數據時,自動觸發
# Session: 因爲沒法提供線程共享功能,開發時要給每一個線程都建立本身的session 打印sesion可知他是sqlalchemy.orm.session.Session的對象 # scoped_session: 爲每一個線程都建立一個session,實現支持線程安全 在整個程序運行的過程中,只存在惟一的一個session對象。 建立方式: 經過本地線程Threading.Local() # session=scoped_session(Session) 建立惟一標識的方法(參考flask請求源碼)
# 使用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的實現基於一下三點 映射類:描述數據庫表結構, 映射文件:指定數據庫表和映射類之間的關係 數據庫配置文件:指定與數據庫鏈接時須要的鏈接信息(數據庫、登陸用戶名、密碼or鏈接字符串)
# 數據庫鏈接池 使用模式: 一、爲每一個線程建立一個鏈接,鏈接不可控,須要控制線程數 二、建立指定數量的鏈接在鏈接池,當線程訪問的時候去取,不夠了線程排隊,直到有人釋放(推薦) --------------------------------------------------------------------------- 兩種寫法: 一、用靜態方法裝飾器,經過直接執行類的方法來鏈接使用數據庫 二、經過實例化對象,經過對象來調用方法執行語句 https://www.cnblogs.com/ArmoredTitan/p/Flask.html
如下SQLAlchemy的字段是否正確?若是不正確請更正:
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())
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 後面不該該加括號,加了的話,字段不會實時更新。
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:123456@127.0.0.1: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__還可設置存儲引擎、外鍵約束等等信息。
經過'UniqueConstraint'字段來設置聯合惟一索引 __table_args=(UniqueConstraint('h_id','username',name='_h_username_uc')) #h_id和username組成聯合惟一約束
異步非阻塞+websocket
# 實現異步非阻塞 視圖函數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模塊中提供了一個WebSocketHandler類。 這個類提供了和已鏈接的客戶端通訊的WebSocket事件和方法的鉤子。 當一個新的WebSocket鏈接打開時,open方法被調用, 而on_message和on_close方法,分別在鏈接、接收到新的消息和客戶端關閉時被調用。 此外,WebSocketHandler類還提供了write_message方法用於向客戶端發送消息,close方法用於關閉鏈接。
# 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'文件
torndb torndb是基於mysqldb的再封裝,因此使用時要先安裝myqldb
tornado-redis
web聊天室,在線投票
# 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 list':查看「某個地方」存儲的全部記錄 'git stash clear':清空「某個地方」 'git stash pop':將第一個記錄從「某個地方」從新拿到工做區(可能有衝突) 'git stash apply':編號, 將指定編號記錄從「某個地方」從新拿到工做區(可能有衝突) 'git stash drop':編號,刪除指定編號的記錄
merge: 會將不一樣分支的提交合併成一個新的節點,以前的提交分開顯示, 注重歷史信息、能夠看出每一個分支信息,基於時間點,遇到衝突,手動解決,再次提交 rebase: 將兩個分支的提交結果融合成線性,不會產生新的節點; 注重開發過程,遇到衝突,手動解決,繼續操做
一、大家公司的代碼review分支怎麼作?誰來作? 答:組長建立review分支,咱們小功能開發完以後,合併到review分支交給老大(小組長)來看, 1.一、你組長不開發代碼嗎? 他開發代碼,可是它只開發核心的東西,任務比較少。 或者抽出時間,咱們一塊兒作這個事情 二、大家公司協同開發是怎麼協同開發的? 每一個人都有本身的分支,階段性代碼完成以後,合併到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
https://blog.csdn.net/june_y/article/details/50817993
在命令行中,使用「git tag –a tagname –m 「comment」能夠快速建立一個標籤。 須要注意,命令行建立的標籤只存在本地Git庫中,還須要使用Git push –tags指令發佈到服務器的Git庫中
gitlab是公司本身搭建的項目代碼託管平臺
一、gitHub是一個面向開源及私有軟件項目的託管平臺 (建立私有的話,須要購買,最低級的付費爲每個月7刀,支持5個私有項目) 二、gitlab是公司本身搭建的項目託管平臺
一、fork須要協做項目 二、克隆/關聯fork的項目到本地 三、新建分支(branch)並檢出(checkout)新分支 四、在新分支上完成代碼開發 五、開發完成後將你的代碼合併到master分支 六、添加原做者的倉庫地址做爲一個新的倉庫地址 七、合併原做者的master分支到你本身的master分支,用於和做者倉庫代碼同步 八、push你的本地倉庫到GitHub 九、在Github上提交 pull requests 十、等待管理員(你須要貢獻的開源項目管理員)處理
通常來講每一個Git項目中都須要一個「.gitignore」文件, 這個文件的做用就是告訴Git哪些文件不須要添加到版本管理中。 實際項目中,不少文件都是不須要版本管理的,好比Python的.pyc文件和一些包含密碼的配置文件等等。
'敏捷開發':是一種以人爲核心、迭代、按部就班的開發方式。 它並非一門技術,而是一種開發方式,也就是一種軟件開發的流程。 它會指導咱們用規定的環節去一步一步完成項目的開發。 由於它採用的是迭代式開發,因此這種開發方式的主要驅動核心是人
'Jenkins'是一個可擴展的持續集成引擎。 主要用於: 持續、自動地構建/測試軟件項目。 監控一些定時執行的任務。
https://blog.csdn.net/zhailihua/article/details/7899006
爲了預防消息丟失,rabbitmq提供了ack 即工做進程在收到消息並處理後,發送ack給rabbitmq,告知rabbitmq這時候能夠把該消息從隊列中刪除了。 若是工做進程掛掉 了,rabbitmq沒有收到ack,那麼會把該消息 從新分發給其餘工做進程。 不須要設置timeout,即便該任務須要很長時間也能夠處理。 ack默認是開啓的,工做進程顯示指定了no_ack=True
一、建立隊列和發送消息時將設置durable=Ture,若是在接收到消息尚未存儲時,消息也有可能丟失,就必須配置publisher confirm channel.queue_declare(queue='task_queue', durable=True) 二、返回一個ack,進程收到消息並處理完任務後,發給rabbitmq一個ack表示任務已經完成,能夠刪除該任務 三、鏡像隊列:將queue鏡像到cluster中其餘的節點之上。 在該實現下,若是集羣中的一個節點失效了,queue能自動地切換到鏡像中的另外一個節點以保證服務的可用性
默認消息隊列裏的數據是按照順序被消費者拿走, 例如:消費者1 去隊列中獲取奇數序列的任務,消費者2去隊列中獲取偶數序列的任務。 channel.basic_qos(prefetch_count=1) 表示誰來誰取,再也不按照奇偶數排列(同時也保證了公平的消費分發)
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是由Python開發的一個簡單、靈活、可靠的處理大量任務的分發系統, # 它不只支持實時處理也支持任務調度。 # http://www.cnblogs.com/wupeiqi/articles/8796552.html
# 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) }, }
pro_cel ├── celery_tasks # celery相關文件夾 │ ├── celery.py # celery鏈接和配置相關文件 │ └── tasks.py # 全部任務函數 ├── check_result.py # 檢查結果 └── send_task.py # 觸發任務
# 通常狀況使用的是從celeryapp中引入的app做爲的裝飾器:@app.task # django那種在app中定義的task則須要使用@shared_task
# 做用: 使用requests能夠模擬瀏覽器的請求 # 經常使用參數: url、headers、cookies、data json、params、proxy # 經常使用返回值: content iter_content text encoding="utf-8" cookie.get_dict()
# BeautifulSoup 用於從HTML或XML文件中提取、過濾想要的數據形式 #經常使用方法 解析:html.parser 或者 lxml(須要下載安裝) find、find_all、text、attrs、get
Selenium是一個用於Web應用程序測試的工具, 他的測試直接運行在瀏覽器上,模擬真實用戶,按照代碼作出點擊、輸入、打開等操做 爬蟲中使用他是爲了解決requests沒法解決javascript動態問題
#一、生成初始的Requests來爬取第一個URLS,而且標識一個回調函數 第一個請求定義在start_requests()方法內默認從start_urls列表中得到url地址來生成Request請求, 默認的回調函數是parse方法。回調函數在下載完成返回response時自動觸發 #二、在回調函數中,解析response而且返回值 返回值能夠4種: a、包含解析數據的字典 b、Item對象 c、新的Request對象(新的Requests也須要指定一個回調函數) d、或者是可迭代對象(包含Items或Request) #三、在回調函數中解析頁面內容 一般使用Scrapy自帶的Selectors,但很明顯你也能夠使用Beutifulsoup,lxml或其餘你愛用啥用啥。 #四、最後,針對返回的Items對象將會被持久化到數據庫 經過Item Pipeline組件存到數據庫 或者導出到不一樣的文件(經過Feed exports) http://www.cnblogs.com/wupeiqi/articles/6229292.html
方式一:內置添加代理功能 # -*- 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, }
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()
http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/autothrottle.html
# 有些狀況下,例如爬取大的站點,咱們但願能暫停爬取,以後再恢復運行。 # Scrapy經過以下工具支持這個功能: 一個把調度請求保存在磁盤的調度器 一個把訪問請求保存在磁盤的副本過濾器[duplicates filter] 一個能持續保持爬蟲狀態(鍵/值對)的擴展 Job 路徑 要啓用持久化支持,你只須要經過 JOBDIR 設置 job directory 選項。 這個路徑將會存儲全部的請求數據來保持一個單獨任務的狀態(例如:一次spider爬取(a spider run))。 必需要注意的是,這個目錄不容許被不一樣的spider 共享,甚至是同一個spider的不一樣jobs/runs也不行。 也就是說,這個目錄就是存儲一個 單獨 job的狀態信息。
在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'
'DepthMiddleware'是一個用於追蹤每一個Request在被爬取的網站的深度的中間件。 其能夠用來限制爬取深度的最大深度或相似的事情。 'DepthMiddleware'能夠經過下列設置進行配置(更多內容請參考設置文檔): 'DEPTH_LIMIT':爬取所容許的最大深度,若是爲0,則沒有限制。 'DEPTH_STATS':是否收集爬取狀態。 'DEPTH_PRIORITY':是否根據其深度對requet安排優先
Scrapy 提供了 pipeline 模塊來執行保存數據的操做。 在建立的 Scrapy 項目中自動建立了一個 pipeline.py 文件,同時建立了一個默認的 Pipeline 類。 咱們能夠根據須要自定義 Pipeline 類,而後在 settings.py 文件中進行配置便可
經過raise DropItem()方法
http://www.cnblogs.com/wupeiqi/articles/6229292.html
實現了分佈式爬蟲,url去重、調度器、數據持久化 'scheduler'調度器 'dupefilter'URL去重規則(被調度器使用) 'pipeline'數據持久化
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)
https://www.cnblogs.com/pupilheart/articles/9851936.html
https://www.cnblogs.com/pupilheart/articles/9851964.html
分佈式爬蟲的更新中。。。
'vitualenv'是一個獨立的python虛擬環境 如: 當前項目依賴的是一個版本,可是另外一個項目依賴的是另外一個版本,這樣就會形成依賴衝突, 而virtualenv就是解決這種狀況的,virtualenv經過建立一個虛擬化的python運行環境, 將咱們所需的依賴安裝進去的,不一樣項目之間相互不干擾
能夠經過對項目目錄掃描,自動發現使用了那些類庫,而且自動生成依賴清單。 pipreqs ./ 生成requirements.txt
1)PyFlakes:靜態檢查Python代碼邏輯錯誤的工具。 2)Pep8: 靜態檢查PEP8編碼風格的工具。 3)NedBatchelder’s McCabe script:靜態分析Python代碼複雜度的工具。 Python代碼分析工具:PyChecker、Pylint
1.B樹中同一鍵值不會出現屢次,而且有可能出如今葉結點,也有可能出如今非葉結點中。 而B+樹的鍵必定會出如今葉結點中,並有可能在非葉結點中重複出現,以維持B+樹的平衡。 2.由於B樹鍵位置不定,且在整個樹結構中只出現一次,
冒泡/選擇/插入/快排
https://www.cnblogs.com/Liqiongyu/p/5911613.html
http://www.cnblogs.com/feixuelove1009/p/6143539.html
工廠模式/單例模式等
leetcode是個題庫,裏面有多很編程題目,能夠在線編譯運行。 https://leetcode-cn.com/problemset/all/
1建立目錄 mkdir /data cd / mkdir data 2:查看目錄 ls ls -l 顯示詳細信息
Linux/Centos
PV訪問量(Page View),即頁面訪問量,每打開一次頁面PV計數+1,刷新頁面也是。 UV訪問數(Unique Visitor)指獨立訪客訪問數,一臺電腦終端爲一個訪客。
'QPS(Query Per Second)' 每秒查詢率,是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準
wsgi是一種通用的接口標準或者接口協議,實現了python web程序與服務器之間交互的通用性。 uwsgi:同WSGI同樣是一種通訊協議 uwsgi協議是一個'uWSGI服務器'自有的協議,它用於定義傳輸信息的類型, 'uWSGI'是實現了uwsgi和WSGI兩種協議的Web服務器,負責響應python的web請求。
# Supervisor: 是一款基於Python的進程管理工具,能夠很方便的管理服務器上部署的應用程序。 是C/S模型的程序,其服務端是supervisord服務,客戶端是supervisorctl命令 # 主要功能: 1 啓動、重啓、關閉包括但不限於python進程。 2 查看進程的運行狀態。 3 批量維護多個進程。
正向代理代理客戶端(客戶端找喲個代理去訪問服務器,服務器不知道你的真實IP) 反向代理代理服務器(服務器找一個代理給你響應,你不知道服務器的真實IP)
SSH 爲 'Secure Shell' 的縮寫,是創建在應用層基礎上的安全協議。 SSH 是目前較可靠,爲遠程登陸會話和其餘網絡服務提供的安全性協議。 利用 SSH 協議能夠有效防止遠程管理過程當中的信息泄露問題。
起初是百度,發現搜到的答案不精準,淨廣告 轉戰谷歌,但牆了;搗鼓怎麼FQ 還會去知乎、stackoverfloow、必應、思否(segmentfault)
python之禪(主要專一Python相關知識,做者:劉志軍) 碼農翻身(主要是Java的,但不光是java,涵蓋面很廣,做者:劉欣) 實驗樓(在線練項目) and so on
Numpy pandas(金融量化分析、聚寬) 百度AI 圖靈API 智能玩具
Domain-Driven Design
一、十進制 與 二進制之間的轉換
(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入。讀數要從前面的整數讀到後面的整數
方法:按權相加法,即將二進制每位上的數乘以權,而後相加之和便是十進制數。
例:將二進制數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