python面试题大全
一、python基礎面試題
1.Python的特點
- Python是一種解釋性語言【開發過程中沒有了編譯這個環節,類似于PHP或者Perl語言】
- Python是交互式語言【可以在一個Python提示符,直接互動執行程序】
- Python是面向對象語言【Python支持面向對象的風格或代碼封裝在對象的編程技術】
- Python是初學者的語言【Python對于初級程序員而言,是一種偉大的語言,他支持廣泛的應用程序開發,從簡單的文字處理到瀏覽器再到游戲】
- Python是跨平臺的【它可以運行在Windows、Mac os或者Linux系統上,也就是說,在Windows上書寫的Python程序,在Linux上也是可以運行的,類似于Java】
2.Python優缺點
優點:
-
易于學習【Python有相對較少的關鍵字,結構簡單,和一個明確定義的語法,學習起來更加簡單】
-
易于閱讀【Python代碼定義的更清晰】
-
易于維護【Python的成功在于它的源代碼是相當容易維護的】
-
一個廣泛的標準庫【Python的最大優勢之一是豐富的庫,跨平臺的,在nuix、weindows和mac os上的兼容性很好】
-
互動模式【互動模式的支持,可以從終端輸入執行代碼并獲得結果的語言,互動的測試和調試代碼片段】
-
可移植性【基于其開發源代碼的特性,Python已經被移植到許多平臺】
-
可擴展性【如果需要一段運行很快的關鍵代碼,或者想要編寫一些不愿開發的算法,可以使用C或者C++完成那部分程序,然后從你的Python程序中調用】
-
數據庫【Python提供所有主要的商業數據庫的接口】
-
GUI編程(圖形化界面)【Python支持GUI可以創建和移植到許多系統調用】
-
可嵌入性【可以將Python嵌入到C或者C++程序,讓你程序的用戶獲得“腳本化”的能力】
點:
-
運行速度慢【和C程序相比非常慢,因為Python是解釋型語言,代碼在執行時會一行一行的翻譯成CPU能理解的機器碼,這個翻譯過程非常耗時,所以很慢,而C程序是運行前直接編譯成CPU能執行的機器碼,所以非常快】
-
代碼不能加密【如果要發布Python程序,實際上就是發布源代碼,這一點跟C語言不通,C語言不用發布源代碼,只需要把編譯后的機器碼(就是windows上常見的xxx.exe)發布出去,要從機器碼反推出C代碼是不可能的,所以,凡是編譯型的語言,都沒有這個問題,而解釋型的語言,則必須把源碼發布出去】
3.Python應用場景
-
Web開發【通過mod_wsgi模塊,Apache可以運行用Python編寫的Web程序。Python定義了WSGI標準應用接口來協調Http服務器與基于Python的Web程序之間的通信。一些Web框架,如Django,TurboGears,web2py,Zope等,可以讓程序員輕松地開發和管理復雜的Web程序】
-
操作系統管理、服務器運維的自動化腳本【在很多操作系統里,Python是標準的系統組件。 大多數Linux發行版以及NetBSD、OpenBSD和Mac OS X都集成了Python,可以在終端下直接運行Python。Python編寫的系統管理腳本在可讀性、性能、代碼重用度、擴展性幾方面都優于普通的shell腳本】
-
網絡爬蟲【Python有大量的HTTP請求處理庫和HTML解析庫,并且有成熟高效的爬蟲框架Scrapy和分布式解決方案scrapy-redis,在爬蟲的應用方面非常廣泛】
-
科學計算(數據分析)【NumPy、SciPy、Pandas、Matplotlib可以讓Python程序員編寫科學計算程序】
-
桌面軟件【PyQt、PySide、wxPython、PyGTK是Python快速開發桌面應用程序的利器】
-
服務器軟件(網絡軟件)【Python對于各種網絡協議的支持很完善,因此經常被用于編寫服務器軟件、網絡爬蟲。第三方庫Twisted支持異步網絡編程和多數標準的網絡協議(包含客戶端和服務器),并且提供了多種工具,被廣泛用于編寫高性能的服務器軟件】
-
游戲【很多游戲使用C++編寫圖形顯示等高性能模塊,而使用Python或者Lua編寫游戲的邏輯、服務器。相較于Python,Lua的功能更簡單、體積更小;而Python則支持更多的特性和數據類型】
搜狐、豆瓣、騰訊、網易、百度、阿里、淘寶、土豆、新浪等都在內部大量的使用Python
4.標識符
概念:計算機編程語言中,標識符是用戶編程時使用的名字,用于給變量、常量、函數、語句塊等命名,以建立起名稱與使用之間的關系
合法標識符的命名規則:
- 只能由數字,字母和下劃線組成
- 不可以是除了下劃線之外的其他特殊字符
- 開頭不能是數字或者空格
- 不能是Python的關鍵字
- 嚴格區分大小寫 age Age
標識符的命名規范:
- 盡量做到見名知意【具有描述性】:盡量使用簡單的英文單詞表示
- 遵守一定的命名規范
- Python官方推薦的命名方式:變量名,函數名和文件名全小寫,使用下劃線連接,如:stu_name check_qq
- 駝峰命名法:不同的單詞之間使用首字母大寫的方式進行分隔,又分為大駝峰和小駝峰,比如:stuName就是小駝峰,StuName就是大駝峰,小駝峰常用于變量或者函數的命名,大駝峰常用于類的命名
5.打包pack和拆包unpack
*:所有m1,m2,*m3 = 34,56,2,56,56,67,68,8,89print(m1,m2,m3)m1,*m2,m3 = 34,56,2,56,56,67,68,8,89print(m1,m2,m3)*m1,m2,m3 = 34,56,2,56,56,67,68,8,89print(m1,m2,m3)m1,m2,*m3 = 34,56,2,56,56,67,68,8,89print(m1,m2,*m3)m1,*m2 = [34,5,6,7,8]print(m1,m2)6.變換兩個變量的值
# 方式一:定義第三方變量 a = 10 b = 20 temp = a a = b b = temp print(a,b)# 方式二 ****** a = 10 b = 20 a,b = b,a print(a,b)# 方式三:加減法 a = 10 b = 20 a = a + b # a = 30 b = a - b # b = 10 a = a - b # a = 20 print(a,b)# 方式四:異或^ #原理:一個數異或另一個數兩次,結果是該數本身 # print(56 ^ 3 ^ 3) a = 10 b = 20 a = a ^ b # a = 10 ^ 20 b = a ^ b # b = 10 ^ 20 ^ 20 = 10 a = a ^ b # a = 10 ^ 20 ^ 10 = 20 print(a,b)# 7.常量:值不能發生改變的標識符 # 常量命名法:所有英文單詞全部大寫,不同單詞之間使用下劃線相連 PI = 3.1415 print(PI)7.可變數據類型和不可變數據類型
? 可變數據類型:list dict set
不可變數據類型:int float bool str tuple
8.說明is和==的區別和聯系
? a.==比較的是內容
b.is比較的是地址
c.如果兩個變量的內容相同,他們的地址不一定相同,如果兩個變量的地址相同,則他們的內容一定相同
9.切片特點
切片:根據指定的區間,通過某種規律在列表,元組或者字符串中進行截取,形成一個新的列表,元組或字符串
語法:列表[start🔚step]
start:開始索引,可以省略,默認為0,不省略的情況下包含在內
end:結束索引,可以省略,默認為最后一個【正數或負數】,不省略的情況下不包含在內
step:步長,可以省略,默認為1
0 1 2 3 4 5 6 7 8
-9 -8 -7 -6 -5 -4 -3 -2 -1
注意:
a.只要切片的語法正確,哪怕獲取不到元素,都不會報錯
b.切片之后會得到一個新的列表,對原列表沒有任何影響
10.append和extend的區別
append和extend都作為向列表中添加元素的功能,有什么區別和聯系
相同點:
a.元素都會出現在列表的末尾
b.都可以添加單個或多個元素
c.都是在原列表的基礎直接操作的
不同點:
a.append可以追加任意類型的數據,而extend只能添加可迭代對象
b.如果向列表中添加一個可迭代對象,append會將可迭代對象整體添加,而extend只會添加可迭代對象中的元素
11.列表拷貝
1.引用賦值結論:列表使用引用賦值,兩個列表指向同一份內存空間,不管是幾維列表,只要其中一個列表中的元素發生修改,則訪問另一個列表,其中的元素會隨著修改 2.淺拷貝淺拷貝結論:一維列表:會將拷貝的列表開辟一份新的內存空間,所以其中一個列表中的元素修改,對另一個列表沒有影響多維列表:本質是一個淺拷貝,只會拷貝最外層的地址,所以如果一個列表修改內層列表的元素,另一個列表會隨著修改 3.深拷貝深拷貝結論:兩個列表指向不同的內存空間,不管是幾維列表,所有的內容都會被重新拷貝,其中一個列表中的元素發生修改,則訪問另一個列表,沒有任何影響11.1列表拷貝面一
a = [1,2,3] b = [4,5] c = [a,b] d = c e = c.copy() a.append(6) print(c,d,e) """ c:[[1,2,3,6],[4,5]] d:[[1,2,3,6],[4,5]] e:[[1,2,3,6],[4,5]] """a = [1,2,3] b = [4,5] c = [a,b] d = c e = c.copy() c.append(6) print(c,d,e) """ c:[[1,2,3],[4,5],6] d:[[1,2,3],[4,5],6] e:[[1,2,3],[4,5]] """11.2列表拷貝面二
a = [1,2,['a','b']] b = a c = copy.deepcopy(a) a[-1].append(3) print(a,b,c) """ a:[1,2,['a','b',3]] b:[1,2,['a','b',3]] c:[1,2,['a','b']] """11.3列表拷貝面三
a = [1,2,['a','b']] b = a c = copy.copy(a) a.append(3) print(a,b,c) """ a:[1,2,['a','b'],3] b:[1,2,['a','b'],3] c:[1,2,['a','b']] """12.冒泡排序
排序思路:比較兩個相鄰的下標對應的元素,如果符合條件就交換位置
# 冒泡排序 # 以升序為例 list1 = [45,6,8,9,2,56,68,98,100,56,4,19] # 外層循環:控制比較的輪數 for i in range(len(list1) - 1):# 內層循環:控制的是每一輪比較的次數,兼顧參與比較的下標for j in range(len(list1) - 1 - i):# 相鄰兩個元素比較大小# 如果下標小的元素 > 下標大的元素,則交換位置if list1[j] > list1[j + 1]:list1[j],list1[j + 1] = list1[j + 1],list1[j] print(list1)# 以降序為例 list1 = [45,6,8,9,2,56,68,98,100,56,4,19] # 外層循環:控制比較的輪數 for i in range(len(list1) - 1):# 內層循環:控制的是每一輪比較的次數,兼顧參與比較的下標for j in range(len(list1) - 1 - i):# 相鄰兩個元素比較大小# 如果下標小的元素 < 下標大的元素,則交換位置if list1[j] < list1[j + 1]:list1[j],list1[j + 1] = list1[j + 1],list1[j] print(list1)13.選擇排序
排序思路:固定一個下標,然后拿這個下標對應的值依次和后面的元素進行比較,最值出現在頭角標位置上
# 選擇排序 # 以升序為例 list1 = [45,6,8,9,2,56,68,98,100,56,4,19] # 外層循環:控制比較的輪數 for i in range(len(list1) - 1):# 內層循環:控制的是每一輪比較的次數,兼顧參與比較的下標for j in range(i + 1,len(list1)):# 相鄰兩個元素比較大小# 如果下標小的元素 > 下標大的元素,則交換位置if list1[i] > list1[j]:list1[i],list1[j] = list1[j],list1[i] print(list1)# 以降序為例 list1 = [45,6,8,9,2,56,68,98,100,56,4,19] # 外層循環:控制比較的輪數 for i in range(len(list1) - 1):# 內層循環:控制的是每一輪比較的次數,兼顧參與比較的下標for j in range(i + 1,len(list1)):# 相鄰兩個元素比較大小# 如果下標小的元素 < 下標大的元素,則交換位置if list1[i] < list1[j]:list1[i],list1[j] = list1[j],list1[i] print(list1)14.順序查找
# 順序查找:將待查找元素和列表中的每個元素進行依次的比對,如果相等,則表示查找成功 # 1. list1 = [34,6,7,7,8,7,45,76,8] key = 7 for i in range(len(list1)):if list1[i] == key:print(f"待查找元素{key},在列表中的索引為:{i}")print("*" *30)# 2.index() list1 = [34,6,7,7,8,7,45,76,8] key = 10 for i in range(len(list1)):if list1[i] == key:print(f"待查找元素{key},在列表中的索引為:{i}")break else:print(f"待查找元素{key}在列表中不存在")15.二分法查找
查找思路:升序的前提下,將待查找的元素與中間下標對應的元素比較,如果大于中間下標對應的元素,則去右半部分查找
注意:前提是列表是有序(升序或者降序)的,通過折半來縮小查找范圍,提高查找效率
# 以升序為例 list1 = [34,6,7,8,9,40,26,7,73,48,737] list1.sort() key = 7left = 0 right = len(list1) - 1while left <= right:# 計算中間下標middle = (left + right) // 2# 比較if key > list1[middle]:# 后半部分:重置left的值left = middle + 1elif key < list1[middle]:# 前半部分:重置right的值right = middle - 1else:print(f"待查找元素{key}在列表中的下標為{middle}")# 查找到元素,則提前結束循環break else:print(f"待查找元素{key}在列表中不存在")# 以降序為例 list1 = [34,6,7,8,9,40,26,7,73,48,737] list1.sort(reverse=True) key = 7left = 0 right = len(list1) - 1while left <= right:# 計算中間下標middle = (left + right) // 2# 比較if key > list1[middle]:# 前半部分:重置right的值right = middle - 1elif key < list1[middle]:# 后半部分:重置left的值left = middle + 1else:print(f"待查找元素{key}在列表中的下標為{middle}")# 查找到元素,則提前結束循環break else:print(f"待查找元素{key}在列表中不存在")16.元組操作
# a t1 = (34,5,6,6,2,7,[1,2,3]) print(id(t1[-1])) t1[-1][0] = 100 print(t1) # (34, 5, 6, 6, 2, 7, [100, 2, 3]) print(id(t1[-1]))# b. # l1 = [3,5,6,7,7,(4,6,7)] # l1[-1][0] = 100 # print(l1) # 報錯# c.遍歷 for ele in tuple3:print(ele) for i in range(len(tuple3)):print(i,tuple3[i]) for i,ele in enumerate(tuple3):print(i,ele)17.列表和字典的區別
# 列表和字典的區別格式:列表:[] 字典:{}存儲的數據:列表中可以存儲任意類型的數據,字典中存儲的是鍵值對,其中鍵只能是不可變的數據類型,值可以是任意的類型是否可變:列表是可變的,字典是可變的是否有序:字典是有序的,Python3.7之前是無序的,3.7之后是有序的是否可以存儲重復數據:列表中可以存儲重復數據,字典中的鍵是唯一的,值可以重復使用的場景不同:列表常用與可以存儲同類型的數據,字典常用于可以存儲同一個對象的不同信息 或者 需要精確定位到某個數據18.定義字典
使用不同的方式定義字典,至少兩種
# 方式一 ****** info_dict = {"name":"張三","age":18,"hobby":"吹牛逼"} print(info_dict)# 方式二 ****** dict1 = {} dict1['aaa'] = 10 dict1['bbb'] = 20 print(dict1)# 方式三: # dict(key1=value1,key2=value2.....) dict2 = dict(x=10,y=20,z=30) print(dict2) # {'x': 10, 'y': 20, 'z': 30} # 問題:采用dict(key1=value1,key2=value2.....)方式,字典的key只能是字符串 # d1 = {10:1,20:2} # d2 = dict(10=1,20=2)# 方式四 # dict([(key1,value1),(key2,value2).....]) dict3 = dict([('a',11),('b',22),('c',33)]) print(dict3) dict3 = dict([(10,11),('b',22),('c',33)]) print(dict3)# 方式五: ******* # 映射 # dict(zip([key1,key2....],[value1,value2...])) dict4 = dict(zip(['name','age','score'],['jack',17,100])) print(dict4) dict4 = dict(zip(('name','age','score'),['jack',17,100])) print(dict4) dict4 = dict(zip(('name','age','score'),('jack',17,100))) print(dict4) dict4 = dict(zip(['name','age','score','height'],['jack',17,100])) print(dict4) dict4 = dict(zip(['name','age','score'],['jack',17,100,456,67,8])) print(dict4)# 注意:不管通過哪種方式定義字典,字典的key都不能是列表,字典,集合等可變的數據類型19.簡述列表,元組,字典,集合和字符串的區別
列表的本質:list,是一種有序的,可變的,可以存儲重復元素的,可以存儲不同類型的集合 元組的本質:tuple,是一種有序的,不可變的,可以存儲重復元素的,可以存儲不同類型的集合 字典的本質:dict,是一種有序的【Python3.7之后】,可變的,key不可以重復,但是value可以重復,key只能是不可變的數據類型,vlue可以是任意的類型的集合 集合的本質:set,是一種無序的,可變的,不可以存儲重復元素的,可以存儲不同類型的集合 字符串的本質:str,是一種有序的,不可變的,可以存儲重復字符的集合20.編碼、解碼
編碼:將字符串類型轉換為字節類型,bytes()或encode() 解碼:將字節類型轉換為字符串類型,str()或decode() 字符串:'' "" 字節:b'' b"" 編碼格式:utf-8gbk# 1.編碼 str1 = "3454hajgaj發哈哈%¥#@" # a.bytes() r1 = bytes(str1,encoding="utf-8") print(r1) print(type(r1))# b.字符串.encode() r2 = str1.encode(encoding="gbk") print(r2) print(type(r2))# 2.解碼 # 注意:編解碼采用的格式必須保持一致 # a.str() r3 = str(r1,encoding="utf-8") print(r3) print(type(r3))# b.字節.decode() r4 = r2.decode(encoding="gbk") print(r4) print(type(r4))# 擴展 # f = open(r"file1.txt","w",encoding="gbk") # f.write("你好hello") # f.close()21.值傳遞和引用的區別
值傳遞:傳參的時候,傳遞的是不可變的數據類型,如:int/float/bool/str/tuple等,當形參發生修改,實參沒有影響引用傳遞:傳參的時候,傳遞的是可變的數據類型,如:list/dict.set等,當形參發生元素的修改,則實參會隨著修改22.什么是匿名函數,優缺點是什么
是一個lambda表達式,本質上還是一個函數,可以設置必需參數,默認參數,關鍵字參數和不定長參數只不過表達式的執行結果就是函數的返回值優點:簡化代碼減少內存空間的使用缺點:只能實現簡單的邏輯,邏輯一旦復雜,如果使用,代碼的可讀性會降低,后期的維護性降低,則不建議使用23.局部變量和全局變量
# a n = 9 def check():n = 1print(n) # 1 check() print(n) # 9# b. # n = 9 # def check(): # n += 1 # n = n + 1 # check() # print(n)# UnboundLocalError: local variable 'n' referenced before assignment24.簡述global和nonlocal關鍵字的作用,并舉例說明
24.1global
# 1. n = 9 def check():n = 5n += 1 # n = n + 1print(n) # 6 check() print(n) # 9# 2. # UnboundLocalError: local variable 'n' referenced before assignment n = 9 def check():# global n,聲明n變量來自于全局變量,則在函數中出現的n將不再是重新定義的新變量global nn += 1 # n = n + 1print(n) # 10 check() print(n) # 1024.1nonlocal
# 說明:nonlocal一般應用在閉包中,跟局部作用域有關# 1. x = 1 def outter():x = 2def inner():x = 3 # 定義了一個新的變量print("inner",x)inner()print("outter",x) outter() print('global',x) """ inner 3 outter 2 global 1 """# 2. x = 1 def outter():x = 2def inner():# nonlocal x,聲明x不是局部變量,而是來自于函數作用域的變量nonlocal xx = 3 # 表示重新賦值print("inner",x)inner()print("outter",x) outter() print('global',x) """ inner 3 outter 3 global 1 """25.簡述可迭代對象和迭代器之間的區別和聯系
區別: 可迭代對象:Iterable,可以直接作用于for循環的對象【可以使用for循環遍歷其中元素的對象】,如:list,tuple,dict,set,str,range(),生成器等迭代器:Iterator,可以直接作用于for循環,或者可以通過next()獲取下一個元素的對象,如:生成器 聯系:迭代器一定是可迭代對象,可迭代對象不一定是迭代器但是,可以通過系統功能iter()將不是迭代器的可迭代對象轉換為迭代器26.分別解釋什么是列表推導式,字典推導式,集合推導式,生成器,可迭代對象,迭代器
迭代器和生成器都是容器對象。它們之間的關系是,生成器是一種特殊的迭代器。(生成器一定是迭代器,但迭代器不一定是生成器)。所以,我們從迭代器入手。 迭代器:python中只要實現了迭代協議的容器,都是迭代器。python的迭代協議,基于兩個方法:- next() 返回迭代容器中的下一個- __iter__() 返回迭代器本身 生成器:生成器是一種特殊的迭代器,所以也是有迭代器的特征的。next()和iter()方法。不同的是next()返回的是yield指令返回的值,iter()方法,返回的是一個生成器對象。27.說明sort()和sorted()之間的區別和聯系
相同點:a.二者都是用來排序的b.默認的情況下,二者都是升序,如果要降序,都是設置reverse=Truec.如果要自定義排序規則,二者都是設置key,key的值都得是一個函數 不同點:a.調用方式不同:列表.sort() , sorted(列表)b.sort是在原列表內部排序的,sorted是生成了一個新的列表28.書寫一個裝飾器,可以統計任意一個函數的執行時間
def wrapper(func):def get_time():# 開始時間戳start = time.time()func()# 結束時間end = time.time()return round(end - start,5)return get_time @wrapper def test():for i in range(100000):pass print(test())29.書寫一個裝飾器,可以統計任意一個函數的執行時間
import time def wrapper(func):def get_time(*args,**kwargs):# 開始時間戳start = time.time()func(*args,**kwargs)# 結束時間end = time.time()return round(end - start,5)return get_time @wrapper30.@xxx被稱為無參裝飾器,@xxxx(value)有參的裝飾器
def outter(a):def inner(b):passreturn inner@outter(value) def func():pass 工作原理:a.自動調用裝飾器的內外部函數b.將裝飾器的參數value傳參給外部函數的參數a,將被修飾的函數傳參給內部函數的參數bc.原函數的函數名指向內部函數的返回值31.自定義模塊的優點
- 提高代碼的可維護性 - 提高了代碼的復用度,當一個模塊書寫完畢,可以被多個地方引用 - 引用其他的模塊 - 避免函數名和變量名的命名沖突32.面向過程和面向對象的區別
面向過程 在生活案例中: 一種看待問題的思維方式,在思考問題的時候,著眼于問題是怎樣一步一步解決的,然后親力親為的去解決問題 在程序中: 代碼從上而下順序執行各模塊之間的關系盡可能簡單,在功能上相對獨立每一模塊內部均是由順序、選擇和循環三種基本結構組成其模塊化實現的具體方法是使用子程序程序流程在寫程序時就已決定 面向對象 在生活案例中: 也是一種看待問題的思維方式,著眼于找到一個具有特殊功能的具體個體,然后委托這個個體去做某件事情,我們把這個個體就叫做對象,一切皆對象是一種更符合人類思考習慣的思想【懶人思想】,可以將復雜的事情簡單化,將程序員從執行者轉換成了指揮者 在程序中:把數據及對數據的操作方法放在一起,作為一個相互依存的整體——對象1》對同類對象抽象出其共性,形成類2》類中的大多數數據,只能用本類的方法進行處理3》類通過一個簡單的外部接口與外界發生關系,對象與對象之間通過消息進行通信4》程序流程由用戶在使用中決定5》使用面向對象進行開發,先要去找具有所需功能的對象,如果該對象不存在,那么創建一個具有該功能的對象注意:面向對象只是一種思想,并不是一門編程語言,也不會綁定編程語言 面向過程就是分析出解決問題所需要的步驟,然后用函數把這些步驟一步一步實現,使用的時候一個一個一次調用就可以了 面向對象是把構成問題事務分解成各個對象,建立對象的目的不是為了完成一個步驟,而是為了描述某個事物在整個解決問題的步驟中的行為33.面向過程和面向對象的優缺點
面向過程:優點:性能比面向對象高,開銷比較大,比較消耗資源,比如單片機、嵌入式開發等一般采用面向過程開發,因為性能是最重要的因素缺點:沒有面向對象易維護,易復用,易擴展 面向對象:優點:易維護,易復用,易擴展,由于面向對象有封裝,繼承,多態的特性,可以設計出低耦合的系統,使得系統更加靈活,更加易于維護缺點:性能比面向過程低 Python是一門面向的語言,面向對象語言的特點:封裝,繼承和多態 狗吃屎:面向對象 吃狗屎:面向過程34.簡述實例屬性【對象屬性】和類屬性之間的區別
a.定義的位置不同:類屬性直接定義在類中,實例屬性可以通過動態綁定 或者 定義在構造函數中 b.訪問的方式不同:類屬性可以通過對象或類名訪問,而實例屬性只能通過對象訪問 c.優先級不同:在類屬性和實例屬性重名的情況下,使用對象訪問,優先訪問的是實例屬性 d.在內存中出現的時機不同:類屬性優先于實例屬性出現在內存中,類屬性隨著類的加載而出現,實例屬性隨著對象的出現而出現 e.使用場景不同:類屬性適用于多個對象共享的數據,實例屬性適用于每個對象特有的數據35.普通實例函數和__init__之間的區別和聯系
不同點:a.函數名不同:實例函數的函數名需要自定義,但是,__init__是固定的,是系統的函數b.調用不同:實例函數需要手動調用,__init__是在創建對象的過程中自動調用的c.調用的次數不同:對于同一個對象而言,實例函數可以被調用無數次,__init__只會被調用一次 相同點:a.定義在類中,本質上都是實例函數,形參列表的第一個參數都是selfb.默認參數,關鍵字參數,不定長參數都可以使用c.也可以設置返回值36.析構函數的調用時機
使用場景:一般用于程序的清理行為,如:關閉文件,關閉數據庫等37.閱讀下面的代碼,寫出執行結果
class Person():@propertydef show(self):return 10 p = Person() p.show() # 報錯,被@property修飾的函數會被當做屬性使用,則p.show的值為show函數的返回值 # 修改方式:p.show()--->r = p.show38.解釋下面不同形式的變量出現在類中的意義
a:普通屬性,在類的外面可以直接訪問 _a:在類的外面可以直接訪問,但是不建議使用,容易和私有化屬性混淆 __a:私有屬性,只能在類的內部被直接訪問,類的外面可以通過暴露給外界的函數訪問 __a__:在類的外面可以直接訪問,但是不建議使用,因為系統的屬性和魔術方法都是這種形式的命名, 如:__slots__,__init__.__del__,__new__,__add__,__sub__,__mul__,__gt__,__lt__,__eq__,__ne__,__str__等39.繼承注意小題
class MyClass(object):x = 10 class SubClass1(MyClass):pass class SubClass2(MyClass):pass print(MyClass.x,SubClass1.x,SubClass2.x) # 10 10 10 SubClass1.x = 20 print(MyClass.x,SubClass1.x,SubClass2.x) # 10 20 10 MyClass.x = 30 print(MyClass.x,SubClass1.x,SubClass2.x) # 30 20 3040.簡述類中的實例函數,靜態函數和類函數之間的區別
a.定義不同:被@classmethod修飾的函數表示類函數,被@staticmethod修飾的函數表示靜態函數,實例函數沒有裝飾器 b.形參列表不同:實例函數的第一個參數是self,表示當前對象,類函數的第一個參數是cls,表示當前類,靜態函數的參數沒有要求 c.調用方式不同:類函數和靜態函數都可以通過類名或者對象調用,但是,實例函數只能通過對象調用 d.使用場景不同:如果要封裝一個工具類,則盡量使用類函數或靜態函數,在實際項目開發中,常用實例函數41.下面哪些打開文件的方式,可以自動創建一個新的文件
a.open('f1.txt','w',encoding='utf-8') b.open('f1.txt','wb',encoding='utf-8') c.open('f1.txt','w+',encoding='utf-8') d.open('f1.txt','a',encoding='utf-8') e.open('f1.txt','r',encoding='utf-8') #abcd42.什么是單例設計模式?
程序運行過程中,確保某一個類只有一個實例【對象】,不管在哪個模塊獲取這個類的對象,獲取到的都是同一個對象。該類有一個靜態方法,向整個工程提供這個實例,例如:一個國家只有一個主席,不管他在哪 單例設計模式的核心:一個類有且僅有一個實例,并且這個實例需要應用于整個程序中,該類被稱為單例類50 執行with上下文的時候,底層的工作原理
with上下文的工作原理 """ 語法: with 對象 as 變量名處理事務 """ class Person(object):# 進入def __enter__(self):print("進入with上下文管理")return self# 退出def __exit__(self, exc_type, exc_val, exc_tb):print("退出with上下文管理")with Person() as p1:print("處理事務")51 列出常見的異常并說明出現異常的原因,至少5個
# 【面試題】列出常見的異常并說明出現異常的原因,至少5個# 1.NameError:使用了一個未定義的變量 # print(num) # NameError: name 'num' is not defined# 2.ValueError:進行數據轉換的時候,類型不匹配 # n = int(input("number:")) # ValueError: invalid literal for int() with base 10: 'gakgjak'# 3.KeyError:當訪問了不存在的key # dict1 = {'a':10} # print(dict1['b']) # KeyError: 'b'# 4.AttributeError:當一個對象訪問了不存在的屬性或函數 class Person():pass p = Person() # print(p.name) # AttributeError: 'Person' object has no attribute 'name'# [24,456].appends(45) # AttributeError: 'list' object has no attribute 'appends'# 5.IndexError:使用索引訪問列表,字符串,元組的時候,索引越界# 6.UnboundLocalError:當不同作用域的變量重名的情況下,訪問了不屬于當前作用域的變量 a = 10 def test():global aa += 1 # UnboundLocalError: local variable 'a' referenced before assignment test() print(a)def outter():a = 10def inner():nonlocal aif a > 3: # UnboundLocalError: local variable 'a' referenced before assignmenta = 34inner() outter()# 7.IndentationError # if 1: # num = 10 # IndentationError: unindent does not match any outer indentation level # print(45)# 8.FileNotFoundError:文件路徑不存在 # open('file1.txt','r',encoding="utf-8") # FileNotFoundError: [Errno 2] No such file or directory: 'file1.txt'# 9.ModuleNotFoundError:模塊路徑錯誤# 10.TypeError:類型不匹配# 11.KeyboardInterruptError52 根據實際使用情況,給下面代碼處理可能存在的異常
f = None try:f = open(r"file1.txt", 'r', encoding="utf-8")f.read() except FileNotFoundError as e:print(e) except LookupError as e:print(e) except ValueError as e:print(e) except UnicodeDecodeError as e:print(e) finally:if f:f.close()# FileNotFoundError # LookupError # ValueError # UnicodeDecodeError53 自定義異常
# 1.自定義一個類,繼承自Exception/BaseException class MyException(Exception):# 2.定義構造函數,調用父類的構造函數,并定義一個實例屬性,表示異常的描述信息def __init__(self,message):super().__init__()self.message = message# 3.重寫__str__,返回異常的描述信息字符串def __str__(self):return self.message# 4.定義一個實例函數,用于處理出現的異常def handle(self):print("處理了異常~~~~") try:raise MyException("出現了錯誤") except MyException as e:print(e)e.handle()# 注意:如果要解決生活中的問題,則可以通過自定義異常處理# 練習: # 需求:自定義一個異常,表示上班遲到的異常,如果8點之前起床,上班不會遲到,如果8點之后起床的,上班會遲到 class LateException(Exception):__slots__ = ("message",)def __init__(self,message):super().__init__()self.message = messagedef __str__(self):return self.messagedef handle(self):print("延遲下班時間")time = float(input("請輸入起床的時間:")) if time > 8:# 出現異常 try:raise LateException("鬧鈴響了沒聽見~~~~~~") except LateException as e:print("遲到的原因:",e)e.handle() else:print("早早到達公司,開始搬磚~~~")54 寫出下面代碼執行的結果
# 注意:不管什么情況下,finally永遠都會執行,哪怕在函數中,try或except代碼塊中書寫了return # a. # def test(): # try: # list1 = [34, 5, 6] # index = int(input("請輸入列表的索引:")) # 1 # num = list1[index] # print(f"獲取的元素為:{num}") # return # except IndexError as e: # print("IndexError", e) # return # except ValueError as e: # print("ValueError:", e) # finally: # print("finally語句被執行了~~~~") # test()# b. # def test(): # list1 = [34, 5, 6] # index = int(input("請輸入列表的索引:")) # 1 # num = list1[index] # print(f"獲取的元素為:{num}") # # try: # test() # except IndexError as e: # print("IndexError", e) # except ValueError as e: # print("ValueError:", e) # finally: # print("finally語句被執行了~~~~")55 match,search和findall之間的區別
r1 = re.match(r"\d+","abc2abc2") print(r1) r1 = re.search(r"\d+","abc2abc2") print(r1) r1 = re.findall(r"\d+","abc2abc2") print(r1)56 進程和線程之間的關系
a.一個程序啟動之后,會啟動一個進程? b.一個進程啟動之后,可能會啟動多個線程,但是至少需要有一個線程,否則這個進程是沒有意義的? c.多個進程間不能共享資源,但多個線程之間資源共享的? d.系統創建進程需要為該進程重新分配系統資源,而創建線程則容易的多,因此使用多線程比使用多進程效率更高57 如何自定義進程
from multiprocessing import Process from time import sleep# 【面試題】如何自定義進程# 通過類的特點將進程進行封裝,在使用的時候,只需要調用即可# a.定義一個類,繼承自Process class MyProcess(Process):# b.書寫構造函數,調用父類的構造函數,并定義進程的名稱def __init__(self,name):Process.__init__(self)self.name = name# c.定義進程處理任務的函數,命名為run,實際表示重寫父類中的run函數# 注意:如果要自定義進程的子類,則必須在子類中重寫run函數def run(self):# 子進程需要處理的任務的邏輯代碼print("子進程啟動")sleep(1)print("子進程結束~~~~~")if __name__ == '__main__':p = MyProcess("進程11")p.start() # 調用start函數,自動調用run函數58 定時線程
import threading# 【面試題】 def run():print("hello~~~~~")if __name__ == '__main__':print("主線程啟動")# Timer(seds,target)t = threading.Timer(5,run)t.start()t.join()print("主線程結束")59 關于python序列化相關的模塊
# 關于python序列化相關的模塊- joblib:- dump(obj,filename)直接將python對象轉換為字節數據存儲到文件中(序列化),- load(filename)將對象的字節數據從文件中加載(反序列化) - pickle:針對任何對象- dumps(obj)-->bytes- dump(obj,filename) bytes寫入到文件中- loads("b")-->obj 從bytes反序列化為object對象- load(filename) 從文件中加載bytes并反序列化為object對象 - json:json格式的字符串- dumps(list|dict)-->str- dump(list|dict,filename)- loads(str)-->list|dict- load(filename)-->list|dict60 華為面試題
解密犯罪時間 | 時間限制:1秒 | 內存限制:262144K | 語言限制:不限 警察在偵破一個案件時,得到了線人給出的可能犯罪時間,形如 “HH:MM” 表示的時刻。 根據警察和線人的約定,為了隱蔽,該時間是修改過的,解密規則為:利用當前出現過的數字,構造下一個距離當前時間最近的時刻,則該時間為可能的犯罪時間。每個出現數字都可以被無限次使用。" "輸入描述: 形如HH:SS的字符串,表示原始輸入 輸出描述: 形如HH:SS的字符串,表示推理出來的犯罪時間 示例1 輸入 18:52 輸出 18:55 說明 利用數字1, 8, 5, 2構造出來的最近時刻是18:55,是3分鐘之后。結果不是18:51因為這個時刻是18小時52分鐘之后。 示例2 輸入 23:59 輸出 22:22 說明 利用數字2, 3, 5, 9構造出來的最近時刻是22:22。 答案一定是第二天的某一時刻,所以選擇可構造的最小時刻為犯罪時間。 備注: 可以保證線人給定的字符串一定是合法的。例如,“01:35” 和 “11:08” 是合法的,“1:35” 和 “11:8” 是不合法的。最近的時刻有可能在第二天def decrypt_crime_time(s):nums_list = [int(i) for i in s if i != ":"]H, M = [int(i) for i in s.split(":")]nums_list = list({i * 10 + j for i in nums_list for j in nums_list if i <= 5})nums_list.sort()if H in nums_list and H != 23:for i in nums_list:if i <= M:continuereturn ":".join([str(H), str(i)])else:return ":".join([str(nums_list[0]), str(nums_list[0])])s = "20:12" print(decrypt_crime_time(s)) s = "23:59" print(decrypt_crime_time(s))61 關系型數據庫有哪些對象
關系型數據庫一般都支持約束、索引、視圖、函數、存儲過程、觸發器、表、字典(動態視圖)等對象。其中相對來說表是最重要的。
62 在數據庫中一個表中可以創建多少個索引
創建索引的個數不受限制,但是一般會根據需要創建索引。
63索引分類和索引類型
【索引分類】:主鍵索引,唯一索引,普通索引,組合索引
【索引類型】:BTREE、HASH
64 事務的四個特性:(ACID)
事務具有四個特性:(ACID)
- ( Atomicity )原子性:事務中的操作要么全執行,要么全失敗
- (Consistency) 一致性:事務操作的前后,數據保持一致
- (Isolation) 隔離性:事務之間互補影響,具有四個級別
- 讀未提交(Read Uncommitted):可以讀取未提交的記錄。
- 讀已提交(Read Committed):事務中只能看到已提交的修改。
- 可重復讀(Repeatable Read):解決了不可重復讀問題(MySQL 默認隔離級別)
- 序列化(Serializable):最高隔離級別。
- (Durability) 持久性:事務提交后數據將會保存,即使系統奔潰了也不會影響數據
65八進制轉換為十進制
int(0o12) ----->10
66 哪些對象可以作為字典的key
可以hash的都可以作為key,
67 HTTP協議不同版本的區別
什么是HTTP協議? HTTP協議全稱HyperText Transfer Protocol,中文名超文本傳輸協議。是互聯網上應用最為廣泛的一種網絡協議。HTTP是基于TCP/IP協議的應用層協議,不涉及數據包的傳輸,主要是規定了客戶端和服務器之間的通信格式。默認使用80端口。現在HTTP已經演化出了很多個版本。HTTP/0.9 HTTP 0.9是最早發現的一個版本,在1991年發布,只接受GET一種請求方法,并且不支持請求頭。只支持純文本一種內容,服務器只能回應HTML格式的字符串,里邊不能插入圖片。HTTP 0.9具有典型的無狀態性,每個事務獨立進行處理,事務結束時就釋放這個連接。由此可見,HTTP協議的無狀態特點在其第一個版本0.9中已經成型。GET /index.htmlHTTP/1.0 1) HTTP 1.0是HTTP協議的第二個版本在1996年發布,如今仍然被廣泛使用,尤其是在代理服務器中。2) 1.0版本不僅僅支持GET命令還有POST和HEAD等請求方法。3) HTTP的請求和回應格式也發生了變化,除了要傳輸的數據之外,每次通信都包含頭信息,用來描述一些信息。4) 不再局限于0.9版本的HTML格式,根據Content-Type可以支持多種數據格式,這使得互聯網不僅僅可以用來傳輸文字,還可以傳輸圖像、音頻、視頻等二進制文件。5) 同時也開始支持cache,就是當客戶端在規定時間內訪問統一網站,直接訪問cache即可。6) 除了數據部分,每次通信都必須包括頭信息(HTTP header)。7) 其他的新增功能還包括狀態碼(status code)、多字符集支持、多部分發送(multi-part type)、權限(authorization)、緩存(cache)、內容編碼(content encoding)等。8) 但是1.0版本的工作方式是每次TCP連接只能發送一個請求,當服務器響應后就會關閉這次連接,下一個請求需要再次建立TCP連接,就是不支持 keep-alive。 TCP連接的建立成本很高,因為需要客戶端和服務器三次握手,并且開始時發送速率較慢(slow start)。所以,HTTP 1.0版本的性能比較差。隨著網頁加載的外部資源越來越多,這個問題就愈發突出了。為了解決這個問題,有些瀏覽器在請求時,用了一個非標準的Connection字段。HTTP/1.1 1) 最大變化,就是引入了持久連接(persistent connection),即TCP連接默認不關閉,可以被多個請求復用,不用聲明Connection: keep-alive。客戶端和服務器發現對方一段時間沒有活動,就可以主動關閉連接。不過,規范的做法是,客戶端在最后一個請求時,發送Connection: close,明確要求服務器關閉TCP連接。2) 加入了管道機制,在同一個TCP連接里,允許多個請求同時發送,增加了并發性,進一步改善了HTTP協議的效率。舉例來說,客戶端需要請求兩個資源。以前的做法是,在同一個TCP連接里面,先發送A請求,然后等待服務器做出回應,收到后再發出B請求。管道機制則是允許瀏覽器同時發出A請求和B請求,但是服務器還是按照順序,先回應A請求,完成后再回應B請求。3) 一個TCP連接現在可以傳送多個回應,勢必就要有一種機制,區分數據包是屬于哪一個回應的。這就是Content-length字段的作用,聲明本次回應的數據長度。4) 分塊傳輸編碼,使用Content-Length字段的前提條件是,服務器發送回應之前,必須知道回應的數據長度。對于一些很耗時的動態操作來說,這意味著,服務器要等到所有操作完成,才能發送數據,顯然這樣的效率不高。更好的處理方法是,產生一塊數據,就發送一塊,采用"流模式"(stream)取代"緩存模式"(buffer)。因此,1.1版規定可以不使用Content-Length字段,而使用"分塊傳輸編碼"(chunked transfer encoding)。只要請求或回應的頭信息有Transfer-Encoding字段,就表明回應將由數量未定的數據塊組成。5) 新增了請求方式PUT、PATCH、OPTIONS、DELETE等。6) 客戶端請求的頭信息新增了Host字段,用來指定服務器的域名。7) HTTP/1.1支持文件斷點續傳,RANGE:bytes,HTTP/1.0每次傳送文件都是從文件頭開始,即0字節處開始。RANGE:bytes=XXXX表示要求服務器從文件XXXX字節處開始傳送,斷點續傳。即返回碼是206(Partial Content)HTTP/2.0 1)二進制協議: HTTP/1.1 版的頭信息肯定是文本(ASCII編碼),數據體可以是文本,也可以是二進制。HTTP/2 則是一個徹底的二進制協議,頭信息和數據體都是二進制,并且統稱為"幀"(frame):頭信息幀和數據幀。2)多工: HTTP/2 復用TCP連接,在一個連接里,客戶端和瀏覽器都可以同時發送多個請求或回應,而且不用按照順序一一對應,這樣就避免了"隊頭堵塞"(HTTP2.0使用了多路復用的技術,做到同一個連接并發處理多個請求,而且并發請求的數量比HTTP1.1大了好幾個數量級)。 舉例來說,在一個TCP連接里面,服務器同時收到了A請求和B請求,于是先回應A請求,結果發現處理過程非常耗時,于是就發送A請求已經處理好的部分, 接著回應B請求,完成后,再發送A請求剩下的部分。3)頭信息壓縮: HTTP 協議不帶有狀態,每次請求都必須附上所有信息。所以,請求的很多字段都是重復的,比如Cookie和User Agent,一模一樣的內容,每次請求都必須附帶,這會浪費很多帶寬,也影響速度。 HTTP/2 對這一點做了優化,引入了頭信息壓縮機制(header compression)。一方面,頭信息使用gzip或compress壓縮后再發送;另一方面,客戶端和服務器同時維護一張頭信息表,所有字段都會存入這個表,生成一個索引號,以后就不發送同樣字段了,只發送索引號,這樣就提高速度了。4)服務器推送: HTTP/2 允許服務器未經請求,主動向客戶端發送資源,這叫做服務器推送(server push)。意思是說,當我們對支持HTTP2.0的web server請求數據的時候,服務器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次創建連接發送請求到服務器端獲取。這種方式非常合適加載靜態資源。 服務器端推送的這些資源其實存在客戶端的某處地方,客戶端直接從本地加載這些資源就可以了,不用走網絡,速度自然是快很多的。總結 HTTP/0.9:功能撿漏,只支持GET方法,只能發送HTML格式字符串。 HTTP/1.0:支持多種數據格式,增加POST、HEAD等方法,增加頭信息,每次只能發送一個請求(無持久連接) HTTP/1.1:默認持久連接、請求管道化、增加緩存處理、增加Host字段、支持斷點傳輸分塊傳輸等。 HTTP/2.0:二進制分幀、多路復用、頭部壓縮、服務器推送68 正則表達式的中文范圍
u4e00-uf9fa569 關于put和patch的區別
patch:更新部分資源,非冪等,非安全 put:更新整個資源,具有冪等性,非安全 注意: 冪等性:多次請求的結果和請求一次的結果一樣 安全性:請求不改變資源的狀態70 session 和 cookie的區別
- 作用范圍不同,Cookie 保存在客戶端(瀏覽器),Session 保存在服務器端。 - 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意數據類型,一般情況下我們可以在 Session 中保持一些常用變量信息,比如說 UserId 等。 - 有效期不同,Cookie 可設置為長時間保持,比如我們經常使用的默認登錄功能,Session 一般失效時間較短,客戶端關閉或者 Session 超時都會失效。 - 隱私策略不同,Cookie 存儲在客戶端,比較容易遭到不法獲取,早期有人將用戶的登錄名和密碼存儲在 Cookie 中導致信息被竊取;Session 存儲在服務端,安全性相對 Cookie 要好一些。 - 存儲大小不同, 單個 Cookie 保存的數據不能超過 4K,Session 可存儲數據遠高于 Cookie71 html 和 xml的區別
一、HTMLHTML(HyperTextMark-upLanguage)即超文本標記語言,是WWW的描述語言。二、XMLXML即ExtentsibleMarkup Language(可擴展標記語言),是用來定義其它語言的一種元語言,其前身是SGML(標準通用標記語言)。它沒有標簽集(tagset),也沒有語法規則(grammatical rule),但 是它有句法規則(syntax rule)。任何XML文檔對任何類型的應用以及正確的解析都必須是良構的(well-formed),即每一個打開的標簽都必須有匹配的結束標簽,不得含有次序顛倒的標簽,并且在語句構成上應符合技術規范的要求。XML文檔可以是有效的(valid),但并非一定要求有效。所謂有效文檔是指其符合其文檔類型定義(DTD)的文檔。如果一個文檔符合一個模式(schema)的規定,那么這個文檔是模式有效的(schema valid)。三、HTML與XML的區別通過以上對HTML及XML的了解,我們來看看他們之間到底存在著什么區別與聯系xml和html都是用于操作數據或數據結構,在結構上大致是相同的,但它們在本質上卻存在著明顯的區別。綜合網上的各種資料總結如下。(一)、語法要求不同:1. 在html中不區分大小寫,在xml中嚴格區分。2. 在HTML中,有時不嚴格,如果上下文清楚地顯示出段落或者列表鍵在何處結尾,那么你可以省略</p>或者</li>之類的結束標記。在XML中,是嚴格的樹狀結構,絕對不能省略掉結束標記。3. 在XML中,擁有單個標記而沒有匹配的結束標記的元素必須用一個/ 字符作為結尾。這樣分析器就知道不用查找結束標記了。4. 在XML中,屬性值必須分裝在引號中。在HTML中,引號是可用可不用的。5. 在HTML中,可以擁有不帶值的屬性名。在XML中,所有的屬性都必須帶有相應的值。6. 在XML文檔中,空白部分不會被解析器自動刪除;但是html是過濾掉空格的。(二)、標記不同:1、html使用固有的標記;而xml沒有固有的標記。2、Html標簽是預定義的;XML標簽是免費的、自定義的、可擴展的。(三)、作用不同:1. html是用來顯示數據的;xml是用來描述數據、存放數據的,所以可以作為持久化的介質!Html將數據和顯示結合在一起,在頁面中把這數據顯示出來;xml則將數據和顯示分開。 XML被設計用來描述數據,其焦點是數據的內容。HTML被設計用來顯示數據,其焦點是數據的外觀。2. xml不是HTML的替代品,xml和html是兩種不同用途的語言。 XML 不是要替換 HTML;實際上XML 可以視作對 HTML 的補充。XML 和HTML 的目標不同HTML 的設計目標是顯示數據并集中于數據外觀,而XML的設計目標是描述數據并集中于數據的內容。3. 沒有任何行為的XML。與HTML 相似,XML 不進行任何操作。(共同點)4. 對于XML最好的形容可能是: XML是一種跨平臺的,與軟、硬件無關的,處理與傳輸信息的工具。5. XML未來將會無所不在。XML將成為最普遍的數據處理和數據傳輸的工具。72 數組和列表的區別
1. 列表list與數組array的定義:列表是由一系列按特定順序排列的元素組成,可以將任何東西加入列表中,其中的元素之間沒有任何關系;Python中的列表(list)用于順序存儲結構。它可以方便、高效的的添加刪除元素,并且列表中的元素可以是多種類型。數組也就是一個同一類型的數據的有限集合。2. 列表list與數組array的相同點:a. 都可以根據索引來取其中的元素;3. 列表list與數組array的不同點:a.列表list中的元素的數據類型可以不一樣。數組array里的元素的數據類型必須一樣;b.列表list不可以進行數學四則運算,數組array可以進行數學四則運算;c.相對于array,列表會使用更多的存儲空間。73 垃圾回收機制
垃圾回收機制,Python 采用 GC 作為自動內存管理機制,GC要做的有2件事,一是找到內存中無用的垃圾對象資源,二是清除找到的這些垃圾對象,釋放內存給其他對象使用。如何實現上述2點了,Python 采用了 引用計數 為主, 標志清除和分代回收 為輔測策略。2.1 引用計數 查看源碼,每一個對象,在源碼里就是一個結構體表示,都會有一個計數字段.typedef struct_object {int ob_refcnt;struct_typeobject *ob_type; } PyObject; PyObject是每個對象必有的內容,其中ob_refcnt就是做為引用計數。當一個對象有新的引用時,它的ob_refcnt就會增加,當引用它的對象被刪除,它的ob_refcnt就會減少。 一旦對象的引用計數為0,該對象立即被回收,對象占用的內存空間將被釋放。此算法的優點和缺點都是非常明顯的: 優點:簡單實時性:一旦沒有引用,內存就直接釋放了。不用像其他機制等到特定時機。 缺點:需要額外的空間維護引用計數。不能解決對象的循環引用。(主要缺點) 接下來說一下什么是循環引用:A和B相互引用而且沒有外部引用A與B中的任何一個。也就是對象之間互相應用,導致引用鏈形成一個環。>>>>>>a = { } #對象A的引用計數為 1 >>>b = { } #對象B的引用計數為 1 >>>a['b'] = b #B的引用計數增1 >>>b['a'] = a #A的引用計數增1 >>>del a #A的引用減 1,最后A對象的引用為 1 >>>del b #B的引用減 1, 最后B對象的引用為 1執行 del 后,A、B對象已經沒有任何引用指向這兩個對象,但是這兩個對象各包含一個對方對象的引用,雖然最后兩個對象都無法通過其它變量來引用這兩個對象了,這對GC來說就是兩個非活動對象或者說是垃圾對象。理論上是需要被回收的。 按上面的引用計數原理,要計數為0才會回收,但是他們的引用計數并沒有減少到零。因此如果是使用引用計數法來管理這兩對象的話,他們并不會被回收,它會一直駐留在內存中,就會造成了內存泄漏(內存空間在使用完畢后未釋放)。為了解決對象的循環引用問題,Python 引入了標記清除和分代回收兩種GC機制。2.2 標記清除 標記清除主要是解決循環引用問題。標記清除算法是一種基于追蹤回收(tracing GC)技術實現的垃圾回收算法。 它分為兩個階段:第一階段是標記階段,GC會把所有的 活動對象 打上標記,第二階段是把那些沒有標記的對象 非活動對象 進行回收。那么GC又是如何判斷哪些是活動對象哪些是非活動對象的呢?對象之間通過引用(指針)連在一起,構成一個有向圖,對象構成這個有向圖的節點,而引用關系構成這個有向圖的邊。從根對象(root object)出發,沿著有向邊遍歷對象,可達的(reachable)對象標記為活動對象,不可達的對象就是要被清除的非活動對象。根對象就是全局變量、調用棧、寄存器。在上圖中,我們把小黑圈視為全局變量,也就是把它作為root object,從小黑圈出發,對象1可直達,那么它將被標記,對象2、3可間接到達也會被標記,而4和5不可達,那么1、2、3就是活動對象,4和5是非活動對象會被GC回收。標記清除算法作為 Python 的輔助垃圾收集技術主要處理的是容器對象(container,上面講迭代器有提到概念),比如list、dict、tuple等,因為對于字符串、數值對象是不可能造成循環引用問題。Python使用一個雙向鏈表將這些容器對象組織起來。Python 這種簡單粗暴的標記清除算法也有明顯的缺點:清除非活動的對象前它必須順序掃描整個堆內存,哪怕只剩下小部分活動對象也要掃描所有對象。2.3 分代回收 分代回收是一種以空間換時間的操作方式。Python將內存根據對象的存活時間劃分為不同的集合,每個集合稱為一個代,Python將內存分為了3“代”,分別為年輕代(第0代)、中年代(第1代)、老年代(第2代),他們對應的是3個鏈表,它們的垃圾收集頻率與對象的存活時間的增大而減小。新創建的對象都會分配在年輕代,年輕代鏈表的總數達到上限時,Python垃圾收集機制就會被觸發,把那些可以被回收的對象回收掉,而那些不會回收的對象就會被移到中年代去,依此類推,老年代中的對象是存活時間最久的對象,甚至是存活于整個系統的生命周期內。同時,分代回收是建立在標記清除技術基礎之上。分代回收同樣作為Python的輔助垃圾收集技術處理容器對象74 樂觀鎖和悲觀鎖
悲觀鎖(Pessimistic Lock)1??理解 當要對數據庫中的一條數據進行修改的時候,為了避免同時被其他人修改,最好的辦法就是直接對該數據進行加鎖以防止并發。這種借助數據庫鎖機制,在修改數據之前先鎖定,再修改的方式被稱之為悲觀并發控制【Pessimistic Concurrency Control,縮寫“PCC”,又名“悲觀鎖”】。悲觀鎖,具有強烈的獨占和排他特性。它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度。因此,在整個數據處理過程中,將數據處于鎖定狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改數據)。之所以叫做悲觀鎖,是因為這是一種對數據的修改持有悲觀態度的并發控制方式。總是假設最壞的情況,每次讀取數據的時候都默認其他線程會更改數據,因此需要進行加鎖操作,當其他線程想要訪問數據時,都需要阻塞掛起。悲觀鎖的實現:傳統的關系型數據庫使用這種鎖機制,比如行鎖、表鎖、讀鎖、寫鎖等,都是在操作之前先上鎖。Java 里面的同步 synchronized 關鍵字的實現。2??悲觀鎖主要分為共享鎖和排他鎖:共享鎖【shared locks】又稱為讀鎖,簡稱 S 鎖。顧名思義,共享鎖就是多個事務對于同一數據可以共享一把鎖,都能訪問到數據,但是只能讀不能修改。排他鎖【exclusive locks】又稱為寫鎖,簡稱 X 鎖。顧名思義,排他鎖就是不能與其他鎖并存,如果一個事務獲取了一個數據行的排他鎖,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排他鎖。獲取排他鎖的事務可以對數據行讀取和修改。3??說明 悲觀并發控制實際上是“先取鎖再訪問”的保守策略,為數據處理的安全提供了保證。但是在效率方面,處理加鎖的機制會讓數據庫產生額外的開銷,還有增加產生死鎖的機會。另外還會降低并行性,一個事務如果鎖定了某行數據,其他事務就必須等待該事務處理完才可以處理那行數據。 三、樂觀鎖(Optimistic Locking)1??理解 樂觀鎖是相對悲觀鎖而言的,樂觀鎖假設數據一般情況不會造成沖突,所以在數據進行提交更新的時候,才會正式對數據的沖突與否進行檢測,如果沖突,則返回給用戶異常信息,讓用戶決定如何去做。樂觀鎖適用于讀多寫少的場景,這樣可以提高程序的吞吐量。樂觀鎖采取了更加寬松的加鎖機制。也是為了避免數據庫幻讀、業務處理時間過長等原因引起數據處理錯誤的一種機制,但樂觀鎖不會刻意使用數據庫本身的鎖機制,而是依據數據本身來保證數據的正確性。樂觀鎖的實現:CAS 實現:Java 中java.util.concurrent.atomic包下面的原子變量使用了樂觀鎖的一種 CAS 實現方式。版本號控制:一般是在數據表中加上一個數據版本號 version 字段,表示數據被修改的次數。當數據被修改時,version 值會 +1。當線程 A 要更新數據時,在讀取數據的同時也會讀取 version 值,在提交更新時,若剛才讀取到的 version 值與當前數據庫中的 version 值相等時才更新,否則重試更新操作,直到更新成功。2??說明 樂觀并發控制相信事務之間的數據競爭(data race)的概率是比較小的,因此盡可能直接做下去,直到提交的時候才去鎖定,所以不會產生任何鎖和死鎖。 四、具體實現1??悲觀鎖實現方式 悲觀鎖的實現,往往依靠數據庫提供的鎖機制。在數據庫中,悲觀鎖的流程如下:在對記錄進行修改前,先嘗試為該記錄加上排他鎖(exclusive locks)。如果加鎖失敗,說明該記錄正在被修改,那么當前查詢可能要等待或者拋出異常。具體響應方式由開發者根據實際需要決定。如果成功加鎖,那么就可以對記錄做修改,事務完成后就會解鎖了。期間如果有其他對該記錄做修改或加排他鎖的操作,都會等待解鎖或直接拋出異常。以 MySql Innodb 引擎舉例,說明 SQL 中悲觀鎖的應用要使用悲觀鎖,必須關閉 MySQL 數據庫的自動提交屬性set autocommit=0。因為 MySQL 默認使用 autocommit 模式,也就是說,當執行一個更新操作后,MySQL 會立刻將結果進行提交。以電商下單扣減庫存的過程說明一下悲觀鎖的使用:在對 id = 1 的記錄修改前,先通過 for update 的方式進行加鎖,然后再進行修改。這就是比較典型的悲觀鎖策略。如果發生并發,同一時間只有一個線程可以開啟事務并獲得 id=1 的鎖,其它的事務必須等本次事務提交之后才能執行。這樣可以保證當前的數據不會被其它事務修改。使用 select…for update 鎖數據,需要注意鎖的級別,MySQL InnoDB 默認行級鎖。行級鎖都是基于索引的,如果一條 SQL 語句用不到索引是不會使用行級鎖的,會使用表級鎖把整張表鎖住,這點需要注意。2??樂觀鎖實現方式樂觀鎖不需要借助數據庫的鎖機制主要就是兩個步驟:沖突檢測和數據更新。比較典型的就是 CAS (Compare and Swap)。CAS 即比較并交換。是解決多線程并行情況下使用鎖造成性能損耗的一種機制,CAS 操作包含三個操作數——內存位置(V)、預期原值(A)和新值(B)。如果內存位置的值(V)與預期原值(A)相匹配,那么處理器會自動將該位置值更新為新值(B)。否則,處理器不做任何操作。無論哪種情況,它都會在 CAS 指令之前返回該位置的值。CAS 有效地說明了“我認為位置(V)應該包含值(A)。如果包含該值,則將新值(B)放到這個位置;否則,不要更改該位置,只告訴我這個位置現在的值即可”。Java 中,sun.misc.Unsafe 類提供了硬件級別的原子操作來實現這個 CAS。java.util.concurrent包下大量的類都使用了這個 Unsafe.java 類的 CAS 操作。當多個線程嘗試使用 CAS 同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程并不會被掛起,而是被告知這次競爭中失敗,并可以再次嘗試。比如前面的扣減庫存問題,通過樂觀鎖可以實現如下: 樂觀鎖使用在更新之前,先查詢一下庫存表中當前庫存數(quantity),然后在做 update 的時候,以庫存數作為一個修改條件。當提交更新的時候,判斷數據庫表對應記錄的當前庫存數與第一次取出來的庫存數進行比對,如果數據庫表當前庫存數與第一次取出來的庫存數相等,則予以更新,否則認為是過期數據。75 html和xml的區別
- html是網頁標簽的標準或規范, 主要用于將標簽的內容以不同的形式渲染到瀏覽器中. - xml是一種數據格式,主要用于不同程序之間的數值交互。<users><user id="10001"><name>disen</name><loves><val>Music</val><val>Play</val></loves></user></users>76 sys和os兩個模塊的區別
- sys是Python解析器內部的模塊- 添加代碼的root目錄 sys.path.insert(0, '')- 查看python的版本,sys.version/platform- 獲取命令行參數 sys.argv- 捕獲全局的異常處理函數 sys.excepthook - os是python程序針對操作系統的模塊- 文件與目錄操作- 環境變量的操作 os.environ- 創建子進程(操作系統命令)os.system(), os.popen()77 協程的三種方式
異步的 輪詢方式 select, 主動去做的 回調方式 poll 被動的 增強式回調方式 epoll78 pymysql的connect()方法的常用參數
-host -port -user -passwd -db -charset -cursor -autocommit: False79 寫出pymsql的Cursor對象的方法與屬性
-execute(sql, args)args是tuple或list時,填充SQL語句中的%s占位符args是dict時,填充SQL語句的%(name)s占位符-fetchall() -fetone() -rowcount -callproc(name, args) 調用存儲過程(procedure) -close80 簡述哪些對象可以使用with關鍵字
- stream文件流對象 - Condition 線程的條件變量對象 - Lock線程鎖對象 - Connection數據庫連接類cursor的對象 - 實現__enter__和__exit__兩種方法的類對象81 re正則的compile、match、search、findall的區別
- compile(pattern, flags) 創建正則對象,可以重復或多次使用。正則實例對象可以調用其他三個方法。 - match(pattern, string, flags=0) 匹配內容中正則部分,如果未匹配成功,返回None,匹配成功返回match對象。一般用于驗證數據場景(手機號,身份證,郵箱)。 - search(pattern, string, pos=0, flags=0) 同match相似,返回第一次匹配正則是內容,未匹配成功返回None。匹配成功之后,可以通過match對象的group獲取匹配的內容。 - findall(pattern, string, flags=0) 匹配所有的符合正則表達式的內容。82 查看端口號的占用情況的命令
首先要檢查是不是有net-tools工具 沒有的話安裝 yum -y install net-toolsnetstat -ltpn | grep <端口號>83 WSGI、uWSGI和uwsgi的區別
WSGI,全稱Web Server Gateway Interface,是為Python語言定義的Web服務器和Web應用程序或框架之間的一種簡單而通用的接口 。描述的是Web服務器如何與Web應用間進行通信。WSGI說白了就是一個網關,網關的作用就是在協議之間進行轉換。uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。它要做的就是把HTTP協議轉化成語言支持的網絡協議。比如把HTTP協議轉化成WSGI協議,讓Python可以直接使用。Nginx中HttpUwsgiModule的作用是與uWSGI服務器進行交換。WSGI,是一種描述web服務器(如nginx,uWSGI等服務器)如何與web應用程序(如用Django、Flask框架寫的程序)通信協議。 uwsgi協議是一個uWSGI服務器自有的協議,它用于定義傳輸信息的類型(type of information),每一個uwsgi packet前4byte為傳輸信息類型描述,用于與nginx等代理服務器通信,它與WSGI相比是兩樣東西。 uWSGI是實現了uwsgi和WSGI兩種協議的Web服務器。84 Redis的五種數據類型
string hash list set zset(有序集合)85 select、poll和epoll之間的區別
https://www.cnblogs.com/aspirant/p/9166944.html86 文件上傳的報文格式
87 埋點
獲取某種資源的請求時,埋點對請求進行處理,用于進行數據分析88 lock和Rlock的區別
lock和rlock都可以用來同步進程或者線程,它們之間的區別在于rlock是可重入的,也就是一個線程可以獲取多次,只有在release相同次數時,rlock才會有locked狀態轉換為unlocked。acquire和release的具體區別: Lock.acquire([blocking]): 線程阻塞或者非阻塞的獲取鎖1.當不帶參數調用時,調用線程會阻塞,直到鎖的狀態是unlocked,然后把鎖設置為locked,返回True2.當設置blocking=False時,調用線程不會阻塞3.如果有多個線程因為獲取鎖而阻塞的話,當鎖的狀態是unloacked的時候,只有一個線程能繼續執行,具體哪個線程獲取鎖,繼續執行要看具體的執行環境RLock.acquire([blocking]): 線程阻塞或者非阻塞的獲取鎖1.不帶參數調用 如果線程已經獲的了鎖,那么鎖的引用加1,返回True;如果線程沒有獲得鎖,線程阻塞直到鎖的狀態是unlocked. 如果這個鎖沒有被任何線程擁有過,設置鎖的引用計數為1,然后返回True。2.設置blocking=False, 線程不阻塞Lock.release(): 釋放鎖Rlock.release(): 釋放鎖,每釋放一個,鎖的引用計數減1,直到鎖的引用計數是0,鎖的狀態才設置為unlocked89 RESTful的四個規范
- 每一種資源都有一個唯一的標識 URI(統一資源標識符) - 每種資源都具有GET/POST/PUT/PATCH/DELETE等相關的動作(謂詞) - 每種資源的動作都是無狀態的(短連接(請求頭) Connection: close)【擴展】長連接(請求頭) Connection: keep-alive; - 每一個動作交互的數據為json或xml90 http的三次握手和https的三次握手
http的三次握手 第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,并進入SYN_SEND狀態,等待服務器確認。 第二次握手:服務器收到syn包,必須確認客戶的syn(ack=j+1),同時自己也發送一個SYN包(syn=k),此時服務器進入SYN_RECV狀態。 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。? https的三次握手
91 flask的四大內置對象
- request from flask import request 線程本地變量 - session 針對MTV,處理有狀態連接的數據,session和cookie組合使用 - config 當前項目的配置信息 - g(global) 局部的而函數內可以修改全局的變量92 響應狀態碼含義
1xx: 表示臨時響應并需要請求者繼續執行操作的狀態代碼100 繼續101 切換協議 2xx:表示成功處理了請求的狀態的碼200 成功201 已創建202 已接受203 非授權信息204 無內容205 重置內容206 部分內容 3xx: 表示要完成請求,需要進一步操作,通常,這些狀態代碼用來重定向300 多種選擇301 永久移動302 臨時移動303 查看其他位置304 未修改305 使用代理307 臨時重定向 4xx: 這些狀態碼表示請求可能出錯,妨礙了服務器的處理400 錯誤請求401 未授權403 禁止404 未找到405 方法禁用406 不接受407 需要代理授權(與401)類似408 請求超時409 沖突410 已刪除411 需要有效長度412 未滿足前提條件413 請求實體過大414 請求的url過長415 不支持的媒體類型416 請求范圍不符合要求417 未滿足期望值 5xx: 這些狀態碼表示服務器在嘗試處理請求時發生內部錯誤。這些錯誤可能是服務器本身的錯誤,而不是請求出錯。500 服務器內部錯誤501 尚未實施502 錯誤網關503 服務不可用504 網關超時505 服務器不支持請求中所用的http協議版本二、數據分析面試題
三、機器學習面試題
四、linux面試題
1.linux常用命令
1.ls命令 :查看當前路徑下的文件及目錄-ls -l:以列表的形式常看文件及目錄-ls -li:以列表的形式并且顯示編號-ls -lS --block-size=K:按照文件大小來排序,大小單位為K(默認降序)-ls -ltr:以生成時間來排序:r代表反排,所以當前為升序-ls -lA:查看當前目錄下的所有文件(包含.開頭的隱藏文件)但不顯示.當前目錄和..父級目錄信息-ls -la:顯示.當前目錄和..父級目錄2.cd命令 :跳轉當前所在路徑的命令 3.pwd命令 :查看當前路徑的命令(絕對路徑) 4.mkdir命令 :創建文件夾命令 5.rmdir命令 :刪除文件夾命令 6.rm命令 :刪除一個不為空的目錄或者文件-rm -rf 文件目錄所在位置-rm -rf *.txt 刪除當前目錄下所有的txt文件 7.touch :創建新的文件命令 8.echo :打印文本的命令 9.find :查找文件或目錄(一般結合管道(|)和grep使用) 10.cp :復制文件的命令 11.mv :剪切文件的命令 12.cat :查看文件內容的命令 13.grep :過濾相關內容的命令2.文件權限操作
1.文件權限概念:一個文件或目錄的權限由三大部分組成的,分別是用戶權限+用戶組權限+其它組權限。每部分的權限又分為三小部分,分別是 r(讀), w(寫), x (執行),代表的數值分別是 r: 4, w:2, x: 1,如果權限值為0時,使用 -表示。2.修改文件的權限:chmod命令- 字符權限:chmod [ugoa] [r|w|x]- 數值權限:chmod 777 a.txt3.服務操作
1.systemctl命令:- start 啟動服務- stop 終止服務- restart 重啟服務- enable 啟動服務(第一次啟動)- disable 禁用服務- status 查看服務狀態 2.service命令:同systemctl雷同 3.netstat命令:監測到網絡數據流的工具- netstat -s: 查看網絡的統計信息- netstat - ltpn: 查看所有tcp協議的程序及端口號 4.ps命令:查看當前運行的進程 ----> ps -ef 5.kill命令:殺死某一個進程 ----> kill -9 進程號 6.內存使用情況top命令:實時獲取內存和進程的使用情況。free命令:命令格式: free [-h|-k|-b|-m|-g|-t] 7.磁盤使用情況df命令:查看當前所有掛裝載磁盤上的存儲情況 ----> df [-l|-a|-h] 8.定時任務crontab命令:使用crontab命令查看、編輯、發布和刪除定時任務。4.yum安裝命令
1.更新與配置資源yum update -y 2.安裝git- yum search git- yum install git -y- git --version 3.安裝python3.7- yum install wget -y- wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz- scp root@10.36.174.67:/opt/project1/python3.7.tar.xz /opt/- tar -xvf python3.7.tar.xz5.docker服務
1.docker基本概念Docker是虛擬化的容器服務。是基于共享底層系統內核和硬件資源,構建的一個虛擬的系統。與VM虛擬機的不同之處,是共享宿主機的內存、存儲等相關的資源。而VM是獨立的內存、CPU和存儲等資源。2.docker組成部分- Docker的客戶端:為用戶提供操作docker的工具,用戶輸入的命令發送給docker守護進程,則docker守護來管理docker鏡像和容器。主要命令是docker【重點】- Docker的守護進程(dockerd: docker daemon 服務):是一種后端進程(即沒有界面),也是一種服務。在使用docker命令時,必須保證docker服務啟動(systemctl start docker)。負責接收docker客戶端發送的指令并解析和執行。- Docker鏡像:容器的創建是依賴于鏡像的,可以將鏡像看成為一個類,容器可以被看成為類的實例。鏡像分本地鏡像和遠程鏡像, 本地鏡像是從遠程鏡像倉庫中下載的,也可以是從某一個容器中生成的。- Docker容器:由鏡像生成的, 一個容器即是一個微型的linux系統,可以進入容器中進行相關的操作,但是linux的工具(如vim)不存在,如需要,則手動安裝。容器中的數據可以由宿主機(容器所在的操作系統)進行同步或管理。最后,容器可以生成本地鏡像。3.docker的常用命令docker images # 查看本地所有鏡像docker search <鏡像名> # 搜索相關的鏡像資源docker pull <鏡像名>[:版本號] # 從遠程鏡像倉庫中下載到本地, 默認版本為latestdocker run [-itd] [-v <宿主機的文件目錄>:<容器的文件目錄> ...] [-p <宿主機的端口>:<容器的端口> ...] --name <容器名> [--hostname hostname] [--ip ipv4地址] [--network network] [-e 環境變量=值 ...] <鏡像名或ID>[:版本號] # 運行docker ps [-a] # 查看docker中正在運行的容器(子進程), -a代表所有容器(啟動、未啟動)docker stop|start|restart <容器名或ID>docker logs [-n 最后的行數] <容器名或ID> # 查看容器的日志docker cp <宿主機文件位置> <容器名或ID>:<容器文件位置> # 宿主機和容器之間相互復制文件docker exec [-it] <容器名或ID> <容器內部的命令> # 執行容器內部的命令(完整的)docker rmi <鏡像名或ID> # 刪除鏡像docker rm <容器名或ID> # 刪除容器docker save -o xxx.tar <IMAGE> ... 將一個或多個鏡像打包成一個tar壓縮文件docker load -i xxxx.tar 從一個tar壓縮文件中加載一個或多個鏡像docker tag SOURSE_IMAGE[:TAG] TARGET_IMAGE[:TAG] 從源鏡像重新標記新的鏡像名4.docker的網絡操作docker network [connect|create|ls|inspect|disconnect|prune|rm]6.pymysql測試連接
1.pip安裝pymysqlpip install pymysql -i https://mirrors.aliyun.com/pypi/simple2.編寫connect_mysql.py文件 from pymysql import Connect conn = Connect(host='10.36.174.67',port=3306,user='root',passwd='root',db='mysql',charset='utf8') print('--connect OK--') with conn.cursor() as c:c.execute('select user,host from user')for row in c.fetchall():print(row) 3.執行測試腳本python connect_mysql.py7.vi編輯器
1.vi編輯器基本概念- Linux強大的文本編輯器,存在三種模式:選擇(默認)模式、編輯模式、命令行模式2.模式切換:- 從選擇模式 切換 到編輯模式: 按 i鍵(當前光標位置插入編輯)- 從編輯模式 切換 到 選擇模式: ESC鍵- 從選擇模式 切換 到 命令行模式: Shift + :3.編輯模式:- 按 i插入, - 按 o當前行下插入新行- 按O(shift + o) 當前行的上方插入一行- 按I(shift+i) 移動光標到當前行的行首- 按A(shift+a)移動光標到當前行的行尾- 按u撤消之前的操作- 按ctrl+r取消撤消操作- 按x 刪除當前光標所在的字符- 按dd刪除當前行(剪貼的效果,即可以dd之后按p來粘貼)。- 按數字+dd 從當前光標所在的行開始,刪除 n 行。 4dd表示當前行開始向下刪除4開行。- 按nyy 從當前光標開始復制n行- 按p在當前光標所在行的下方開始粘貼(之前復制的內容)- 按gg進入首行首字符位置- 按Shift+g進入最后一行首字符位置- 按gg d G 清空文件內容4.命令行模式:- /查詢的內容- set number 顯示行號- 行號 跳轉到指定行號的行首- w 寫入,不退出- q 退出,前提沒有修改文件(正常退出)- q! 強制退出, 不保存- %s/查找的內容/替換的內容/g 查找并替換全部8.用戶及組命令
useradd、usermod、userdel、passwd 、chown 命令 1.創建系統用戶:useradd或adduser 可以創建linux用戶常用的選項:-d, --home-dir HOME_DIR 指定home目錄-e, --expiredate EXPIRE_DATE 指定用戶的過期時間-g GID 指定主組的名稱, 默認用戶名即是主組名-G GID 指定附加組的名稱-m 創建用戶的家目錄(Home)-p PASSWORD 指定口令-r 表示創建系統用戶,非系統用戶不能ssh遠程登錄2.刪除用戶:userdel -fr 用戶名-f 是強制刪除,沒有提示-r 是刪除用戶的home目錄和mail相關資源3.修改用戶口令使用 passwd修改用戶的新口令。9.mysql創建用戶和數據庫
1.查看數據庫show databases;2.打開數據庫use databases;3.創建用戶create user 'disen'@'%' identified by 'disen';4.授權grant all privileges on stu.* to 'disen'@'%';如果授權之后,無法使用數據庫,可以刷新試試flush privileges;10.linux的目錄結構
Linux操作系統中的文件目錄結構:/ 根目錄,位于Linux文件系統目錄結構的頂層,一般根目錄下只存放目錄,不要存放文件,/etc、/bin、/dev、/lib、/sbin應該和根目錄放,類同Window的根路徑是各個盤符(C:、D:)~ 當前用戶的home(家)目錄 (非root用戶是在/home/{用戶名}, root用戶的家目錄是 /root)/bin : 提供用戶使用的基本命令, 存放二進制命令,不允許關聯到獨立分區,OS啟動會用到里面的程序。/boot:用于存放引導文件,內核文件,引導加載器./sbin:管理類的基本命令,不能關聯到獨立分區,OS啟動時會用到的程序(重要的命令通常處于bin,不重要的則安裝在sbin)。/lib:存放系統在啟動時依賴的基本共享庫文件(.so)以及內核模塊文件. 系統使用的函數庫的目錄 也存放了大量的腳本庫文件 ,程序在執行過程中,需要調用時會用到/lib64:存放64位系統上的輔助共享庫文件./etc: 系統配置文件存放的目錄,該目錄存放系統的大部分配置文件和子目錄,不建議在此目錄下存放可執行文件 。/home:普通用戶主目錄,當新建賬戶時,都會分配在此,建議單獨分區,并分配額外空間用于存儲數據。/root: 系統管理員root的宿主目錄,系統第一個啟動的分區為/,所以最好將/root和/放置在一個分區下。/media:便攜式移動設備掛載點目錄./mnt:臨時文件系統掛載點./dev: 設備(device)文件目錄,存放linux系統下的設備文件,訪問該目錄下某個文件,相當于訪問某個設備,存放連接到計算機上的設備(終端、磁盤驅動器、光驅及網卡等)的對應文件 (b 隨機訪問,c 線性訪問)/opt:第三方應用程序的安裝位置./srv: 服務啟動之后需要訪問的數據目錄,存放系統上運行的服務用到的數據,如www服務需要訪問的網頁數據存放在/srv/www內。/tmp:存儲臨時文件, 任何人都可以訪問,重要數據一定不要放在此目錄下。/usr: 應用程序存放目錄,/usr/bin 存放保證系統擁有完整功能而提供的應用程序, /usr/share 存放共享數據,/usr/lib 存放不能直接運行的,卻是許多程序運行所必需的一些函數庫文件,_/usr/local 存放軟件升級包,第三方應用程序的安裝位置,/usr/share/doc _系統說明文件存放目錄。/var :放置系統中經常要發生變化的文件,如日志文件。/var/log 日志目錄及文件./var/tmp:保存系統兩次重啟之間產生的臨時數據./proc: 用于輸出內核與進程信息相關的虛擬文件系統,目錄中的數據都在內存中,如系統核心,外部設備,網絡狀態,由于數據都存放于內存中,所以不占用磁盤空間/sys : 用于輸出當前系統上硬件設備相關的虛擬文件系統.五、Linux shell編程總結
五、MySQL面試題
1.什么是數據庫
1.數據庫的基本概念:- 數據庫(Database)是一種存儲結構化數據的方式,一般存在兩種類型的數據庫: 關系型數據庫、非關系型數據庫。- 關系型數據庫: 存儲二維關系表的倉庫, 二維關系表是由列(特征)和行組成的。提供標準的SQL語句進行管理(創建、修改、刪除)。關系型數據庫一般都支持約束、索引、視圖、函數、存儲過程、觸發器、表、字典(動態視圖)等對象。【重點】- 非關系型數據庫: 不需要使用SQL,通過SDK(軟件開發環境-模塊或庫, Software Development Kit)相關的方法進行操作,不支持二維關系結構,又稱之為NoSQL數據庫。包含redis、mongodb等。2.有哪些關系型數據庫
- 大廠的關系型數據庫: DB2(IBM公司)、Oracle(甲骨文公司)、MySQL(原Sun公司,目前也是甲骨文公司)。 - 其它的關系型數據庫:MariDB(個人, 同MySQL一個作者)、 posgreSQL(開源的數據庫) - Hadoop家族的數據庫: Hive(依賴MySQL, MapReduce), Hbase(實時) - 嵌入式設備中的數據庫: sqlite3(沒有特定的數據類型)、IotDB(分布式物聯網存儲的實時數據庫)3.三個數據范式
1.數據范式的基本概念:限制表的設計, 讓表的結構更合理、減少數據冗余。 2.第一范式:確保每一個列保持原子性(列不可分隔)。理解:表字段每一列一個屬性,不可在差分成兩個或者多個列。 3.第二范式:確保每一列的數據都和主鍵相關,即表中存在主鍵約束。理解:存在任意的一個表字段,都和表的主鍵存在部分依賴。 4.第三范式:確保每一列都和主鍵直接相關,而不能間接相關。即存在主外鍵關系。理解:存在一個表字段,和主鍵存在傳遞函數關系(即存在主外鍵關系)4.DDL語句
1.DDL語句基本概念:(主要是對表、視圖、...進行操作)DDL 數據庫描述或定義語言(Data Definition Language),包含數據庫、表、視圖、函數、索引、存儲過程、觸發器等對象的創建、修改和刪除等操作。4.1創建和刪除數據庫
1.創建數據庫:create database 數據庫名 2.刪除數據庫:drop database 數據庫名4.2創建表
1.語法:create table [if not exists] <表名>(<字段名> <字段類型>[ (字段數據長度) ] [約束] [comment 注釋文本], ...,[constraint 表級約束語句]) [engine=INNODB|MYISAM|MEMERY|CSV] [character set 字符集];2.注意創建表的時候主要關注:字段名,字段類型,約束,和引擎3.特別注意:constraint子句constraint [約束名稱] 約束類型 [index_type: {BTREE, HASH}] (字段名,...) [references 引用表的名稱(引用的字段名) on <delete|update> <restrict|cascade|set null|no action|set default> ]4.3修改表
修改表: 表名、表字段名、字段類型及字段的約束。 1.修改表名alter table 表名 rename as|to 新表名舉例:alter table book rename as tb_book;2.修改表字段alter table 表名 change column 舊字段名 新字段名 類型舉例:alter table tb_book change column name book_name varchar(40);3.修改字段類型alter table 表名 modify 列名 類型(長度)舉例:alter table tb_book modify summary varchar(200);4.刪除字段主外鍵約束- 刪除外鍵約束:alter table 表名 drop foreign key 約束名稱舉例:alter table tb_book drop foreign key book_author_fk;- 刪除主鍵約束:alter table 表名 drop primary key舉例:alter table tb_author drop primary key;- 刪除唯一約束:alter table <表名> drop {index|key} 唯一約束名或列名舉例:alter table tb_book drop index name;5.刪除字段alter table 表名 drop 字段名舉例:alter table tb_book drop summary;6.添加字段alter table 表名 add 字段名 數據類型 約束 注釋等舉例:alter table tb_book add column summary text not null;7.添加字段約束alter table <表名>add [constraint [約束名] ] | primary key [index_type: {using btree|hash}] (字段1, 字段2, ....) | unique [key | index ] [index_name] [index_type] (字段1, 字段2, ...) | foreign key (字段1, 字段2,...) references 引用表名(字段1,字段2, ...) [on delete|update restrict|cascade|set null|no action|set default]舉例:alter table tb_author modify author_id integer primary key auto_increment; -- alter table tb_author add primary key (author_id);4.4刪除表
drop table 表名4.5查詢表結構
方式一:DESC 方式二:show create table 表名4.6查看所有的表
show tables;4.7子查詢創建表
create table 表名 select子句 舉例:create table tb_bejin_authorselect * from tb_author where city='北京';5.DML語句
1.DML語言的基本概念:(主要是對表中的數據進行增刪改的操作)DML(Data Manipulation Language) 數據操縱語言,主要負責數據(行或記錄)的插入、更新和刪除操作。5.1增加數據
1.單行插入:insert into <表名> [(字段1, 字段2, ...)] values (字段值1, 字段值2, ...) 舉例:insert into tb_author values(1, 'disen', '西安', '17791692095');2.多行插入:insert into <表名> [((字段1, 字段2, ...))] values (字段值1, 字段值2, ...), (字段值1, 字段值2, ...),(字段值1, 字段值2, ...),...(字段值1, 字段值2, ...); 舉例:insert into tb_author(city, name, phone) values ('北京', '老鄧', '18918810018'), ('北京', '老劉', '17866541239'), ('杭州', '老馬', '18766541908');3.子查詢方式插入:insert into <表名> [(字段1, ...)] select子句; 舉例:insert into tb_bejin_author select * from tb_author where city='北京';5.2更新數據
update <表名> set 字段1=字段值1 [,字段2=字段值2, ...] [where 子句] 舉例:update tb_author set city='上海' where city='西安' and name='disen';5.3刪除數據
delete from <表名> [where 子句] 舉例:delete from tb_book where act_price <= 15;6.DQL語句
1.DQL語句的基本概念:(主要是對表中的數據進行查看操作)DQL(Data Query Language)數據查詢語言,主要負責數據的查詢,包含單表查詢、多表查詢、子查詢、分組查詢、條件查詢、模糊查詢、分頁查詢、窗口函數統計等。6.1select from where語句
1.selectselect后面主要跟的是表字段,篩選想要的字段 2.fromfrom后面主要跟的是表名,表示從哪個表里面去查看 3.wherewhere后面主要跟的是條件,表示滿足這樣條件的表數據有哪些 4.group by、having,order by、limit、offset、rows等這些主要是更在where后面用于細致的過濾條件6.2內連接、外鏈接、自然連接語句
1.內連接join on:將兩個主外鍵關系的表進行連接,返回的是符合匹配后的數據join后面跟的是要被連接的表 on后面跟的是條件:兩個表主外鍵相等 2.外鏈接- 左外連接:left join on不同之處在于,連接后的表除了保存了匹配后的數據,還保存了左邊表中沒有匹配的數據- 右外連接:right join on不同之處在于,連接之后的表除了保存了匹配之后的數據,還保存了右邊表中沒有匹配的數據 3.自然連接join:和內連接的原理一致,只不過他不在需要on后面的主外鍵相當的條件了,默認會匹配他們的主外鍵關系,也是我們在設計模型中常用的連接方式6.3分組語句
group by 分組子句,可以按列中相同的數據進行分組,分組之后的數據可以聚合計算,聚合計算函數包含最小min()、最大max()、求和sum()、統計數量count和平均avg()。6.4排序語句
order by 子句可以按列的值進行升序ASC、降序DESC進行排序 【注意】order by 可以對多個列進行排序,先左后右。如果左邊的值相同的情況下,按右邊的列值進行排序。6.5分頁語句
mysql 中分頁使用limit 關鍵字, limit子句在select查詢語句的最后位置。 limit 起始行號(從0開始), 記錄個數(行數,一般使用10, 20, 50, 100)6.6union語句
- union 語句實現兩個select子查詢的數據聯合。默認是去重的。 - union all 保留所有子查詢的結果,不去重。 舉例:select a.book_id, a.book_name, b.name as author_name,b.author_idfrom tb_book anatural left join tb_author bunionselect a.book_id, a.book_name, b.name as author_name,b.author_idfrom tb_book anatural right join tb_author b;6.7windows語句
1.windows語句基本概念:- mysql 從8.0開始支持窗口語句查詢,即分區統計和現在數據進行連接顯示(輸出 )。一般配合 聚合函數+ over(), over()函數中可以指定分區(分組)的字段,即指定partition by子句。當然也可以使用其它的窗口函數,如rank實現排名。2.常用語句:- 聚合函數+over()- 費聚合函數+over()- row_number()- rank()排名【注意】在over()函數中指定partition by子句。當然也可以使用其它的窗口函數,如rank實現排名。7.DTL語句
1.DTL語句的基本概念:DTL主要是對事務進行操作的語句。7.1開啟事務
begin;7.2回滾事務
callback;7.3提交事務
commit;8.常用函數
8.1時間函數
8.2字符函數
8.3數值函數
1.常用的數值函數:- abs(n): 絕對值- round(n): 四舍五入- ceil(n): 上行取整- floor(n): 下行取整- sin(n)- cos(n)- tan(n)- atan(n)- asin(n)- acos(n):- sqrt(n): 開平方根- power(n, m): n的m次方/冪8.4聚合函數
1.常用的聚合函數:- min()- max()- sum()- avg()- count()8.5加密函數
1.常用的加密函數- 不可逆的有:sha1(s): sha1 簽名信息, 40位。sha2(s, 0|224|256|384|512): 比sha1更強大的數據加密算法md5(s): md5簽名信息,32位。可逆的有:aes_encrypt(str, key): 使用key密鑰對str進行AES加密(對稱加密-可逆的)aes_decrypt(encrypt_str, key): 使用key密鑰進encrypt_str密文解密。9.索引
mysql索引是一種數據結構(btree, hash),在DQL語句的where條件中使用索引字段,則先從索引中查詢,達到加速查詢效果。 【重點】一張表中的索引個數,原則上沒有限制,但索引不能過量創建,否則會影響DML語句的性能。 視圖是一種高級子查詢,即將查詢語句存儲,以便之后使用。視圖同表一樣,存在創建、修改和查詢。9.1創建索引
方式一:create [ unique|fulltext|spatial ] index <索引名> [ using <index_type> ] on <表名>(<字段名> [ (length)] [ ASC | DESC ])舉例:create index pay_time_index using btree on tb_table(order_pay_time,DESC);方式二:在創建表的時候創建索引舉例:drop table if exists tb_cate;create table if not exists tb_cate(id integer primary key auto_increment,name varchar(20),ord int,constraint unique index name_uniq using btree (name) );方式三:在修改表的時候創建索引舉例:alter table tb_cate add fulltext index cate_name_index (name);9.2查看索引
查看索引我們常用的方法是通過索引視圖來查看9.3刪除索引
alter table 表名 drop index 索引名 【注意】刪除普通索引都好刪除,在刪除外鍵索引時,先要解除外鍵約束,才能刪除。同理,刪除主鍵索引時,先要解除主鍵約束,才能刪除。10.視圖
視圖用于緩存復雜的sql語句, 查詢的用法同表。 視圖本質上是一張虛擬的表。10.1創建視圖
create view as select子句 舉例: create or replace view account_top10 as select * from account where money >= 1000000;10.2刪除視圖
drop view [if exists] <視圖名>;11.函數
11.1創建函數
create [definer=user[@host] ] function <函數名> ( [IN |OUT|INOUT] <參數名> <參數類型>, ...) returns <函數返回數據的類型> [comment 注釋] [deterministic] <函數的功能>; 舉例: create function pct_format(val float) returns varchar(10) deterministic return concat(round(val * 100), '%');11.2使用函數
select c.cid,c.name,max(score) max_score,min(score) min_score,round(avg(score),2) avg_score,pct_format(sum(s1)/count(1)) as '及格率',pct_format(sum(s2)/count(1)) as '中等率',pct_format(sum(s3)/count(1)) as '優良率',pct_format(sum(s4)/count(1)) as '優秀率' from (select cid,score,if(score >= 60, 1, 0) as s1,if(score >=70 and score <80,1, 0) as s2,if(score >=80 and score <90, 1, 0 ) as s3,if(score >=90,1, 0) as s4from SC ) A natural join Course c group by c.cid,c.name;11.3刪除函數
drop function [if exists] <函數名>;12.存儲過程
1.存儲過程概念:存儲過程可以實現比較復雜業務邏輯的SQL語句,SQL語句可以是DML或DQL語句。12.1創建存儲過程
CREATE [DEFINER = user] procedure <存儲過程名> ([proc_parameter[,...]]) [characteristic ...] begin<存儲過程體> end;舉例: delimiter && create procedure stu_total_level (sid varchar(50), out sum_score float, out level varchar(10)) beginselect sum(score) ,case when sum(score)>=240 then '優'when sum(score)>=200 then '良'when sum(score)>=180 then '及格'else '不及格' end into sum_score, levelfrom SCgroup by sid; end && delimiter ;【注意】delimiter是SQL語句的結束符12.2調用存儲過程
使用call調用存儲過程,如果存儲過程需要變量輸出,則直接使用@變量名聲明 舉例: -mysql> call stu_total_level('01', @score, @level); -mysql> select @score, @level;12.3刪除存儲過程
drop procedure if exists <存儲過程名>;13.觸發器
1.觸發器基本概念trigger存儲器是基于行級事件,監測發生或改變的數據。 如,刪除用戶信息時,在刪除之前可以將數據存儲到日志文件中(備份)。13.1創建觸發器
CREATEtrigger 觸發器名稱trigger_time trigger_eventON tbl_name FOR EACH ROW[trigger_order]trigger_body{begin;操作end;}trigger_time: { BEFORE | AFTER } trigger_event: { INSERT | UPDATE | DELETE } trigger_order: { FOLLOWS | PRECEDES } other_trigger_name13.2刪除觸發器
drop trigger 觸發器名稱14.數據庫用戶
1.數據庫用戶概念:數據庫的管理用戶信息存儲在mysql.user表中。一般用戶信息包含user用戶名、host主機、authentication_string 口令等。14.1創建用戶
create user <user>@<host> identified [with mysql_native_password] by <口令> [password expire [default | never | interval N day] ] [account lock|unlock]舉例: create user 'disen'@'%' identified with mysql_native_password by 'disen';14.2修改用戶
alter user [if exists] <user>@<host> identified [with mysql_native_password] by <口令> [password expire [default | never | interval N day] ] [account lock|unlock]- 鎖定用戶:alter user 'disen'@'%' account lock; - 修改并解鎖用戶:alter user 'disen'@'%' identified with mysql_native_password by 'disen123' account unlock;14.3刪除用戶
drop user [if exists] <user>@<host> 舉例:drop user 'disen'@'%';15.權限
mysql中存在非常多的權限,以便于為不同的管理員提供不同的權限操作15.1管理員權限
1.常見權限等級命令- ALL 具有所有權限- CREATE TABLESPACE 創建表空間- CREATE USER 創建用戶- FILE 輸出文件和加載文件- PROCESS 訪問線程信息的權限- RELOAD 重載權限,如具有flush相關的功能(flush-privileges、flush-status)- REPLICATION CLIENT 客戶端備份權限- REPLICATION SLAVE 主從備份權限- SHOW DATABASES 顯示數據庫信息的權限- SHOW VIEW 顯示視圖的權限- SHUTDOWN 關閉或重啟服務的權限,針對mysqladmin shutdown|restart命令。- SUPER 具有超級用戶權限,如設置全局變量等- TRIGGER 具有觸發器相關權限- UPDATE 具有更新表記錄的權限- SELECT 具有查詢表的權限- INSERT 具有插入表權限- INDEX 具有索引相關的管理權限- DELETE 具有刪除表記錄的權限- CREATE View 具有創建視圖的權限- CREATE 具有創建數據庫和表的權限- DROP 具有刪除對象的權限ALTER 具有修改對象的權限15.2授權
grant <權限> on <數據庫>[.<對象>] to <用戶名>@<主機> 舉例:grant select,update on studb.Student to 'disen'@'%';grant select,update on studb.Teacher to disen;15.3查看權限
show grants; show grants for <user>@<host> ; show grants current_user();15.4撤銷權限
REVOKEpriv_type [(column_list)][, priv_type [(column_list)]] ...ON [object_type] priv_levelFROM user_or_role [, user_or_role] ...舉例: revoke drop on studb.A from disen;16.SQL優化
-1.通過show status命令了解各種SQL的執行頻率 -2.定位執行效率較低的SQL語句 -3.通過EXPLAIN分析較低SQL的執行計劃 -4.通過show profile分析SQL -5.通過trace分析優化器如何選擇執行計劃 -6.確定問題并采取相應的優化措施六、Python與MySQL的交互【連接橋梁】
1.pymysql的curl操作
2.封裝DB類
3.基于type元類設計ORM
4.sqlalchemy的應用
七、FASTAPI面試題
八、html+css+javascript面試題
九、Django面試題
十、VUE面試題
十一、爬蟲面試題
十二、Redis面試題
1.Redis和MySQL的區別
1.mysql是關系型數據庫,而redis是NOSQL,非關系型數據庫。mysql將數據持久化到硬盤,讀取數據慢,而redis數據先存儲在緩存中,讀取速度快,但是保存時間有限,最后按需要可以選擇持久化到硬盤。 2.mysql作為持久化數據庫,每次訪問都要在硬盤上進行I/O操作。頻繁訪問數據庫會在反復連接數據庫上花費大量時間。redis則會在緩存區存儲大量頻繁訪問的數據,當瀏覽器訪問數據的時候,先訪問緩存,如果訪問不到再進入數據庫.2.Redis的五大數據類型
1.字符串類型 String 添加操作:set 2.哈希對象 hash 添加操作: hset 3.列表對象 list 添加操作: lpush 4.集合對象 set 添加操作:sadd 5.有序集合對象 sorted set 添加操作: zadd3.Redis如何解決key沖突?
拉鏈法。這個問題可以考慮到另一個問題,HashMap是如何解決key沖突的,同樣也是采用拉鏈地址法。如果被問到解決key值沖突還有什么方法?一般來說解決key值沖突的方法有倆種,一種是開放地址法,另一種就是拉鏈法。4.Redis的存儲機制和持久化方案?
背景:首先要明白什么是持久化?上面第一個問題已經闡述過了,簡單來說,類似于MySQL這種直接將數據存到硬盤的方式就是持久化。但是Redis又不能照搬照抄SQL的存儲方法,最大的原因也是講過的——NoSQL,也就意味著沒有類似于B+樹的操作。 方法一:RDB持久化策略。也是redis的默認方法。先將數據存儲到內存,當數據累計到某種設定的閾值后會觸發一次DUMP 操作,將變化的數據存進RDB文件。一旦 Redis 異常退出,就會丟失最后一次快照以后更改的所有數據方式二:開啟AOF持久化策略 先將數據存儲到內存。開啟 AOF 持久化后每執行一條會更改 Redis 中的數據的命令,Redis 就會將該命令寫入硬盤中的 AOF 文件.AOF文件不存儲數據,儲存的是執行的命令。 AOF最關鍵的配置就是關于調用fsync追加日志文件的頻率,有兩種預設頻率,always每次記錄進來都添加,everysecond 每秒添加一次。(fsync函數的作用就是將數據從內存寫入硬盤)。 由于AOF和RDB存儲的文件內容并不相同,RDB存儲的是真實的,存進去的數據,AOF存儲的是大量操作數據的指令,這種指令一旦增多,就會必然使得AOF文件擴大,所以會引發一種新的機制:Rewrite。所謂Rewrite就是將日志文件中的所有數據都重新寫到另外一個新的日志文件中,但是不同的是,對于老日志文件中對于Key的多次操作,只保留最終的值的那次操作記錄到日志文件中,從而縮小日志文件的大小。5.redis過期策略
如何設置redis的過期時間?最簡單的就是使用expire key second,當然還有各種其他方式,比如pexpire key milliseconds等等,redis查看過期時間的語法也很簡單,ttl key就可以看到還剩多長時間。 redis內置的策略叫做惰性刪除,也叫“被動刪除”。 原理:key過期的時候不刪除,每次從數據庫獲取key的時候去檢查是否過期,若過期,則刪除,返回null。這個方法是可取的,但是必然存在另外一個問題,使用的時候判斷是否過期再刪除,萬一我不使用呢?若大量的key在超出超時時間后,很久一段時間內,都沒有被獲取過,那么可能發生內存泄露6.Redis的集群策略?
redis的集群有多個,但是性能最強大的是官方的redis-cluster。 1.使用去中心化化思想, 使用hash slot方式 將16348個hash slot 覆蓋到所有節點上 對于存儲的每個key值 使用CRC16(KEY)&16348=slot 得到他對應的hash slot 并在訪問key時就去找他的hash slot在哪一個節點上 然后由當前訪問節點從實際被分配了這個hash slot的節點去取數據。 2.投票容錯。通過投票容錯機制判斷節點是否還在工作中。Redis集群中每個節點都會按時向其他節點發送”心跳包”。當有一個節點不響應時,則判斷該節點故障。要求是超過半數的投票不響應。 3.為了解決節點master失效fail的問題,可以使用主從復制策略。7.Redis是單線程的嗎?
redis是單線程的! redis 核心就是 如果我的數據全都在內存里,我單線程的去操作 就是效率最高的,為什么呢,因為多線程的本質就是 CPU 模擬出來多個線程的情況,這種模擬出來的情況就有一個代價,就是上下文的切換,對于一個內存的系統來說,它沒有上下文的切換就是效率最高的。redis 用 單個CPU 綁定一塊內存的數據,然后針對這塊內存的數據進行多次讀寫的時候,都是在一個CPU上完成的,所以它是單線程處理這個事。在內存的情況下,這個方案就是最佳方案。 什么時候用多線程的方案呢? 答案是:下層的存儲等慢速的情況。比如磁盤8.redis的常用命令
8.1key相關的命令
- keys * 查看所有的key - select n 選擇某一個數據庫,n可以是0~15, 默認的數據庫是0號庫, 默認是16個數據庫 - del key [key ...] 刪除key - expire key seconds 設置key的過期時間 - flushdb 清空當前的庫的key - flushall 清空所有庫的key - exit 退出redis交互環境8.2string相關命令
- set name disen [EX seconds] 添加name的值為disen ,可指定過期時間(秒) - get name 獲取name的value值8.3 list類型的命令
- hset key field value 賦值舉例:hset user username ljj - hget key field 取值舉例:hget user username - hget key 獲取所有字段值舉例:hget user - hdel key field 刪除字段舉例:hdel user username - hincrby key field increment 增加數字舉例:hincrby user age 2 - hexists key field 判斷字段是否存在舉例:hexists user username8.4 hash類型的命令
- lpush key value [value…] 向列表左邊添加元素舉例:lpush list:1 1 2 3 - rpush key value [value…] 向列表右邊添加元素舉例:rpush list:1 4 5 6 - lrange key start stop 查看start到stop之間的元素舉例:lrange list:1 0 2 - lpop key rpop key 移除列表左邊的元素并返回舉例: lpop list:1 - llen key 獲取列表中所有元素舉例:llen list:1 - lrem key count value 刪除列表指定元素舉例:lrem list:1 0 4 - lindex key index 獲取指定索引元素值舉例:lindex list:1 2 - lset key index value 設置指定索引的元素值舉例:lset list:1 2 2 - ltrim key start stop 只保留start,stop中間的元素值舉例:ltrim list:1 0 2 - linsert key before | after pivot value 向列表中插入元素 - rpoplpush source destination 將元素從一個列表移動到另一個列表中去8.5 set類型的命令
- sadd key member [member…] 增加元素 - srem key member [member…] 刪除元素 - smembers key 獲取集合中所有元素 - sismember key member 判斷元素是否在集合中 - sdiff key [key…] 集合的差集運算 - sinter key [key…] 集合的交集運算 - sunion key [key…] 集合的并集運算 - scard key 獲取集合中元素的個數 - spop key 從集合中彈出一個元素(隨機彈出)8.6 zset類型的命令
1.zset基本概念:SortedSet 又叫 zset,SortedSet 是有序集合,可排序的,但是唯一。 SortedSet 和 Set 的不同之處,會給 Set 中元素添加一個分數,然后通過這個分數進行排序。 - zadd key score member [score member…] 增加元素 - zscore key member 獲取元素分數 - zrem key member [member…] 刪除元素 - zrange key start stop [withscores] 獲得排名在某個范圍的元素列表 - zrevrange key start stop [withscores] 按照元素分數從大到小的順序返回索引從start到stop之間的所有元素 - zrank key member 從小到大獲取元素排名 - zrevrank key member 從大到小獲取元素排名 - zrangebyscore key min max [withscores][limit offset count] 獲取指定分數范圍的元素 - zincrby key increment member 增加某個元素的分數,返回結果值 - zcard key 獲得集合中元素的數量 - zcount key min max 獲得指定分數范圍內元素的個數 - zremrangebyrank key start stop 按照排名范圍刪除元素十三、Git操作面試題
1.git常用命令有哪些?
git branch 查看本地所有分支 git status 查看當前狀態 git commit 提交 git branch -a 查看所有的分支 git branch -r 查看遠程所有分支 git commit -am "init" 提交并且加注釋 git remote add origin git@192.168.1.119:ndshow git push origin master 將文件給推到服務器上 git remote show origin 顯示遠程庫origin里的資源 git push origin master:develop git push origin master:hb-dev 將本地庫與服務器上的庫進行關聯 git checkout --track origin/dev 切換到遠程dev分支 git branch -D master develop 刪除本地庫develop git checkout -b dev 建立一個新的本地分支dev git merge origin/dev 將分支dev與當前分支進行合并 git checkout dev 切換到本地dev分支 git remote show 查看遠程庫 git add . git rm 文件名(包括路徑) 從git中刪除指定文件 git clone git://github.com/schacon/grit.git 從服務器上將代碼給拉下來 git config --list 看所有用戶 git ls-files 看已經被提交的 git rm [file name] 刪除一個文件 git commit -a 提交當前repos的所有的改變 git add [file name] 添加一個文件到git index git commit -v 當你用-v參數的時候可以看commit的差異 git commit -m "This is the message describing the commit" 添加commit信息 git commit -a -a是代表add,把所有的change加到git index里然后再commit git commit -a -v 一般提交命令 git log 看你commit的日志 git diff 查看尚未暫存的更新 git rm a.a 移除文件(從暫存區和工作區中刪除) git rm --cached a.a 移除文件(只從暫存區中刪除) git commit -m "remove" 移除文件(從Git中刪除) git rm -f a.a 強行移除修改后文件(從暫存區和工作區中刪除) git diff --cached 或 $ git diff --staged 查看尚未提交的更新 git stash push 將文件給push到一個臨時空間中 git stash pop 將文件從臨時空間pop下來 --------------------------------------------------------- git remote add origin git@github.com:username/Hello-World.git git push origin master 將本地項目給提交到服務器中 ----------------------------------------------------------- git pull 本地與服務器端同步 ----------------------------------------------------------------- git push (遠程倉庫名) (分支名) 將本地分支推送到服務器上去。 git push origin serverfix:awesomebranch ------------------------------------------------------------------ git fetch 相當于是從遠程獲取最新版本到本地,不會自動merge git commit -a -m "log_message" (-a是提交所有改動,-m是加入log信息) 本地修改同步至服務器端 : git branch branch_0.1 master 從主分支master創建branch_0.1分支 git branch -m branch_0.1 branch_1.0 將branch_0.1重命名為branch_1.0 git checkout branch_1.0/master 切換到branch_1.0/master分支 du -hsgit branch 刪除遠程branch git push origin :branch_remote_name git branch -r -d branch_remote_name -----------------------------------------------------------初始化版本庫,并提交到遠程服務器端 mkdir WebApp cd WebApp git init 本地初始化 touch README git add README 添加文件 git commit -m 'first commit' git remote add origin git@github.com:daixu/WebApp.git 增加一個遠程服務器端2.提交是發生沖突,你能解釋沖突是如何產生的嗎?你是如何解決的?
我們在開發過程中,都有自己的分支,基本不會發生提交沖突。但如果是諸如公共類的公共方法,我和別人同時修改同一個文件,他提交后我再提交就會報沖突的錯誤。 發生沖突,在IDE里面一般都是對比本地文件和遠程分支的文件,然后把遠程分支上文件的內容手工修改到本地文件,然后再提交沖突的文件使其保證與遠程分支的文件一致,這樣才會消除沖突,然后再提交自己修改的部分。特別要注意下,修改本地沖突文件使其與遠程倉庫的文件保持一致后,需要提交后才能消除沖突,否則無法繼續提交。必要時可與同事交流,消除沖突。 發生沖突,也可以使用命令。- 通過git stash命令,把工作區的修改提交到棧區,目的是保存工作區的修改; - 通過git pull命令,拉取遠程分支上的代碼并合并到本地分支,目的是消除沖突; - 通過git stash pop命令,把保存在棧區的修改部分合并到最新的工作空間中;3.如果本次提交失誤操作,如何撤銷?
如果想撤銷提交到索引區的文件,可以通過git reset HEAD file;如果想撤銷提交到本地倉庫的文件,可以通過git reset –soft HEAD^n恢復當前分支的版本庫至上一次提交的狀態,索引區和工作空間不變更;可以通過git reset –mixed HEAD^n恢復當前分支的版本庫和索引區至上一次提交的狀態,工作區不變更;可以通過git reset –hard HEAD^n恢復當前分支的版本庫、索引區和工作空間至上一次提交的狀態。4.如果我想修改提交的歷史信息,應該用什么命令?
如果修改最近一次提交的歷史記錄,就可以用git commit –amend命令;vim編輯的方式; 如果修改之前提交的歷史記錄,就需要按照下面的步驟: 第一步:- git logs -3 首先查看前三次的提交歷史記錄; 第二步:- git rebase –i HEAD~3,會把前3次的提交記錄按照倒敘列出來;- 這里把第一行的‘pick’修改為‘edit’,然后esc + :wq退出vim編輯器; 第三步:- git commit –amend 進入vim編輯器并修改提交信息。 第四步:- git rebase –continue 第五步:- 查看修改結果,修改成功5.你使用過git stash命令嗎?你一般什么情況下會使用它?
命令git stash是把工作區修改的內容存儲在棧區。 以下幾種情況會使用到它: - 解決沖突文件時,會先執行git stash,然后解決沖突; - 遇到緊急開發任務但目前任務不能提交時,會先執行git stash,然后進行緊急任務的開發,然后通過git stash pop取出棧區的內容繼續開發; - 切換分支時,當前工作空間內容不能提交時,會先執行git stash再進行分支切換;6.如何查看分支提交的歷史記錄?查看某個文件的歷史記錄呢?
- 查看分支的提交歷史記錄:- git log –number:表示查看當前分支前number個詳細的提交歷史記錄;- git log –number –pretty=oneline:在上個命令的基礎上進行簡化,只顯示sha-1碼和提交信息;- git reflog –number: 表示查看所有分支前number個簡化的提交歷史記錄;- git reflog –number –pretty=oneline:顯示簡化的信息歷史信息;- 查看文件的歷史記錄:如果要查看某文件的提交歷史記錄,直接在上面命令后面加上文件名即可。注意:如果沒有number則顯示全部提交次數。7.能不能說一下git fetch和git pull之間的區別?
簡單來說:git fetch branch是把名為branch的遠程分支拉取到本地;而git pull branch是在fetch的基礎上,把branch分支與當前分支進行merge;因此pull = fetch + merge。8.使用過git merge和git rebase嗎?他們之間有什么區別?
簡單的說,git merge和git rebase都是合并分支的命令。 git merge branch會把branch分支的差異內容pull到本地,然后與本地分支的內容一并形成一個committer對象提交到主分支上,合并后的分支與主分支一致; git rebase branch會把branch分支優先合并到主分支,然后把本地分支的commit放到主分支后面,合并后的分支就好像從合并后主分支又拉了一個分支一樣,本地分支本身不會保留提交歷史。9.能說一下git系統中HEAD、工作樹和索引之間的區別嗎?
- HEAD文件包含當前分支的引用(指針); - 工作樹是把當前分支檢出到工作空間后形成的目錄樹,一般的開發工作都會基于工作樹進行;索引index文件是對工作樹進行代碼修改后,通過add命令更新索引文件;GIT系統通過索引index文件生成tree對象;10.之前項目中是使用的GitFlow工作流程嗎?它有什么好處?
GitFlow可以用來管理分支。GitFlow工作流中常用的分支有下面幾類:10.1master分支
最為穩定功能比較完整的隨時可發布的代碼,即代碼開發完成,經過測試,沒有明顯的bug,才能合并到 master 中。請注意永遠不要在 master 分支上直接開發和提交代碼,以確保 master 上的代碼一直可用;10.2develop分支
用作平時開發的主分支,并一直存在,永遠是功能最新最全的分支,包含所有要發布 到下一個 release 的代碼,主要用于合并其他分支,比如 feature 分支; 如果修改代碼,新建 feature 分支修改完再合并到 develop 分支。所有的 feature、release 分支都是從 develop 分支上拉的。10.3feature分支
這個分支主要是用來開發新的功能,一旦開發完成,通過測試沒問題(這個測試,測試新功能沒問題),我們合并回develop 分支進入下一個 release10.4release分支
用于發布準備的專門分支。當開發進行到一定程度,或者說快到了既定的發布日,可以發布時,建立一個 release 分支并指定版本號(可以在 finish 的時候添加)。開發人員可以對 release 分支上的代碼進行集中測試和修改bug。(這個測試,測試新功能與已有的功能是否有沖突,兼容性)全部完成經過測試沒有問題后,將 release 分支上的代碼合并到 master 分支和 develop 分支10.5hotfix 分支
用于修復線上代碼的bug。**從 master 分支上拉。**完成 hotfix 后,打上 tag 我們合并回 master 和 develop 分支。10.6GitFlow主要工作流程
1.初始化項目為gitflow , 默認創建master分支 , 然后從master拉取第一個develop分支 2.從develop拉取feature分支進行編碼開發(多個開發人員拉取多個feature同時進行并行開發 , 互不影響) 3.feature分支完成后 , 合并到develop(不推送 , feature功能完成還未提測 , 推送后會影響其他功能分支的開發);合并feature到develop , 可以選擇刪除當前feature , 也可以不刪除。但當前feature就不可更改了,必須從release分支繼續編碼修改 4.從develop拉取release分支進行提測 , 提測過程中在release分支上修改BUG 5.release分支上線后 , 合并release分支到develop/master并推送;合并之后,可選刪除當前release分支,若不刪除,則當前release不可修改。線上有問題也必須從master拉取hotfix分支進行修改; 6.上線之后若發現線上BUG , 從master拉取hotfix進行BUG修改; 7.hotfix通過測試上線后,合并hotfix分支到develop/master并推送;合并之后,可選刪除當前hotfix ,若不刪除,則當前hotfix不可修改,若補丁未修復,需要從master拉取新的hotfix繼續修改; 8.當進行一個feature時 , 若develop分支有變動 , 如其他開發人員完成功能并上線 , 則需要將完成的功能合并到自己分支上,即合并develop到當前feature分支; 9.當進行一個release分支時 , 若develop分支有變動 , 如其他開發人員完成功能并上線 , 則需要將完成的功能合并到自己分支上,即合并develop到當前release分支 (!!! 因為當前release分支通過測試后會發布到線上 , 如果不合并最新的develop分支 , 就會發生丟代碼的情況);GitFlow的好處:為不同的分支分配一個明確的角色,并定義分支之間如何交互以及什么時間交互;可以幫助大型項目理清分支之間的關系,簡化分支的復雜度。11.使用過git cherry-pick,有什么作用?
命令git cherry-pick可以把branch A的commit復制到branch B上。 在branch B上進行命令操作:- 復制單個提交:git cherry-pick commitId- 復制多個提交:git cherry-pick commitId1…commitId3注意:復制多個提交的命令不包含commitId1.12.git跟其他版本控制器有啥區別?
GIT是分布式版本控制系統,其他類似于SVN是集中式版本控制系統。 分布式區別于集中式在于:每個節點的地位都是平等,擁有自己的版本庫,在沒有網絡的情況下,對工作空間內代碼的修改可以提交到本地倉庫,此時的本地倉庫相當于集中式的遠程倉庫,可以基于本地倉庫進行提交、撤銷等常規操作,從而方便日常開發。13.如何把本地倉庫的內容推向一個空的遠程倉庫?
- git remote add origin XXXX - git push -u origin master - git push origin master14.常用命令補充
1.生成密鑰:ssh-keygen 2.git init在當前目錄下創建一個本地倉庫 3.git push -u origin master15.git分支操作,問什么要做git分支
十五、項目闡述
1.二手交易平臺
2.自動化測試平臺
簡單的說,git merge和git rebase都是合并分支的命令。
git merge branch會把branch分支的差異內容pull到本地,然后與本地分支的內容一并形成一個committer對象提交到主分支上,合并后的分支與主分支一致;
git rebase branch會把branch分支優先合并到主分支,然后把本地分支的commit放到主分支后面,合并后的分支就好像從合并后主分支又拉了一個分支一樣,本地分支本身不會保留提交歷史。
9.能說一下git系統中HEAD、工作樹和索引之間的區別嗎?
- HEAD文件包含當前分支的引用(指針); - 工作樹是把當前分支檢出到工作空間后形成的目錄樹,一般的開發工作都會基于工作樹進行;索引index文件是對工作樹進行代碼修改后,通過add命令更新索引文件;GIT系統通過索引index文件生成tree對象;10.之前項目中是使用的GitFlow工作流程嗎?它有什么好處?
GitFlow可以用來管理分支。GitFlow工作流中常用的分支有下面幾類:10.1master分支
最為穩定功能比較完整的隨時可發布的代碼,即代碼開發完成,經過測試,沒有明顯的bug,才能合并到 master 中。請注意永遠不要在 master 分支上直接開發和提交代碼,以確保 master 上的代碼一直可用;10.2develop分支
用作平時開發的主分支,并一直存在,永遠是功能最新最全的分支,包含所有要發布 到下一個 release 的代碼,主要用于合并其他分支,比如 feature 分支; 如果修改代碼,新建 feature 分支修改完再合并到 develop 分支。所有的 feature、release 分支都是從 develop 分支上拉的。10.3feature分支
這個分支主要是用來開發新的功能,一旦開發完成,通過測試沒問題(這個測試,測試新功能沒問題),我們合并回develop 分支進入下一個 release10.4release分支
用于發布準備的專門分支。當開發進行到一定程度,或者說快到了既定的發布日,可以發布時,建立一個 release 分支并指定版本號(可以在 finish 的時候添加)。開發人員可以對 release 分支上的代碼進行集中測試和修改bug。(這個測試,測試新功能與已有的功能是否有沖突,兼容性)全部完成經過測試沒有問題后,將 release 分支上的代碼合并到 master 分支和 develop 分支10.5hotfix 分支
用于修復線上代碼的bug。**從 master 分支上拉。**完成 hotfix 后,打上 tag 我們合并回 master 和 develop 分支。10.6GitFlow主要工作流程
1.初始化項目為gitflow , 默認創建master分支 , 然后從master拉取第一個develop分支 2.從develop拉取feature分支進行編碼開發(多個開發人員拉取多個feature同時進行并行開發 , 互不影響) 3.feature分支完成后 , 合并到develop(不推送 , feature功能完成還未提測 , 推送后會影響其他功能分支的開發);合并feature到develop , 可以選擇刪除當前feature , 也可以不刪除。但當前feature就不可更改了,必須從release分支繼續編碼修改 4.從develop拉取release分支進行提測 , 提測過程中在release分支上修改BUG 5.release分支上線后 , 合并release分支到develop/master并推送;合并之后,可選刪除當前release分支,若不刪除,則當前release不可修改。線上有問題也必須從master拉取hotfix分支進行修改; 6.上線之后若發現線上BUG , 從master拉取hotfix進行BUG修改; 7.hotfix通過測試上線后,合并hotfix分支到develop/master并推送;合并之后,可選刪除當前hotfix ,若不刪除,則當前hotfix不可修改,若補丁未修復,需要從master拉取新的hotfix繼續修改; 8.當進行一個feature時 , 若develop分支有變動 , 如其他開發人員完成功能并上線 , 則需要將完成的功能合并到自己分支上,即合并develop到當前feature分支; 9.當進行一個release分支時 , 若develop分支有變動 , 如其他開發人員完成功能并上線 , 則需要將完成的功能合并到自己分支上,即合并develop到當前release分支 (!!! 因為當前release分支通過測試后會發布到線上 , 如果不合并最新的develop分支 , 就會發生丟代碼的情況);GitFlow的好處:為不同的分支分配一個明確的角色,并定義分支之間如何交互以及什么時間交互;可以幫助大型項目理清分支之間的關系,簡化分支的復雜度。11.使用過git cherry-pick,有什么作用?
命令git cherry-pick可以把branch A的commit復制到branch B上。 在branch B上進行命令操作:- 復制單個提交:git cherry-pick commitId- 復制多個提交:git cherry-pick commitId1…commitId3注意:復制多個提交的命令不包含commitId1.12.git跟其他版本控制器有啥區別?
GIT是分布式版本控制系統,其他類似于SVN是集中式版本控制系統。 分布式區別于集中式在于:每個節點的地位都是平等,擁有自己的版本庫,在沒有網絡的情況下,對工作空間內代碼的修改可以提交到本地倉庫,此時的本地倉庫相當于集中式的遠程倉庫,可以基于本地倉庫進行提交、撤銷等常規操作,從而方便日常開發。13.如何把本地倉庫的內容推向一個空的遠程倉庫?
- git remote add origin XXXX - git push -u origin master - git push origin master14.常用命令補充
1.生成密鑰:ssh-keygen 2.git init在當前目錄下創建一個本地倉庫 3.git push -u origin master15.git分支操作,問什么要做git分支
十五、項目闡述
1.二手交易平臺
2.自動化測試平臺
3.高校團委學生會管理系統
總結
以上是生活随笔為你收集整理的python面试题大全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5G比4G到底有啥好处?看完就彻底明白了
- 下一篇: 能恢复手机短信数据恢复软件下载