1、python基礎相關知識體系

python基礎

a. Python(解釋型語言、弱類型語言)和其餘語言的區別?

  1、編譯型語言:一次性,將所有的程序編譯成二進制文件,而後在運行。(c,c++ ,go)
     運行速度快。開發效率低

  2、解釋型語言:當你的程序運行時,一行一行的解釋,並運行。(python , PHP)
    運行速度相對較慢,可是調試代碼很方便,開發效率高

html

  3、混合型:(C#,Java)前端

  python特色:java

  1. python代碼結構清晰簡潔、簡單易學
  2. 開發效率很是高,Python有很是強大的第三方庫
  3. 可移植性--因爲python開源本質,Python程序無需修改就幾乎能夠在市場上全部的系統平臺上運行
  4. 可擴展性--能夠把你的部分程序用C或C++編寫,而後在你的Python程序中使用它們。
  5. 可嵌入性--能夠把Python嵌入你的C/C++程序,從而向你的程序用戶提供腳本功能。

二、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,而是經過網絡調用來交互,確保各程序之間的獨立性。
View Code

三、 請至少列舉5個 PEP8 規範(越多越好)

一、縮進使用4個空格鍵。不建議使用tab
二、運算符左右隔空一格
三、類名首字母大寫
四、函數命名所有使用小寫,能夠用下劃線分割
五、常量或全局變量使用大寫,能夠用下劃線分割
六、不建議import os,time
七、建議使用塊註釋

參考python

四、 經過代碼實現以下轉換

print("轉換爲二進制爲:", bin(dec)) int("01010101",2) print("轉換爲八進制爲:", oct(dec)) print("轉換爲十六進制爲:", hex(dec))

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

def addr2dec(addr):
    "將點分十進制IP地址轉換成十進制整數"
    items = [int(x) for x in addr.split(".")]
    print(items)
    return sum(items[i] << [24, 16, 8, 0][i] for i in range(4))

print(addr2dec("10.3.9.12"))

六、ascii、unicode、utf-八、gbk 區別?

python2內容進行編碼(默認ascii),而python3對內容進行編碼的默認爲utf-8。
ascii 最多隻能用8位來表示(一個字節),即:2**8 = 256,因此,ASCII碼最多隻能表示 256 個符號。 1-->48 A-->65 a-->97
unicode 規定雖有的字符和符號最少由 16 位來表示(2個字節),即:2 **16 = 65536,
UTF-8 是對Unicode編碼的壓縮和優化,他再也不使用最少使用2個字節,而是將全部的字符和符號進行分類:
     A 1個字節 歐洲 一個字 2個字節 亞洲 一個子 3個字節
gbk A : 1個字節 中 :兩個字節

    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 False and 1     #Falsemysql

七、字節碼和機器碼的區別? 

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

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

八、列舉 Python2和Python3的區別?

一、默認解釋器編碼:
py2: ascii
  py3: utf-8

二、字符串:
  py2: str:字符串 -->字節
     unicode:u"shh"
  py3: bytes 和 str

三、range和xrange
  py2 range返回list xrange返回生成器
  py3 range返回生成器

四、py2 int、long
  py3 int

五、py2 yield
  py3 yiled、 yield from

六、py2 新式類和經典類
  py3 新式類

七、py2 raw_input py3 input

八、py2 print py3 print()

九、Python3和Python2中 int 和 long的區別? 

python3去除了long類型,如今只有一種整型——int,但它的行爲就像python2版本的longnginx

十、 布爾值爲False的常⻅值都有那些?

0 空列表字符串  負數 不成立的表達式  None 等c++

十一、文件操做時:xreadlines和readlines的區別?

readlines     返回一個列表程序員

xreadlines   返回一個生成器

十二、數據類型

不可哈希:list dict set   可哈希:int str bool None tuple
- 字符串 strip()去除
           find()找不到返回-1 、index()找不到報錯
           split()分割
           join()拼接
           replace()替換
- 字典 pop() 刪除 建立字典的三種方法:一、直接表達 二、dict(name="cao") 三、dict.formkeys(["key","key"],value)
          update()
          clear()清空
          get()
          dict.items()
- 元組tuple 只讀 按str索引方法去查 - 列表 append()
          inset()按索引增長
          extend()迭代增長
          conut()
          sort()排序
          index()
          rserver()反轉
- 集合   add() update() remove() del() pop() clear() 交集$ 並集| 差集-
collections  Python內建的一個集合模塊,提供了許多有用的集合類。
Counter是一個簡單的計數器,例如,統計字符出現的個數:
OrderedDict能夠實現一個FIFO(先進先出)的dict,當容量超出限制時,先刪除最先添加的Key:
deque是爲了高效實現插入和刪除操做的雙向列表,適合用於隊列和棧:
defaultdict使用dict時,若是引用的Key不存在,就會拋出KeyError。若是但願key不存在時,返回一個默認值,就能夠用defaultdict:

1三、*arg和**kwarg做用

*args    :接收全部按照位置傳的參數,接收到的是參數組成的元祖
**kwargs :接收全部按照關鍵字傳的參數,接收到的是參數組成的字典

1四、Python垃圾回收機制? 

引用計數 (對象被引用時+1,引用的對象被刪除時-1)

標記清除 

分代回收(系統中的全部內存塊根據其存活時間劃分爲不一樣的集合,每個集合就成爲一個「代」,垃圾收集的頻率隨着「代」的存活時間的增大而減少)

1五、深淺拷貝

在Python中對象的賦值其實就是對象的引用。當建立一個對象,把它賦值給另外一個變量的時候,python並無拷貝這個對象,只是拷貝了這個對象的引用而已。

淺拷貝:拷貝了最外圍的對象自己,內部的元素都只是拷貝了一個引用而已。也就是,把對象複製一遍,可是該對象中引用的其餘對象我不復制

深拷貝:外圍和內部元素都進行了拷貝對象自己,而不是引用。也就是,把對象複製一遍,而且該對象中引用的其餘對象我也複製。

###############################

淺拷貝copy ,第一層建立的是新的內存地址,而從第二層開始,指向的都是同一個內存地址,因此,對於第二層以及更深的層數來講,與原內存地址不變。

l1 = [1,[22,33,44],3,4,]
l2 = l1.copy()
l1[1].append('55')

print(l1,id(l1),id(l1[1]))      #[1, [22, 33, 44, '55'], 3, 4] 1787518244744 1787518244808
print(l2,id(l2),id(l2[1]))        #[1, [22, 33, 44, '55'], 3, 4] 1787518244616 1787518244808
############
l1[1].append("cao")
print(l1)   #[1, [22, 33, 44, '55', 'cao'], 3, 4]
print(l2)  #[1, [22, 33, 44, '55', 'cao'], 3, 4]

#########################
l1[0] = "chao"
print(l1)   #['chao', [22, 33, 44, '55'], 3, 4]
print(l2)  #[1, [22, 33, 44, '55'], 3, 4]
View Code

深拷貝deepcopy,兩個是徹底獨立的,改變任意一個的任何元素(不管多少層),另外一個絕對不改變。

import copy
l1 = [1,[22,33,44],3,4,]
l2 = copy.deepcopy(l1)

print(id(l1[1]))
print(id(l2[1]))
print("="*20)

l1[0] = 111
print(l1)
print(l2)
print("="*20)

l1[1].append('barry')
print(l1)
print(l2)

############
1742824920904
1742824920520
====================
[111, [22, 33, 44], 3, 4]
[1, [22, 33, 44], 3, 4]
====================
[111, [22, 33, 44, 'barry'], 3, 4]
[1, [22, 33, 44], 3, 4]
View Code

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

1七、求結果

v = dict.fromkeys(['k1','k2'],[])
print(v)
v["k1"].append(666)
print(v)
v["k1"] = 777
print(v)
{'k1': [], 'k2': []}
{'k1': [666], 'k2': [666]}
{'k1': 777, 'k2': [666]}
##############
def num():
return [lambda x:x+1 for i in range(4)]

print([m(2) for m in num()]) #[3,3,3,3]
print([m(1) for m in num()]) #[2,2,2,2]

################
print([ i % 2 for i in range(10) ])  #[0,1,0,1,0,1,0,1,0,1]
print(( i % 2 for i in range(10) )) #生成器
###################
a. 1 or 2
 1
b. 1 and 2
 2
c. 1 < (2==2)
 False
d. 1 < 2 == 2 Ture
not > and > or

函數

- 函數參數傳遞的是什麼? 引用、內存地址

#魔性的用法:默認參數儘可能避免使用可變數據類型
類型一:
lst = []
def func(l = lst):  #默認參數
    l.append(1)
    print(l)

func()      #[1]
func()      #[1,1]

  默認參數只會被執行一次:第一次調用函數時,默認參數被初始化爲【】,之後每次調用時都會使用已經初始化的【】。
類型二:
lst = []
def func(l = lst):
    l.append(1)
    print(l)

func([])    #[1]
func([])    #[1]

類型三:
def func(a1,a2=[]):
    a2.append(a1)
    print(a2)

func(1)        #[1,]
func(3,[])      #[3,]
func(4)        #[1,4]

類型四:
def func(a1,a2=[]):
    a2.append(a1)
    return a2


l1 = func(1)
print(l1)       # [1,]
l2 = func(3,[])
print(l2)       # [3, ]
l3 = func(4)
print(l3)       # [1,4]

類型五:
def func(a1,a2=[]):
    a2.append(a1)
    return a2

l1 = func(1)     # l1=[1,4]
l2 = func(3,[])  # l2=[3,]
l3 = func(4)     # l3=[1,4]
print(l2)
print(l1)
print(l3)
示例

1七、lambda、三元表達式

簡單的函數:     my_lambda = lambda arg : arg + 1
簡單的條件語句: val= "cao" if 1==1 else "chao"

各類推導式

列表生成式
s1=[i*2 for i in range(5)]
print(s1)
生成器表達式
s=(i*2 for i in range(5) )
print(s.__next__())
print(next(s))

基於列表生成式和lambda應用

val = [lambda :i + 1 for i in range(10)]    [function,funtion...]
print(val,type(val))        #<class 'list'>   
print(val[0],type(val[0]))  #<class 'function'>
data = val[0]()
print(data)         #10
應用到閉包函數:
當調用函數的時候,都會優先在外部做用域中查找i變量,這時列表生產式中循環立馬執行,最後i賦值爲9

1八、閉包

def foo():
    m=3
    n=5
    def bar():
        a=4
        return m+n+a
    return bar
>>>bar =  foo()
>>>bar()
12

簡單的說,這種內部函數可使用外部函數變量的行爲,就叫閉包。

閉包的意義與應用:延遲計算:

閉包的意義:返回的函數對象,不只僅是一個函數對象,在該函數外還包裹了一層做用域,這使得,該函數不管在何處調用,優先使用本身外層包裹的做用域

#應用領域:延遲計算(原來咱們是傳參,如今咱們是包起來)

裝飾器就是閉包函數的一種應用場景

1九、- 常見內置函數:

- map - filter
map()函數接收兩個參數,一個是函數,一個是可迭代對象,map將傳入的函數依次做用到序列的每一個元素,並把結果做爲新的list返回。
def mul(x):
    return x*x

n=[1,2,3,4,5]
res=list(map(mul,n))
print(res)  #[1, 4, 9, 16, 25]

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]
View Code
- isinstance - type
isinstance() 函數來判斷一個對象是不是一個已知的類型,相似 type()。

isinstance() 與 type() 區別:

type() 不會認爲子類是一種父類類型,不考慮繼承關係。

isinstance() 會認爲子類是一種父類類型,考慮繼承關係。

若是要判斷兩個類型是否相同推薦使用 isinstance()。
View Code
- zip
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)]
View Code
- reduce
from functools import reduce
reduce() 函數會對參數序列中元素進行累積。

用傳給reduce中的函數 function(有兩個參數)先對集合中的第一、2個元素進行操做,獲得的結果再與第三個數據用function函數運算,最後獲得一個結果。

>>>def add(x, y) :            # 兩數相加
...     return x + y
... 
>>> reduce(add, [1,2,3,4,5])   # 計算列表和:1+2+3+4+5
15
>>> reduce(lambda x, y: x+y, [1,2,3,4,5])  # 使用 lambda 匿名函數
15
View Code

生成器、迭代器、裝飾器

20、生成器

生成器:一個函數調用時返回一個迭代器,或 函數中包含yield語法,那這個函數就會變成生成器;

應用場景:

- range/xrange
  - py2: range(1000),當即建立;xrange(1000)生成器;
  - py3: range(1000)生成器; 沒有xrange

-redis獲取值
  hscan_iter 利用yield封裝hscan建立生成器,實現分批去redis中獲取數據

2一、迭代器

迭代器:含有__iter__和__next__方法 (包含__next__方法的可迭代對象就是迭代器)
   特色:
      訪問者不須要關心迭代器內部的結構,僅需經過next()方法不斷去取下一個內容(惰性計算)
      不能隨機訪問集合中的某個值 ,只能從頭至尾依次訪問
      訪問到一半時不能往回退
      便於循環比較大的數據集合,節省內存

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

應用場景:

- wtforms中對form對象進行循環時候,顯示form中包含的全部字段。

 - 列表、字典、元組

總結:若是想要讓一個對象能夠被for循環,那麼就須要在當前類中定義__iter__

 2二、裝飾器

問題:什麼是裝飾器?
  
在對原函數不進行修改時,在函數執行前和執行後添加功能

問題:手寫裝飾器
import functools
def warpper(func):
@functools.wraps(func) #保留原函數信息
def inner(*args,**kwargs):
#執行函數前
return func(*args,**kwargs)
#執行函數後
return inner

# 1. 執行wapper函數,並將被裝飾的函數當作參數。 wapper(index)
# 2. 將第一步的返回值,從新賦值給 新index = wapper(老index)
@warpper #index=warpper(index)
def index(x):
return x+100
問題:應用場景
    django: csrf 內置認證、緩存
     flask: 路由、before_request

帶參數裝飾器:flask:路由
       CBV as_view()

2三、偏函數

偏函數:
import functools
def func(a1, a2, a3):
    return a1 + a2 + a3

new_func = functools.partial(func, 11, 2)  #將11,2依次傳入到func函數的前兩個參數
print(new_func(3))

應用場景
falsk中取值時 經過localproxy 、偏函數、localstack、local

2四、談談面向對象認識

-繼承、封裝、多態(簡單描述)
  python中一切皆對象     

封裝:
  其實就是將不少數據封裝到一個對象中,相似於把不少東西放到一個箱子中,
  如:一個函數若是好多參數,起始就能夠把參數封裝到一個對象再傳遞。
應用場景:
  - django rest framework中的request對象。
  - flask中:request_context/app_context對象

繼承:
  若是多個類中都有共同的方法,那麼爲了不反覆編寫,就能夠將方法提取到基類中實現,讓全部派生類去繼承便可。

應用場景:
  - rest frmawork 視圖
  - 版本、認證、分頁


多態:
  python自己就是多態的,崇尚鴨子模型,只要會呱呱叫我麼就認爲它是鴨子。

class A:
    def send(self):
        print("A")
class B:
    def f(self):
        print("B")

def func(arg):
    arg.send()

obj = A()
func(obj)
多態
-雙下劃線:
     __getattr__
       -CBV       -django配置文件       -wtforms中的Form()示例化中 將"_fields中的數據封裝到From類中"

     __mro__ wtform中 FormMeta中繼承類的優先級

      __dict__    

     __new__ ,實例化可是沒有給當前對象
        wtforms,字段實例化時返回:不是StringField,而是UnboundField
       rest frawork many=Turn  中的序列化
       單例模式      __call__        flask 請求的入口app.run()      字段生成標籤時:字段.__str__
=> 字段.__call__ => 插件.__call__ __iter__ 循環對象是,自定義__iter__         wtforms中BaseForm中循環顯示全部字段時定義了__iter__ -metaclass     - 做用:用於指定當前類使用哪一個類來建立     - 場景:在類建立以前定製操做     示例:wtforms中,對字段進行排序。

2五、super做用

子類繼承父類的方法,其繼承順序按照__mro__

2六、靜態方法和類方法區別

staticmethod

classmethod   須要傳入參數cls當前類   

兩種方法都不須要實例化就可使用l類.方法或對象.方法

2六、⾯向對象深度優先和廣度優先是什麼?

Python的類能夠繼承多個類,Python的類若是繼承了多個類,那麼其尋找方法的方式有兩種

當類是經典類時,多繼承狀況下,會按照深度優先方式查找

當類是新式類時,多繼承狀況下,會按照廣度優先方式查找

簡單點說就是:經典類是縱向查找,新式類是橫向查找

經典類和新式類的區別就是,在聲明類的時候,新式類須要加上object關鍵字。在python3中默認全是新式類

2七、什麼是函數什麼是方法

from types import MethodType,FunctionType

class Foo(object):
    def fetch(self):
        pass
       Foo.fetch   此時fetch爲函數
print(isinstance(Foo.fetch,MethodType))
print(isinstance(Foo.fetch,FunctionType)) # True

obj = Foo()
       obj.fetch  此時fetch爲方法
print(isinstance(obj.fetch,MethodType)) # True
print(isinstance(obj.fetch,FunctionType))

2八、單例模式

單例模式:一個類只能有一個實例化對象

應用場景:Django中的admin組件中admin.site()就是由單例模式建立的,其中封裝了全部的表對象

#基於new
class
Singleton(object):
  每一次實例化的時候,返回同一個instance對象 def __new__(cls,
*args,**kwargs): if not hasattr(cls,"instance"): cls.instace=super(Singleton,cls).__new__(cls,*args,**kwargs) return cls.instace a=Singleton() b=Singleton() print(a,b) print(a is b)

#基於裝飾器
def Singleton(cls):
_instance={}
  
def _singleton(*args,**kwargs):
if cls not in _instance:
_instance[cls]=cls(*args,**kwargs)
return _instance[cls]
return _singleton

@Singleton
class A(object):
a=1
def __init__(self,x=None):
self.x=x

c=A(2)
b=A(3)
print(c is b)

模塊 

2九、經常使用模塊

os、sys、json、re、logging、random、time、requests、beautifulsoup,

os模塊是與操做系統交互的一個接口 ,提供了不少方法來處理文件和目錄

  os.remove(‘path/filename’) 刪除文件

  os.rename(oldname, newname) 重命名文件

  os.walk() 生成目錄樹下的全部文件名

  os.chdir('dirname') 改變目錄
  os.getcwd() 取得當前工做目錄
  os.path.getsize() 返回文件大小
View Code

sys模塊負責程序與python解釋器的交互,提供了一系列的函數和變量,用於操控python的運行時環境。

sys.argv           命令行參數List,第一個元素是程序自己路徑
sys.exit(n)        退出程序,正常退出時exit(0),錯誤退出sys.exit(1)
sys.version        獲取Python解釋程序的版本信息
sys.path           返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform       返回操做系統平臺名稱
View Code

logging  :記錄日誌,分爲五種級別,debug,info ,warning,error,critical

random

random.random()   0-1隨機數

random.randint(1,9)  1-9 隨機整數

requests  獲取頁面html和xml

json 序列化

30、re正則

.     匹配除換行符之外的任意字符
\w    匹配字母或數字或下劃線
\s    匹配任意的空白符
\d    匹配數字
\n    匹配一個換行符
\t    匹配一個製表符
\b    匹配一個單詞的結尾
^    匹配字符串的開始
$    匹配字符串的結尾
\W    
匹配非字母或數字或下劃線
\D    
匹配非數字
\S    
匹配非空白符
a|b    
匹配字符a或字符b
()    
匹配括號內的表達式,也表示一個組
[...]    
匹配字符組中的字符
[^...]    
匹配除了字符組中字符的全部字符
 

用法說明
*    重複零次或更屢次
+    重複一次或更屢次
?    重複零次或一次
{n}    重複n次
{n,}    重複n次或更屢次
{n,m}    重複n到m次
View Code

一、寫一個郵箱、手機號、IP

#匹配手機號
import re

def phone(arg):
    s=re.match("^(13|14|15|18)[0-9]{9}$",arg)
    if s:
        return "正確"
    return "錯誤"

print(phone("23722751552"))
#匹配郵箱
  re.match("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$",arg)
#匹配IP
re.match("\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b",arg)
?: 優先匹配
\b 匹配一個單詞的結尾

3一、match和search的區別

  re.match只匹配字符串的開始,若是字符串開始不符合正則表達式,則匹配失敗,函數返回None;

  re.search匹配整個字符串,直到找到一個匹配。

1 import re
2 s="fnfffidvvgf"
3 
4 m=re.match("fi",s)
5 print(m)  #None
6 s=re.search("fi",s).group()
7 print(s)  #fi

3二、貪婪匹配與非貪婪匹配

  貪婪匹配:   匹配1次或屢次<.+>     匹配0次或屢次<.*>

  非貪婪匹配:匹配0次或1次<.?>

34. 如何⽤⼀代碼⽣成[1,4,9,16,25,36,49,64,81,100]

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

35 、⼀⾏代碼實現刪除列表中重複的值    

list(set([1,2,45,5,2]))

3六、用Python實現一個二分查找的函數

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(1, li)  # 元素索引爲2
View Code

3七、給出路徑找文件

方法一: 使用os.walk
file-- 是你所要便利的目錄的地址, 返回的是一個三元組(root,dirs,files)。

root 所指的是當前正在遍歷的這個文件夾的自己的地址
dirs 是一個 list ,內容是該文件夾中全部的目錄的名字(不包括子目錄)
files 一樣是 list , 內容是該文件夾中全部的文件(不包括子目錄)
def open_2(file):

    for root, dirs , files in os.walk(file):
        print("ss",files)
        for filename in files:
            print(os.path.abspath(os.path.join(root, filename)))   #返回絕對路徑

open_2("F:\搜索")


方法二:
import os
def open(files):

    for dir_file in os.listdir(files):
        # print("ss",dir_file)   #遞歸獲取全部文件夾和文件
        files_dir_file = os.path.join(files, dir_file) 

        if os.path.isdir(files_dir_file):  #是否是文件夾
            open(files_dir_file)
        else:
            print(files_dir_file)

open("F:\搜索")


並將下面的全部文件內容寫入到一個文件中
def open_2(file):
    for root, dirs , files in os.walk(file):
        for filename in files:
            with open(os.path.abspath(os.path.join(root, filename)), "r") as f:
                for i in f.readlines():
                    print(i)
                    with open("./cao.txt","a",encoding="utf-8") as f2:
                        f2.write(i)
                        f2.write("\n")
open_2("F:\搜索")
示例

3八、建立、刪除文件

1 # 建立一個文件
2 open("chao.txt","w",encoding="utf-8")
3 import os
#刪除文件
4 os.remove("chao.txt")

3九、第三方軟件安裝

  一、pip3 包管理器

  二、源碼安裝

    -下載、解壓

    -python  setup.py  bulid

    -python  setup.py  install

40、一、二、三、四、5 能組成多少個互不相同且⽆重複的三位數

使用python內置的排列組合函數(不放回抽樣排列)
product 笛卡爾積  (有放回抽樣排列)
permutations 排列  (不放回抽樣排列)
combinations 組合,沒有重複  (不放回抽樣組合)
combinations_with_replacement 組合,有重複  (有放回抽樣組合)

import itertools
print(len(list(itertools.permutations('12345', 3))))  # 60

50、什麼是反射

反射的核心本質就是以字符串的形式去導入個模塊,經過字符串的形式操做對象相關的屬性

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

導入模塊:

x=__import__("time")
print(x.time())

5一、metaclass做用?以及應用場景? 

指定當前類是由那個類建立的

默認爲type

- 場景:在類建立以前定製操做 - 示例:wtforms中,對字段進行排序。

5二、異常處理理寫法以及如何主動跑出異常(應⽤用場景) 

try:
    fh = open("testfile", "w")
    try:
        fh.write("這是一個測試文件,用於測試異常!!")
    finally:
        print "關閉文件"
        fh.close()
except IOError:
    print "Error: 沒有找到文件或讀取文件失敗"

raise拋異常

inputValue=input("please input a int data :")
if type(inputValue)!=type(1):
    raise ValueError
else:
    print inputValue
View Code

5三、json序列化時,能夠處理的數據類型有哪些?如何定製支持datetime類型?

整數、字符創、字典、列表、bool、None

重寫default()

import json
import datetime

dic = {
    'k1':123,
    'ctime':datetime.datetime.now()
}

class MyJSONEncoder(json.JSONEncoder):
    def default(self,o):
        if isinstance(o,datetime.datetime):
            return o.strftime("%Y-%m-%d")
        else:
            return super(MyJSONEncoder,self).default(o)

v=json.dumps(dic,cls=MyJSONEncoder)
print(v)
View Code

5四、json序列化時,默認遇到中文會轉換成unicode,若是想要保留中文怎麼辦

 json.dumps(xxxx,ensure_ascii=False)

5五、有用過with statement嗎?它的好處是什麼? 

上下文管理器:

在使用Python編程中,能夠會常常碰到這種狀況:有一個特殊的語句塊,在執行這個語句塊以前須要先執行一些準備動做;當語句塊執行完成後,須要繼續執行一些收尾動做。

例如:當須要操做文件或數據庫的時候,首先須要獲取文件句柄或者數據庫鏈接對象,當執行完相應的操做後,須要執行釋放文件句柄或者關閉數據庫鏈接的動做。

又如,當多線程程序須要訪問臨界資源的時候,線程首先須要獲取互斥鎖,當執行完成並準備退出臨界區的時候,須要釋放互斥鎖。

對於這些狀況,Python中提供了上下文管理器(Context Manager)的概念,能夠經過上下文管理器來定義/控制代碼塊執行前的準備動做,以及執行後的收尾動做。
在Python中,能夠經過with語句來方便的使用上下文管理器,
with語句能夠在代碼塊運行前進入一個運行時上下文(執行__enter__方法),並在代碼塊結束後退出該上下文(執行__exit__方法)。

操做文件:with open

Flask中的離線腳本:

with  app.app_context():  

  pass

5六、簡述 yield和yield from關鍵字。

yiled:一、一個函數中含有yield關鍵字,此函數爲生成器,

   二、生成器調用是不會當即執行,必須使用next()(結束是會報錯)或send()或for調用執行

   三、yield能夠返回值也能夠取值(生產者消費者模式)

   四、調用生成器send方法傳遞數據時,必須先調用next(生成器)或者生成器.send(None)方法

yield from 可讓生成器,直接在其餘函數中調用,

網絡編碼

5六、OSI 七層協議

 互聯網協議按照功能不一樣分爲osi七層或tcp/ip五層或tcp/ip四層

物理層:主要是基於電器特性發送高低電壓(電信號),高電壓1,低電壓0,設備有網卡、網線、集線器,中繼器,雙絞線等!  單位:bit比特

數據鏈路層:定義了電信號的分組方式(電信號0和1沒有實際意義)規定了報頭(18字節)和數據     設備有:網橋、以太網交換機、網卡   單位:幀

網絡層:主要功能是將ip地址翻譯成對應的mac物理地址    路由  arp協議

傳輸層:創建端口到端口之間的通訊    tcp協議udp協議

會話層:創建客戶端與服務端鏈接

表示層:對來自應用層的命令和數據進行解釋,並按照必定的格式傳送給會話層

應用層:規定應用程序的數據格式

5七、什麼是C/S架構和B/S架構

C/S架構:
  client端與server端的服務架構(客戶端能夠包含一個或多個在用戶的電腦上運行的程序)

 B/S架構:隸屬於C/S架構的
   Broswer端(網頁端)與server端
    優勢:統一了全部應用程序的入口、使用方便、輕量級

5八、三次握手四次揮手

  三次握手:

    SYC=1(創建鏈接)  ACK(確認請求)

    一、客戶端(Client)向服務端(Server)發送一次請求(請求鏈接)

    二、服務端確認並回復客戶端(ACK=1, SYC=1,並在seq基礎上產生一個隨機數發給客戶端)

    三、客戶端檢驗確認請求(ACK=1)     此時客戶端與服務端就創建了鏈接

  四次揮手:

    FAN=1(斷鏈接) ACK=1(確認請求)

    一、客戶端向服務端發一次請求(FAN=1)

    二、服務端回覆客戶端 (ACK=1)  (斷開客戶端—>服務端)

    三、服務端再向客戶端發請求(FAN=1)  (由於有數據傳輸,因此二、3不能合併)

    四、客戶端確認請求(ACK=1)        (斷開服務端--->客戶端)

 5九、爲什麼基於tcp協議的通訊⽐基於udp協議的通訊更可靠

  tcp是基於鏈接的,必須先啓動服務端,而後再啓動客戶端去鏈接服務端(三次握手,四次揮手)

  udp是無鏈接的,先啓動那一端均可以  (應用:QQ聊天)     (可能會產生丟包,由於服務端不監聽客戶端只負責發送數據,無論客戶端是否收到數據)

60、什麼是socket?簡述基於tcp協議的套接字通訊流程

兩個程序經過一個雙向的通訊鏈接實現數據的交換,這個鏈接的一端稱爲一個socket   
TCP協議操做:
   服務器端:                    客戶端
     建立套接字                    建立套接字 
     綁定ip和端口                  綁定ip和端口
     監聽                          鏈接服務器
     accept等待鏈接                通訊(收recv,發send)
     通訊(收recv,發send)
 UDP:傳輸速度快 不面向鏈接,不能保證數據的完整性 服務器端: 客戶端: 建立套接字 綁定套接字 綁定ip和端口 通訊(收recvfrom,發sendto) 通訊(收recvfrom,發sendto)

6一、什麼是粘包? socket 中形成粘包的緣由是什麼? 哪些狀況會發生粘包現象?

粘包只會在tcp中產生,由於tcp是面向鏈接的、面向流(能夠將多個小數據合併成一個大的數據包發送)這樣以來,接收方不知道 數據包中的數據是以什麼未分割數據的,就會產生粘包
           而udp是無鏈接的、面向消息的(他不會將多個消息合併成一個大消息發送的,即便是空消息也會發送(自動加上消息頭的))

兩種狀況:
一、發送端須要等緩衝區滿才發送出去,形成粘包(發送數據時間間隔很短,數據了很小,會合到一塊兒,產生粘包)
二、接收方不及時接收緩衝區的包,形成多個包接收(客戶端發送了一段數據,服務端只收了一小部分,服務端下次再收的時候仍是從緩衝區拿上次遺留的數據,產生粘包)

6二、IO多路複用的做用? 

監聽多個socket是否發生變化

- select,內部循環檢測socket是否發生變化;最多檢測1024個socket
- poll,    內部循環檢測socket是否發生變化;
- epoll,  使用回調函數的機制(自定義了三個函數)任務完成時自動調用的函數

6三、交換機與路由器的區別

交換機                             路由器(小型交換機)
數據連接層         網絡層
利用mac地址肯定傳輸數據的目的地      利用網關ip地址肯定傳輸數據的目的地
                      有防火牆

6四、什麼是防火牆以及做用?

防火牆是內部網與外部網之間的一種訪問控制設備。

它可經過監測、限制、更改跨越防火牆的數據流,儘量地對外部屏蔽網絡內部的信息、結構和運行情況, 以此來實現網絡的安全保護。

6五、什麼是局域網和廣域網?

局域網:是指在小範圍內由多臺計算機互聯成的計算機組    廣域網:

6六、子網掩碼

 將某個IP地址劃分紅網絡地址主機地址兩部分。

ip和子網掩碼作按位與運算,能夠獲得網關ip

子網掩碼是用來判斷任意兩臺計算機的IP地址是否屬於同一個子網絡的根據。

併發編程

6五、進程、線程、協程的區別

進程:正在執行的一個程序或者一個任務,而執行任務的是cpu
    每一個進程都有本身的獨立內存空間,不一樣進程經過進程間通訊IPC(隊列,管道)來通訊。
    開進程消耗比較大,且上下文進程間的切換開銷比較大,
    相比線程數據相對比較穩定安全。

線程:線程是進程的一個實體,是CPU調度和分派的基本單位
    線程間通訊主要經過共享內存,開線程資源開銷小,上下文切換很快,但相比進程不夠穩定容易丟失數據。

協程:是一種「微線程」,實際並不存在,是程序員人爲創造出來的控制程序調度的(程序執行一段代碼,切換執行另外一段代碼)它能夠實現單線程下的併發、
    一、程序執行遇到IO切換,性能提升,實現了併發
    二、無IO時切換,性能下降
  優勢:
    1. 協程的切換開銷更小,屬於程序級別的切換,操做系統徹底感知不到,於是更加輕量級
    2. 單線程內就能夠實現併發的效果,最大限度地利用cpu

一、進程多與線程比較

1.線程是程序執行的最小單位,而進程是操做系統分配資源的最小單位;

2.一個進程由一個或多個線程組成,線程是一個進程中代碼的不一樣執行路線;

3.進程之間相互獨立,但同一進程下的各個線程之間共享程序的內存空間(包括代碼段、數據集、堆等)及一些進程級的資源(如打開文件和信號),某進程內的線程在其它進程不可見;

4.開啓進程比開線程資源開銷大,線程上下文切換比進程上下文切換要快得多。由於線程共享進程內的資源

二、協程與線程進行比較

  1) 一個線程能夠多個協程,一個進程也能夠單獨擁有多個協程,這樣python中則能使用多核CPU。

  2) 線程進程都是同步機制,而協程則是異步

  3) 協程能保留上一次調用時的狀態,每次過程重入時,就至關於進入上一次調用的狀態

 

進程是系統分配系統資源的最小單位,進程之中能夠有多個線程,一個進程中的全部資源共享,進程之間資源不會共享;
線程是系統進行任務調度的最小單位,一個進程中的線程共享該進程的系統資源,線程是輕量級的進程;
協程又稱微線程,輕量級線程,執行具備原子性,執行須要程序員來調用度,能夠執行效率高

 

三、多線程用於IO密集型,如socket,爬蟲,web

  多進程用於計算密集型,如金融分析

四、使用concurrent.futures開線程池和進程池

五、進程鎖與線程鎖

  進程鎖:

#加鎖能夠保證多個進程修改同一塊數據時,同一時間只能有一個任務能夠進行修改,即串行的修改,沒錯,速度是慢了,但犧牲了速度卻保證了數據安全。
雖然能夠用文件共享數據實現進程間通訊,但問題是:
1.效率低(共享數據基於文件,而文件是硬盤上的數據)
2.須要本身加鎖處理


#所以咱們最好找尋一種解決方案可以兼顧:1、效率高(多個進程共享一塊內存的數據)2、幫咱們處理好鎖問題。這就是mutiprocessing模塊爲咱們提供的基於消息的IPC通訊機制:隊列和管道。
1 隊列和管道都是將數據存放於內存中
2 隊列又是基於(管道+鎖)實現的,可讓咱們從複雜的鎖問題中解脫出來,
咱們應該儘可能避免使用共享數據,儘量使用消息傳遞和隊列,避免處理複雜的同步和鎖問題,並且在進程數目增多時,每每能夠得到更好的可獲展性。

  線程鎖:

  GIL和Lock

  解決死鎖問題使用遞歸鎖(Rlock)

7三、進程鎖和線程鎖的做用?

進程鎖:爲了不多個進程同時同享一個資源,加鎖限制同一時間只能有一個進程修改數據,從而保證數據安全   (可使用隊列和管道)

線程鎖:同一時間只能一個線程訪問加鎖的資源,可是其餘線程能夠訪問未加鎖的資源

6六、GIL鎖

GIL是全局解釋器鎖,它的本質是一把互斥鎖,將併發運行變成串行,以此來控制同一時間內共享數據只能被一個任務所修改,進而保證數據安全。(同一時刻同一進程中只有一個線程被執行)

6六、GIL與lock的區別

鎖的目的是爲了保護共享的數據,同一時間只能有一個線程來修改共享的數據

結論:保護不一樣的數據就應該加不一樣的鎖。

GIL 與Lock是兩把鎖,保護的數據不同,GIL是解釋器級別的(固然保護的就是解釋器級別的數據,好比垃圾回收的數據),
                    Lock是保護用戶本身開發的應用程序的數據,很明顯GIL不負責這件事,只能用戶自定義加鎖處理

6七、進程池和線程池

進程池;

from concurrent.futures import ProcessPoolExecutor
import time,os
def piao(name,n):
    print('%s '%(name))
    time.sleep(2)
    return n**3
if __name__=='__main__':
    p = ProcessPoolExecutor(4)
    objs= []
    for i in range(10):
        obj = p.submit(piao,'sb %s'%i,i)
        objs.append(obj)   
    p.shutdown(wait=True)
    print("",os.getpid())
    for obj in objs:
        print(obj.result())
異步調用
from concurrent.futures import ProcessPoolExecutor
import time,os
def piao(name,n):
    print('%s is pioing %s'%(name,os.getpid()))
    return n**2
if __name__=='__main__':
    p = ProcessPoolExecutor(4)
    for i in range(10):
        res = p.submit(piao,'alex %s'%i,i).result()
        print(res)
    p.shutdown(wait=True)
    print('',os.getpid())
同步調用

線程池:

from concurrent.futures import ThreadPoolExecutor
from threading import current_thread
import time,random
def task(n):
    print('%s is running' %current_thread().getName())
    time.sleep(random.randint(1,3))
    return n**2

if __name__ == '__main__':
    # t=ProcessPoolExecutor() #默認是cpu的核數
    # import os
    # print(os.cpu_count())

    t=ThreadPoolExecutor(3) #默認是cpu的核數*5
    objs=[]
    for i in range(10):
        obj=t.submit(task,i)
        objs.append(obj)
        
    t.shutdown(wait=True)
    for obj in objs:
        print(obj.result())
    print('',current_thread().getName())
View Code

6八、threading.local的做用?

爲每個線程開闢一塊內存空間存數據

6九、進程之間如何進行通訊?

一、管道(無名管道、有名管道)
二、消息隊列
三、信號量
四、信號
五、共享內存地址
六、socket

70、什麼是arp協議?

 經過ip地址獲取mac地址的一種協議

7一、什麼是併發和並行?

併發:是一種僞並行,單個cpu能夠利用多道技術實現「併發」

並行:多個任務能夠同時運行,多cpu才能實現

7二、解釋什麼是異步非阻塞?

  - 非阻塞:程序執行過程當中遇到IO不等待
  - 代碼:
      sk = socket.socket()
      sk.setblocking(False)   #會報錯,捕獲異常
  - 異步:
    - 經過執行回調函數:當達到某個指定的狀態以後,自動調用特定函數。

7五、什麼是域名解析?

把域名解析成ip  :先去本地hosts文件中解析,若是沒有再去DNS域名解析服務器解析

7六、如何修改本地hosts文件?

hosts:網址與ip的關係映射

7七、生產者消費者模型應用場景及優點?

建立一個緩衝區,減小了生產者與消費者這件的依賴關係、支持併發、解決了生產者快慢的問題

7八、什麼是cdn?

用戶能夠就近取得所需的內容,提升用戶訪問網站的響應速度。(解決了Internet網絡擁擠的狀態)

相關技術:負載均衡、緩存、動態內容分發與複製(將靜態網頁、圖像、流媒體複製放入各個cdn中)

7九、LVS是什麼及做用?

LVS(liunx虛擬服務器):是一個虛擬的服務器集羣系統:

LVS主要用於多服務器的負載均衡。它工做在網絡層,能夠實現高性能,高可用的服務器集羣技術

80、keepalived是什麼及做用?

Keepalived的做用是檢測服務器的狀態,若是有一臺web服務器宕機,或工做出現故障,Keepalived將檢測到,並將有故障的服務器從系統中剔除,同時使用其餘服務器代替該服務器的工做,當服務器工做正常後Keepalived自動將服務器加入到服務器羣中,這些工做所有自動完成,不須要人工干涉,須要人工作的只是修復故障的服務器

做用:

  管理LVS負載均衡軟件、實現LVS集羣節點的狀態檢查

  作web架構的高可用

8一、什麼是負載均衡?

將請求分發到不一樣的服務器上去響應,而且讓每一個服務器的負載達到均衡的狀態

種類:

  1. 基於重定向
  2. 基於DNS域名解析
  3. 基於網絡層
  4. 基於數據鏈路層
  5. 反向代理

8二、實現高可用的方法

  1. 主從複製
  2. 分佈式集羣
  3. 雙機雙工

8三、公司項目1000用戶,QPS=1000 ,若是用戶猛增10000w?項目如何提升的併發?

  1. 數據庫讀寫分離
  2. 負載均衡
  3. 設置緩存

8四、haproxy是什麼以及做用?

haproxy:是一種提供高可用、負載均衡以及基於tcp或http的應用程序代理 

做用:

  1. 提供正向代理、反向代理
  2. 代理服務器,能夠提供緩存功能加速客戶端訪問,同時能夠對緩存數據進行有效性檢查
  3. 內容路由:根據流量以及內容類型將請求轉發至特定的服務器
  4. 轉碼器:支持壓縮功能,將數據以壓縮形式發送給客戶端

8五、Nginx是什麼及做用?

一、nginx是一個輕量級的Web服務器(反向代理服務器、負載均衡服務器)

二、做用:

  (1)保證內網的安全,可使用方向代理WAF(Web防火牆)功能,阻止web攻擊(大型網站,一般將反向代理做爲公網訪問地址,Web服務器是內網)

  (2)負載均衡,經過反向代理服務器來優化網站的負載,其特色是佔有內存少,併發能力強

三、正向代理與反向代理

比喻:a(客戶端)、b(代理)、c(服務端)三我的,正向代理是:a經過b向c借錢(a是知道c存在的)

                          反向代理是:a向b借錢,b向c借錢(a不知道c的存在)

8六、什麼是rpc及應用場景?

rpc(遠程過程調用):可讓程序在不一樣的內存空間(不一樣的系統)實現遠程數據通訊和互相調用

流程:客戶端調用rpc接口------>rpc-------->服務端

應用場景:好比兩臺服務器A,B,一個應用部署在A服務器上,想要調用B服務器上應用提供的函數或者方法,因爲不在一個內存空間,不能直接調用,這時候須要經過就能夠應用RPC框架的實現來解決

8七、簡述 asynio模塊的做用和應用場景。

asynio模塊能夠實現異步網絡操做、併發、協程

8八、簡述 gevent模塊的做用和應用場景。

python經過gevent中的greenlet實現協程,

當一個greenlet遇到IO操做時,好比訪問網絡,就自動切換到其餘的greenlet,等到IO操做完成,再在適當的時候切換回來繼續執行。因爲IO操做很是耗時,常常使程序處於等待狀態,有了gevent自動切換協程,就保證總有greenlet在運行,而不是等待IO。

使用gevent實現單線程併發      爬蟲(gevent中的pool或joinall)  web聊天室

8九、twisted框架的使用和應用?

twisted是一個用python語言編寫的事件驅動網絡框架,

特色是:內部基於一個事件循環(reactor),當外部事件執行時遇到IO等待則掛起,執行下一個,IO等待完成後返回一個Deferred對象,Deferred對象會自動觸發回調機制調用相應的函數處理

數據庫

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

  1. 關係型(有表結構):Mysql、oracle、sql server 、db二、sqllite、access    
  2. 菲關係(key-value):mongodb、redis、memcache

優缺點:關係型:容易理解(二維表結構)、支持sql複雜查詢、支持事務(保持數據一致性)

    非關係:數據基於鍵值對存儲、查詢速度快,數據沒有耦合性、擴展性強、

二、引擎

innodb    支持事務(回滾)、表鎖、行鎖(select id,name from user where id=2 for update)

myisam    支持全文索引、表鎖(- select * from user for update)

三、簡述數據庫範式? 

  1. 無重複列

  2. 表中屬性必須依賴於主鍵

  3. 非主屬性相關信息(關聯表信息)不能依賴於主鍵 (消除數據冗餘)

四、設計表

權限表、BBS、權限

注意:FK   M2M

五、數據操做

練習題

多表聯查:
select * from tb1,tb2 沒有where條件時,笛卡爾乘積效果

left join 以左表爲基準,顯示因此的內容,右表沒有對應項時,顯示null
  select * from tb1 left join tb2 on tb1.id=tb2.id;
inner join 只顯示兩張表共同內容
  select * from tb1 inner join tb2 on tb1.id=tb2.id;
union  顯示兩張表因此內容
  select * from tb1 left join tb2 on tb1.id=tb2.id union select * from tb2 left join tb1 on tb1.id=tb2.id;

分組函數

  select 部門ID,max(id) from 用戶表 group by 部門ID having count(id)>3 

  group by 字段  having   判斷條件   (固定語法)分組和聚合函數搭配

六、索引

建立索引:

建立表+索引
create table tb( id int not null primary key
           name varchar(32),
           pwd varchar(32)
           unique tb_pwd (pwd))

普通索引:create index tb_name on tb(name)
聯合索引:create index tb_name_age on tb(name,age)

原理:B+/哈希索引    查找速度快;更新速度慢

 一、索引必定是爲搜索條件的字段建立的

 二、innodb表的索引會存放於s1.ibd文件中,而myisam表的索引則會有單獨的索引文件table1.MYI

 

單列:
  一、普通索引 index   加速查找
  二、惟一索引 unique   加速查找+不能重複
  三、主鍵索引 primary key 加速查找+不能重複+不能爲空
多列:
  一、聯合索引
  二、聯合惟一索引
  三、聯合主鍵索引

聯合索引聽從最左前綴原則

若是組合索引爲:(name,email)
name and email -- 使用索引
name -- 使用索引
email -- 不使用索引

其它操做:
  索引合併:利用多個單例索引查找
  覆蓋索引:在索引表中就能查到想要的數據

建立了索引,但沒法命中

            - like '%xx'
                select * from tb1 where name like '%cn';
            - 使用函數
                select * from tb1 where reverse(name) = 'wupeiqi';
            - or
                select * from tb1 where nid = 1 or email = 'seven@live.com';
                特別的:當or條件中有未創建索引的列才失效,如下會走索引
                        select * from tb1 where nid = 1 or name = 'seven';
                        select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
            - 類型不一致
                若是列是字符串類型,傳入條件是必須用引號引發來,否則...
                select * from tb1 where name = 999;
            - !=
                select * from tb1 where name != 'alex'
                特別的:若是是主鍵,則仍是會走索引
                    select * from tb1 where nid != 123
            - >
                select * from tb1 where name > 'alex'
                特別的:若是是主鍵或索引是整數類型,則仍是會走索引
                    select * from tb1 where nid > 123
                    select * from tb1 where num > 123
            - order by
                select email from tb1 order by name desc;
                當根據索引排序時候,選擇的映射若是不是索引,則不走索引
                特別的:若是對主鍵排序,則仍是走索引:
                    select * from tb1 order by nid desc;
View Code

七、事務

一組sql批量執行,要麼所有執行成功、要麼所有失敗 遵循原子性、一致性、持久性、隔離性

start transaction;  開始事務   增、刪、改
update user set balance=900 where name='wsb'; #買支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
update user set balance=1090 where name='ysb'; #賣家拿到90元
commit;    提交事務
rollback; 回滾

八、數據庫鎖

問題:如何基於數據庫實現商城商品計數器?

select * from user for update

樂觀鎖(讀)

悲觀鎖(寫)

八、存儲過程、視圖、函數、觸發器

存儲過程、視圖、函數、觸發器、都是保存在數據庫中

觸發器:在數據庫中對某張表進行「增刪改」時,添加一些操做

視圖:一張虛擬表,根據SQL語句動態的獲取數據集,並命名,下次使用時直接調用名稱(只能查)

v = select * from tb where id <1000
select * from v 
等同於:                  
select * from (select * from tb where id <1000) as v 

存儲過程:將經常使用的sql語句命名保存到數據庫中,使用時能夠直接調用名稱

     參數有:in(入參類型) out(出參類型) inout(出入參類型)

函數:在sql語句中使用

  - 聚合:max/sum/min/avg
  - 時間格式化 date_format
  - 字符串拼接 concat

存儲過程與函數的區別:

區別:
  函數               存儲過程
  必須有返回值 return         能夠經過out、inout返回零各或多個值
  不能單獨使用,必須做爲表達式的一部分 能夠做爲一個獨立的sql語句執行
  sql語句中能夠直接調用函數           sql中不能調用過程

九、主鍵和外鍵的區別?

主鍵:肯定表中一條記錄的惟一標識

外鍵:用於關聯另外一張表的字段,(經過該字段肯定表中記錄)

十、char和varchar的區別?

char        固定長度(255)

varchar   變長 (理論65535)

十一、MySQL常見的函數?

1、數學函數
    ROUND(x,y)
        返回參數x的四捨五入的有y位小數的值
        
    RAND()
        返回0到1內的隨機值,能夠經過提供一個參數(種子)使RAND()隨機數生成器生成一個指定的值。

2、聚合函數(經常使用於GROUP BY從句的SELECT查詢中)
    AVG(col)返回指定列的平均值
    COUNT(col)返回指定列中非NULL值的個數
    MIN(col)返回指定列的最小值
    MAX(col)返回指定列的最大值
    SUM(col)返回指定列的全部值之和
    GROUP_CONCAT(col) 返回由屬於一組的列值鏈接組合而成的結果    
    
3、字符串函數

    CHAR_LENGTH(str)
        返回值爲字符串str 的長度,長度的單位爲字符。一個多字節字符算做一個單字符。
    CONCAT(str1,str2,...)
        字符串拼接
        若有任何一個參數爲NULL ,則返回值爲 NULL。
    CONCAT_WS(separator,str1,str2,...)
        字符串拼接(自定義鏈接符)
        CONCAT_WS()不會忽略任何空字符串。 (然而會忽略全部的 NULL)。

    CONV(N,from_base,to_base)
        進制轉換
        例如:
            SELECT CONV('a',16,2); 表示將 a 由16進制轉換爲2進制字符串表示

    FORMAT(X,D)
        將數字X 的格式寫爲'#,###,###.##',以四捨五入的方式保留小數點後 D 位, 並將結果以字符串的形式返回。若  D 爲 0, 則返回結果不帶有小數點,或不含小數部分。
        例如:
            SELECT FORMAT(12332.1,4); 結果爲: '12,332.1000'
    INSERT(str,pos,len,newstr)
        在str的指定位置插入字符串
            pos:要替換位置其實位置
            len:替換的長度
            newstr:新字符串
        特別的:
            若是pos超過原字符串長度,則返回原字符串
            若是len超過原字符串長度,則由新字符串徹底替換
    INSTR(str,substr)
        返回字符串 str 中子字符串的第一個出現位置。

    LEFT(str,len)
        返回字符串str 從開始的len位置的子序列字符。

    LOWER(str)
        變小寫

    UPPER(str)
        變大寫
   
    REVERSE(str)
        返回字符串 str ,順序和字符順序相反。
        
    SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
        不帶有len 參數的格式從字符串str返回一個子字符串,起始於位置 pos。帶有len參數的格式從字符串str返回一個長度同len字符相同的子字符串,起始於位置 pos。 使用 FROM的格式爲標準 SQL 語法。也可能對pos使用一個負值。倘若這樣,則子字符串的位置起始於字符串結尾的pos 字符,而不是字符串的開頭位置。在如下格式的函數中能夠對pos 使用一個負值。

        mysql> SELECT SUBSTRING('Quadratically',5);
            -> 'ratically'

        mysql> SELECT SUBSTRING('foobarbar' FROM 4);
            -> 'barbar'

        mysql> SELECT SUBSTRING('Quadratically',5,6);
            -> 'ratica'

        mysql> SELECT SUBSTRING('Sakila', -3);
            -> 'ila'

        mysql> SELECT SUBSTRING('Sakila', -5, 3);
            -> 'aki'

        mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
            -> 'ki'
            
4、日期和時間函數
    CURDATE()或CURRENT_DATE() 返回當前的日期
    CURTIME()或CURRENT_TIME() 返回當前的時間
    DAYOFWEEK(date)   返回date所表明的一星期中的第幾天(1~7)
    DAYOFMONTH(date)  返回date是一個月的第幾天(1~31)
    DAYOFYEAR(date)   返回date是一年的第幾天(1~366)
    DAYNAME(date)   返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE);
    FROM_UNIXTIME(ts,fmt)  根據指定的fmt格式,格式化UNIX時間戳ts
    HOUR(time)   返回time的小時值(0~23)
    MINUTE(time)   返回time的分鐘值(0~59)
    MONTH(date)   返回date的月份值(1~12)
    MONTHNAME(date)   返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE);
    NOW()    返回當前的日期和時間
    QUARTER(date)   返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE);
    WEEK(date)   返回日期date爲一年中第幾周(0~53)
    YEAR(date)   返回日期date的年份(1000~9999)
    
    重點:
    DATE_FORMAT(date,format) 根據format字符串格式化date值

       mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y');
        -> 'Sunday October 2009'
       mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s');
        -> '22:23:00'
       mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00',
        ->                 '%D %y %a %d %m %b %j');
        -> '4th 00 Thu 04 10 Oct 277'
       mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
        ->                 '%H %k %I %r %T %S %w');
        -> '22 22 10 10:23:00 PM 22:23:00 00 6'
       mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
        -> '1998 52'
       mysql> SELECT DATE_FORMAT('2006-06-00', '%d');
        -> '00'
        
5、加密函數
    MD5()    
        計算字符串str的MD5校驗和
    PASSWORD(str)   
        返回字符串str的加密版本,這個加密過程是不可逆轉的,和UNIX密碼加密過程使用不一樣的算法。
        
6、控制流函數            
    CASE WHEN[test1] THEN [result1]...ELSE [default] END
        若是testN是真,則返回resultN,不然返回default
    CASE [test] WHEN[val1] THEN [result]...ELSE [default]END  
        若是test和valN相等,則返回resultN,不然返回default

    IF(test,t,f)   
        若是test是真,返回t;不然返回f

    IFNULL(arg1,arg2) 
        若是arg1不是空,返回arg1,不然返回arg2

    NULLIF(arg1,arg2) 
        若是arg1=arg2返回NULL;不然返回arg1        
        
7、控制流函數小練習
#7.1、準備表
/*
Navicat MySQL Data Transfer

Source Server         : localhost_3306
Source Server Version : 50720
Source Host           : localhost:3306
Source Database       : student

Target Server Type    : MYSQL
Target Server Version : 50720
File Encoding         : 65001

Date: 2018-01-02 12:05:30
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `c_id` int(11) NOT NULL,
  `c_name` varchar(255) DEFAULT NULL,
  `t_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`c_id`),
  KEY `t_id` (`t_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES ('1', 'python', '1');
INSERT INTO `course` VALUES ('2', 'java', '2');
INSERT INTO `course` VALUES ('3', 'linux', '3');
INSERT INTO `course` VALUES ('4', 'web', '2');

-- ----------------------------
-- Table structure for score
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `s_id` int(10) DEFAULT NULL,
  `c_id` int(11) DEFAULT NULL,
  `num` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of score
-- ----------------------------
INSERT INTO `score` VALUES ('1', '1', '1', '79');
INSERT INTO `score` VALUES ('2', '1', '2', '78');
INSERT INTO `score` VALUES ('3', '1', '3', '35');
INSERT INTO `score` VALUES ('4', '2', '2', '32');
INSERT INTO `score` VALUES ('5', '3', '1', '66');
INSERT INTO `score` VALUES ('6', '4', '2', '77');
INSERT INTO `score` VALUES ('7', '4', '1', '68');
INSERT INTO `score` VALUES ('8', '5', '1', '66');
INSERT INTO `score` VALUES ('9', '2', '1', '69');
INSERT INTO `score` VALUES ('10', '4', '4', '75');
INSERT INTO `score` VALUES ('11', '5', '4', '66.7');

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `s_id` varchar(20) NOT NULL,
  `s_name` varchar(255) DEFAULT NULL,
  `s_age` int(10) DEFAULT NULL,
  `s_sex` char(1) DEFAULT NULL,
  PRIMARY KEY (`s_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '魯班', '12', '');
INSERT INTO `student` VALUES ('2', '貂蟬', '20', '');
INSERT INTO `student` VALUES ('3', '劉備', '35', '');
INSERT INTO `student` VALUES ('4', '關羽', '34', '');
INSERT INTO `student` VALUES ('5', '張飛', '33', '');

-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `t_id` int(10) NOT NULL,
  `t_name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`t_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES ('1', '大王');
INSERT INTO `teacher` VALUES ('2', 'alex');
INSERT INTO `teacher` VALUES ('3', 'egon');
INSERT INTO `teacher` VALUES ('4', 'peiqi');

#7.2、統計各科各分數段人數.顯示格式:課程ID,課程名稱,[100-85],[85-70],[70-60],[ <60]

select  score.c_id,
          course.c_name, 
      sum(CASE WHEN num BETWEEN 85 and 100 THEN 1 ELSE 0 END) as '[100-85]',
      sum(CASE WHEN num BETWEEN 70 and 85 THEN 1 ELSE 0 END) as '[85-70]',
      sum(CASE WHEN num BETWEEN 60 and 70 THEN 1 ELSE 0 END) as '[70-60]',
      sum(CASE WHEN num < 60 THEN 1 ELSE 0 END) as '[ <60]'
from score,course where score.c_id=course.c_id GROUP BY score.c_id;
View Code

十二、分頁

 select * form tb limit 0,5

limit  起始,數量

數據量過大,頁數越大,查詢速度越慢,由於頁數越大,數據id就越大,查詢時就會從頭開始掃描數據,

解決辦法:

方案一:
  一、記錄當期頁,數據ID的最大值、最小值,   二、翻頁查詢時,先根據數據ID篩選數據,在limit查詢
  select * from (select * from tb where id > 22222222) as B limit 0,10
  若是用戶本身修改url上的頁碼,咱們能夠參考rest-frameword中的分頁,對url中的頁碼進行加密處理

方案二:
能夠根據實際業務需求,只展現部分數據(只顯示200-300頁的數據)

1三、慢日誌查詢

slow_query_log = ON                            是否開啓慢日誌記錄
long_query_time = 2                            時間限制,超過此時間,則記錄
slow_query_log_file = /usr/slow.log          日誌文件
log_queries_not_using_indexes = ON          爲使用索引的搜索是否記錄

1四、數據庫導入導出

導入:mysqldump -u root -p db > F:\db.txt
導出:mysqldump -u root -p db(存在的) < F:\db.txt;  

1五、執行計劃

explain  select * from tb;   #查看sql語句執行速度

1六、優化方案

- 不用 select *
- 固定長度字段列,往前放
- char(固定長度)和varchar
- 固定數據放入內存:choice
- 讀寫分離,利用數據庫的主從進行分離:主,用於刪除、修改更新;從,查。
- 分庫,當數據庫中表太多,將表分到不一樣的數據庫;例如:1w張表
- 分表
  - 水平分表,將某些列拆分到另一張表;例如:博客+博客詳細
  - 垂直分表,將歷史信息分到另一張表中;例如:帳單
- 緩存:利用redis、memcache,將經常使用的數據放入緩存中

-查詢一條數據

  select * from tb where name='alex' limit 1

-text類型

 爲前面幾個字符串建立索引

 1七、問題

在對name作了惟一索引前提下,簡述如下區別:
 
       一、 select * from tb where name = ‘Oldboy-Wupeiqi’ 
                 
        二、select * from tb where name = ‘Oldboy-Wupeiqi’ limit 1    速度快

 1八、秒殺程序設計,如何不會出現超賣

一、添加事務,
   加鎖
   修改數據並判斷是否爲0
釋放鎖
提交事務

二、將秒殺商品放入redis中利用watch實現,

三、使用隊列

處理併發:

  一、前端:擴容(加機器)、 限流(限制ip訪問次數)、靜態化(頁面最大程度使用靜態,cdn)

  二、後端:【內存】+【排隊】

相關文章
相關標籤/搜索