精心整理170道Python面試題,建議先收藏

2022-05-20     CDA數據分析師

原標題:精心整理170道Python面試題,建議先收藏

作者:周蘿蔔

來源:蘿蔔大雜燴

精心整理的 Python 相關的基礎知識,用於面試,或者平時複習,都是很好的!廢話不多說,直接開搞

由於文章過長,蘿蔔哥也貼心的把文章整理成了PDF文檔,在文末查看獲取方式

  • 基礎篇
    • 1. 為什麼學習 Python
    • 2. 解釋型和編譯型語言的區別
    • 3. 簡述下 Python 中的字符串、列表、元組和字典
    • 4. 簡述上述數據類型的常用方法
    • 5. 簡述 Python 中的字符串編碼
    • 6.一行代碼實現數值交換
    • 7. is 和 == 的區別
    • 8.Python 函數中的參數類型
    • 9.`*arg` 和 `**kwarg` 作用
    • 10.一行代碼實現1-100之和
    • 11.獲取當前時間
    • 12.PEP8 規範
    • 13.Python 的深淺拷貝
    • 14.查看下面代碼的輸出
    • 15.可變類型與不可變類型
    • 16.列印九九乘法表
    • 17.filter、map、reduce 的作用
    • 18.re 的 match 和 search 區別
    • 19.面向對象中`__new__` 和 `__init__` 區別
    • 20.三元運算規則
    • 21.生成隨機數
    • 22.zip 函數用法
    • 23.range 和 xrange 的區別
    • 24.with 方法打開文件的作用
    • 25.什麼是正則的貪婪匹配
    • 26.為什麼不建議函數的默認參數傳入可變對象
    • 27.字符串轉列表
    • 28.字符串轉整數
    • 29.刪除列表中的重複值
    • 30.字符串單詞統計
    • 31.列表推導,求奇偶數
    • 32.一行代碼展開列表
    • 33.實現二分法查找函數
    • 34.字典和 json 轉換
    • 35.列表推導式、字典推導式和生成器
    • 36.簡述 read、readline、readlines 的區別
    • 37.打亂一個列表
    • 38.反轉字符串
    • 39.單下劃線和雙下劃線的作用
    • 40.新式類和舊式類
    • 41.Python 面向對象中的繼承有什麼特點
    • 42.super 函數的作用
    • 43.類中的各種函數
    • 44.如何判斷是函數還是方法
    • 45.isinstance 的作用以及與 type的區別
    • 46.單例模式與工廠模式
    • 47.查看目錄下的所有文件
    • 48.計算1到5組成的互不重複的三位數
    • 49.去除字符串首尾空格
    • 50.去除字符串中間的空格
    • 51. 字符串格式化方式
    • 52. 將"hello world"轉換為首字母大寫"Hello World"(不使用 title 函數)
    • 53. 一行代碼轉換列表中的整數為字符串
    • 54. 合併兩個元組到字典
    • 55. 給出如下代碼的輸入,並簡單解釋
    • 56. Python 中的反射
    • 57. 實現一個簡單的 API
    • 58. metaclass 元類
    • 59. sort 和 sorted 的區別
    • 60. Python 中的 GIL
    • 61. 產生8位隨機密碼
    • 62. 輸出原始字符
    • 63. 列表內,字典按照 value 大小排序
    • 64. 簡述 any 和 all 方法
    • 65. 反轉整數
    • 66. 函數式編程
    • 67. 簡述閉包
    • 68. 簡述裝飾器
    • 69. 協程的優點
    • 70. 實現一個斐波那契數列
    • 71. 正則切分字符串
    • 72. yield 用法
    • 73. 冒泡排序
    • 74. 快速排序
    • 75. requests 簡介
    • 76. 比較兩個 json 數據是否相等
    • 77. 讀取鍵盤輸入
    • 78. enumerate
    • 79. pass 語句
    • 80. 正則匹配郵箱
    • 81. 統計字符串中大寫字母的數量
    • 82. json 序列化時保留中文
    • 83. 簡述繼承
    • 84. 什麼是猴子補丁
    • 85. help 函數和 dir 函數
    • 86. 解釋 Python 中的`//`,`%`和`**`運算符
    • 87. 主動拋出異常
    • 88. tuple 和 list 轉換
    • 89. 簡述斷言
    • 90. 什麼是異步非阻塞
    • 91. 什麼是負索引
    • 92. 退出 Python 後,內存是否全部釋放
    • 93. Flask 和 Django 的異同
    • 94. 創建刪除作業系統上的文件
    • 95. 簡述 logging 模塊
    • 96. 統計字符串中單詞出現次數
    • 97. 正則 re.complie 的作用
    • 98. try except else finally 的意義
    • 99.反轉列表
    • 100. 字符串中數字替換
  • 綜合篇:網絡編程
    • 101. 簡述 OSI 七層協議
    • 102. 三次握手、四次揮手的流程
    • 103. 什麼是 C/S 和 B/S 架構
    • 104. TCP 和 UDP 的區別
    • 105. 區域網和廣域網
    • 106. arp 協議
    • 107. 什麼是 socket?簡述基於 TCP 協議的套接字通信流程
    • 108. 簡述 進程、線程、協程的區別以及應用場景
    • 109. 如何使用線程池和進程池
    • 110. 進程之間如何進行通信
    • 111. 進程鎖和線程鎖
    • 112. 什麼是並發和並行
    • 113. threading.local 的作用
    • 114. 什麼是域名解析
    • 115. LVS 是什麼及作用
    • 116. Nginx 的作用
    • 117. keepalived 及 HAProxy
    • 118. 什麼是 rpc
    • 119. 從瀏覽器輸入一個網址到展示網址頁面的過程
    • 120. 什麼是cdn
  • 綜合篇:資料庫和框架
    • 121. 列舉常見的資料庫
    • 122. 資料庫設計三大範式
    • 123. 什麼是資料庫事務
    • 124. MySQL 索引種類
    • 125. 資料庫設計中一對多和多對多的應用場景
    • 126. 簡述觸發器、函數、視圖、存儲過程
    • 127. 常用 SQL 語句
    • 128. 主鍵和外鍵的區別
    • 129. 如何開啟 MySQL 慢日誌查詢
    • 130. MySQL 資料庫備份命令
    • 131. char 和 varchar 的區別
    • 132. 最左前綴原則
    • 133. 無法命中索引的情況
    • 134. 資料庫讀寫分離
    • 135. 資料庫分庫分表
    • 136. redis 和 memcached 比較
    • 137. redis中資料庫默認是多少個 db 及作用
    • 138. redis 有哪幾種持久化策略
    • 139. redis 支持的過期策略
    • 140. 如何保證 redis 中的數據都是熱點數據
    • 141. Python 操作 redis
    • 143. 如何高效的找到 redis 中的某個 KEY
    • 144. 基於 redis 實現先進先出、後進先出及優先級隊列
    • 145. redis 如何實現主從複製
    • 146. 循環獲取 redis 中某個非常大的列表數據
    • 147. redis 中的 watch 的命令的作用
    • 148. redis 分布式鎖
    • 149. http 協議
    • 150. uwsgi,uWSGI 和 WSGI 的區別
    • 151. HTTP 狀態碼
    • 152. HTTP常見請求方式
    • 153. 響應式布局
    • 154. 實現一個簡單的 AJAX 請求
    • 155. 同源策略
    • 156. 什麼是 CORS
    • 157. 什麼是 CSRF
    • 158. 前端實現輪詢、長輪詢
    • 159. 簡述 MVC 和 MTV
    • 160. 接口的冪等性
    • 161. Flask 框架的優勢
    • 162. 什麼是 ORM
    • 163. PV、UV 的含義
    • 164. supervisor 的作用
    • 165. 使用 ORM 和原生 SQL 的優缺點
    • 166. 列舉一些 django 的內置組件
    • 167. 列舉 Django 中執行原生 sql 的方法
    • 168. cookie 和 session 的區別
    • 169. beautifulsoup 模塊的作用
    • 170. Selenium 模塊簡述
  • 1. 為什麼學習 Python
  • 2. 解釋型和編譯型語言的區別
  • 3. 簡述下 Python 中的字符串、列表、元組和字典
  • 4. 簡述上述數據類型的常用方法
  • 5. 簡述 Python 中的字符串編碼
  • 6.一行代碼實現數值交換
  • 7. is 和 == 的區別
  • 8.Python 函數中的參數類型
  • 9.`*arg` 和 `**kwarg` 作用
  • 10.一行代碼實現1-100之和
  • 11.獲取當前時間
  • 12.PEP8 規範
  • 13.Python 的深淺拷貝
  • 14.查看下面代碼的輸出
  • 15.可變類型與不可變類型
  • 16.列印九九乘法表
  • 17.filter、map、reduce 的作用
  • 18.re 的 match 和 search 區別
  • 19.面向對象中`__new__` 和 `__init__` 區別
  • 20.三元運算規則
  • 21.生成隨機數
  • 22.zip 函數用法
  • 23.range 和 xrange 的區別
  • 24.with 方法打開文件的作用
  • 25.什麼是正則的貪婪匹配
  • 26.為什麼不建議函數的默認參數傳入可變對象
  • 27.字符串轉列表
  • 28.字符串轉整數
  • 29.刪除列表中的重複值
  • 30.字符串單詞統計
  • 31.列表推導,求奇偶數
  • 32.一行代碼展開列表
  • 33.實現二分法查找函數
  • 34.字典和 json 轉換
  • 35.列表推導式、字典推導式和生成器
  • 36.簡述 read、readline、readlines 的區別
  • 37.打亂一個列表
  • 38.反轉字符串
  • 39.單下劃線和雙下劃線的作用
  • 40.新式類和舊式類
  • 41.Python 面向對象中的繼承有什麼特點
  • 42.super 函數的作用
  • 43.類中的各種函數
  • 44.如何判斷是函數還是方法
  • 45.isinstance 的作用以及與 type的區別
  • 46.單例模式與工廠模式
  • 47.查看目錄下的所有文件
  • 48.計算1到5組成的互不重複的三位數
  • 49.去除字符串首尾空格
  • 50.去除字符串中間的空格
  • 51. 字符串格式化方式
  • 52. 將"hello world"轉換為首字母大寫"Hello World"(不使用 title 函數)
  • 53. 一行代碼轉換列表中的整數為字符串
  • 54. 合併兩個元組到字典
  • 55. 給出如下代碼的輸入,並簡單解釋
  • 56. Python 中的反射
  • 57. 實現一個簡單的 API
  • 58. metaclass 元類
  • 59. sort 和 sorted 的區別
  • 60. Python 中的 GIL
  • 61. 產生8位隨機密碼
  • 62. 輸出原始字符
  • 63. 列表內,字典按照 value 大小排序
  • 64. 簡述 any 和 all 方法
  • 65. 反轉整數
  • 66. 函數式編程
  • 67. 簡述閉包
  • 68. 簡述裝飾器
  • 69. 協程的優點
  • 70. 實現一個斐波那契數列
  • 71. 正則切分字符串
  • 72. yield 用法
  • 73. 冒泡排序
  • 74. 快速排序
  • 75. requests 簡介
  • 76. 比較兩個 json 數據是否相等
  • 77. 讀取鍵盤輸入
  • 78. enumerate
  • 79. pass 語句
  • 80. 正則匹配郵箱
  • 81. 統計字符串中大寫字母的數量
  • 82. json 序列化時保留中文
  • 83. 簡述繼承
  • 84. 什麼是猴子補丁
  • 85. help 函數和 dir 函數
  • 86. 解釋 Python 中的`//`,`%`和`**`運算符
  • 87. 主動拋出異常
  • 88. tuple 和 list 轉換
  • 89. 簡述斷言
  • 90. 什麼是異步非阻塞
  • 91. 什麼是負索引
  • 92. 退出 Python 後,內存是否全部釋放
  • 93. Flask 和 Django 的異同
  • 94. 創建刪除作業系統上的文件
  • 95. 簡述 logging 模塊
  • 96. 統計字符串中單詞出現次數
  • 97. 正則 re.complie 的作用
  • 98. try except else finally 的意義
  • 99.反轉列表
  • 100. 字符串中數字替換
  • 101. 簡述 OSI 七層協議
  • 102. 三次握手、四次揮手的流程
  • 103. 什麼是 C/S 和 B/S 架構
  • 104. TCP 和 UDP 的區別
  • 105. 區域網和廣域網
  • 106. arp 協議
  • 107. 什麼是 socket?簡述基於 TCP 協議的套接字通信流程
  • 108. 簡述 進程、線程、協程的區別以及應用場景
  • 109. 如何使用線程池和進程池
  • 110. 進程之間如何進行通信
  • 111. 進程鎖和線程鎖
  • 112. 什麼是並發和並行
  • 113. threading.local 的作用
  • 114. 什麼是域名解析
  • 115. LVS 是什麼及作用
  • 116. Nginx 的作用
  • 117. keepalived 及 HAProxy
  • 118. 什麼是 rpc
  • 119. 從瀏覽器輸入一個網址到展示網址頁面的過程
  • 120. 什麼是cdn
  • 121. 列舉常見的資料庫
  • 122. 資料庫設計三大範式
  • 123. 什麼是資料庫事務
  • 124. MySQL 索引種類
  • 125. 資料庫設計中一對多和多對多的應用場景
  • 126. 簡述觸發器、函數、視圖、存儲過程
  • 127. 常用 SQL 語句
  • 128. 主鍵和外鍵的區別
  • 129. 如何開啟 MySQL 慢日誌查詢
  • 130. MySQL 資料庫備份命令
  • 131. char 和 varchar 的區別
  • 132. 最左前綴原則
  • 133. 無法命中索引的情況
  • 134. 資料庫讀寫分離
  • 135. 資料庫分庫分表
  • 136. redis 和 memcached 比較
  • 137. redis中資料庫默認是多少個 db 及作用
  • 138. redis 有哪幾種持久化策略
  • 139. redis 支持的過期策略
  • 140. 如何保證 redis 中的數據都是熱點數據
  • 141. Python 操作 redis
  • 143. 如何高效的找到 redis 中的某個 KEY
  • 144. 基於 redis 實現先進先出、後進先出及優先級隊列
  • 145. redis 如何實現主從複製
  • 146. 循環獲取 redis 中某個非常大的列表數據
  • 147. redis 中的 watch 的命令的作用
  • 148. redis 分布式鎖
  • 149. http 協議
  • 150. uwsgi,uWSGI 和 WSGI 的區別
  • 151. HTTP 狀態碼
  • 152. HTTP常見請求方式
  • 153. 響應式布局
  • 154. 實現一個簡單的 AJAX 請求
  • 155. 同源策略
  • 156. 什麼是 CORS
  • 157. 什麼是 CSRF
  • 158. 前端實現輪詢、長輪詢
  • 159. 簡述 MVC 和 MTV
  • 160. 接口的冪等性
  • 161. Flask 框架的優勢
  • 162. 什麼是 ORM
  • 163. PV、UV 的含義
  • 164. supervisor 的作用
  • 165. 使用 ORM 和原生 SQL 的優缺點
  • 166. 列舉一些 django 的內置組件
  • 167. 列舉 Django 中執行原生 sql 的方法
  • 168. cookie 和 session 的區別
  • 169. beautifulsoup 模塊的作用
  • 170. Selenium 模塊簡述

Python 語言簡單易懂,上手容易,隨著 AI 風潮,越來越火

2. 解釋型和編譯型語言的區別

編譯型語言:把做好的源程序全部編譯成二進位的可運行程序。然後,可直接運行這個程序。如:C,C++ 解釋型語言:把做好的源程序翻譯一句,然後執行一句,直至結束!如:Python, (Java 有些特殊,java程序也需要編譯,但是沒有直接編譯稱為機器語言,而是編譯稱為位元組碼,然後用解釋方式執行位元組碼。)

3. 簡述下 Python 中的字符串、列表、元組和字典

字符串(str):字符串是用引號括起來的任意文本,是程式語言中最常用的數據類型。列表(list):列表是有序的集合,可以向其中添加或刪除元素。元組(tuple):元組也是有序集合,但是是無法修改的。即元組是不可變的。字典(dict):字典是無序的集合,是由 key-value 組成的。集合(set):是一組 key 的集合,每個元素都是唯一,不重複且無序的。

4. 簡述上述數據類型的常用方法

字符串:

切片 mystr='luobodazahui' mystr[1:3] output 'uo'

format mystr2 = "welcome to luobodazahui, dear {name}" mystr2.format(name="baby") output 'welcome to luobodazahui, dear baby'

join 可以用來連接字符串,將字符串、元組、列表中的元素以指定的字符(分隔符)連接生成一個新的字符串。mylist = ['luo', 'bo', 'da', 'za', 'hui'] mystr3 = '-'.join(mylist) print(mystr3) outout 'luo-bo-da-za-hui'

replace String.replace(old,new,count) 將字符串中的 old 字符替換為 New 字符,count 為替換的個數 mystr4 = 'luobodazahui-haha' print(mystr4.replace('haha', 'good'))

output luobodazahui-good

split 切割字符串,得到一個列表

# 以空格分割

print(mystr5.split)

# 以h分割

print(mystr5.split( 'h'))

# 以逗號分割

print(mystr5.split( ','))

output

['luobo,dazahui', 'good']

['luobo,daza', 'ui good']

['luobo', 'dazahui good']

列表:

切片 同字符串

append 和 extend 向列表中國添加元素

mylist2 = [ 3, 4]

mylist3 = [ 1, 2]

mylist1.append(mylist2)

print(mylist1)

mylist3.extend(mylist2)

print(mylist3)

outout

[1, 2, [3, 4]]

[1, 2, 3, 4]

刪除元素 del:根據下標進行刪除 pop:刪除最後一個元素 remove:根據元素的值進行刪除

delmylist4[ 0]

print(mylist4)

mylist4.pop

print(mylist4)

mylist4.remove( 'c')

print(mylist4)

output

['b', 'c', 'd']

['b', 'c']

['b']

元素排序 sort:是將list按特定順序重新排列,默認為由小到大,參數 reverse=True 可改為倒序,由大到小。reverse:是將list逆置

mylist5.sort

print(mylist5)

mylist5.reverse

print(mylist5)

output

[1, 2, 3, 4, 5]

[5, 4, 3, 2, 1]

字典:

清空字典 dict.clear

dict1.clear

print(dict1)

output

{}

指定刪除 使用 pop 方法來指定刪除字典中的某一項

d1 = dict1.pop( 'key1')

print(d1)

print(dict1)

output

1

{'key2': 2}

遍歷字典

mykey = [key forkey indict2]

print(mykey)

myvalue = [value forvalue indict2.values]

print(myvalue)

key_value = [(k, v) fork, v indict2.items ]

print(key_value)

output

['key1', 'key2']

[1, 2]

[('key1', 1), ('key2', 2)]

fromkeys 用於創建一個新字典,以序列中元素做字典的鍵,value 為字典所有鍵對應的初始值

dict.fromkeys(keys, 0)

output

{'zhangfei': 0, 'guanyu': 0, 'liubei': 0, 'zhaoyun': 0}

5. 簡述 Python 中的字符串編碼"中文".encode( 'utf-8')

output

b'\xe4\xb8\xad\xe6\x96\x87'

decode

b'\xe4\xb8\xad\xe6\x96\x87'.decode( 'utf-8')

output

'中文'

6.一行代碼實現數值交換1a = 1

2b = 2

3a, b = b, a

4print(a, b)

output

12 1

7. is 和 == 的區別

先來看個例子

c = d = [ 1, 2]

e = [ 1, 2]

print(c isd)

print(c == d)

print(c ise)

print(c == e)

output

True

True

False

True

== 是比較操作符,只是判斷對象的值(value)是否一致,而 is 則判斷的是對象之間的身份(內存地址)是否一致。對象的身份,可以通過 id 方法來查看

id(c)

id(d)

id(e)

output

88748080

88748080

88558288

可以看出,只有 id 一致時,is 比較才會返回 True,而當 value 一致時,== 比較就會返回 True

8.Python 函數中的參數類型

位置參數,默認參數,可變參數,關鍵字參數

9. *arg 和 **kwarg 作用

允許我們在調用函數的時候傳入多個實參

deftest(*arg, **kwarg):

ifarg:

print( "arg:", arg)

ifkwarg:

print( "kearg:", kwarg)

test( 'ni', 'hao', key= 'world')

output

arg: ('ni', 'hao')

kearg: {'key': 'world'}

可以看出, *arg 會把位置參數轉化為 tuple **kwarg 會把關鍵字參數轉化為 dict

10.一行代碼實現1-100之和sum(range( 1, 101))

11.獲取當前時間importtime

importdatetime

print(datetime.datetime.now)

print(time.strftime( '%Y-%m-%d %H:%M:%S'))

output

2019-06-07 18:12:11.165330

2019-06-07 18:12:11

12.PEP8 規範

簡單列舉10條:儘量以免單獨使用小寫字母'l',大寫字母'O',以及大寫字母'I'等容易混淆的字母。函數命名使用全部小寫的方式,可以使用下劃線。常量命名使用全部大寫的方式,可以使用下劃線。使用 has 或 is 前綴命名布爾元素,如: is_connect = True; has_member = False 不要在行尾加分號, 也不要用分號將兩條命令放在同一行。不要使用反斜槓連接行。頂級定義之間空2行, 方法定義之間空1行,頂級定義之間空兩行。如果一個類不繼承自其它類, 就顯式的從object繼承。內部使用的類、方法或變量前,需加前綴 _ 表明此為內部使用的。要用斷言來實現靜態類型檢測。

13.Python 的深淺拷貝

淺拷貝

importcopy

list1 = [ 1, 2, 3, [ 1, 2]]

list2 = copy.copy(list1)

list2.append( 'a')

list2[ 3].append( 'a')

print(list1, list2)

output

[1, 2, 3, [1, 2, 'a']] [1, 2, 3, [1, 2, 'a'], 'a']

能夠看出,淺拷貝只成功」獨立「拷貝了列表的外層,而列表的內層列表,還是共享的

深拷貝

importcopy

list1 = [ 1, 2, 3, [ 1, 2]]

list3 = copy.deepcopy(list1)

list3.append( 'a')

list3[ 3].append( 'a')

print(list1, list3)

output

[1, 2, 3, [1, 2]] [1, 2, 3, [1, 2, 'a'], 'a']

深拷貝使得兩個列表完全獨立開來,每一個列表的操作,都不會影響到另一個

14.查看下面代碼的輸出defnum:

return[ lambdax:i*x fori inrange( 4)]

print([m( 1) form innum])

output

[3, 3, 3, 3]

通過運行結果,可以看出 i 的取值為3,很神奇

15.可變類型與不可變類型

可變數據類型:list、dict、set

不可變數據類型:int/float、str、tuple

16.列印九九乘法表fori inrange( 1, 10):

forj inrange( 1, i+ 1):

print( "%s*%s=%s "%(i, j, i*j), end= "")

print

output

1*1=1

2*1=2 2*2=4

3*1=3 3*2=6 3*3=9

4*1=4 4*2=8 4*3=12 4*4=16

5*1=5 5*2=10 5*3=15 5*4=20 5*5=25

6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36

7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49

8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64

9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

print 函數,默認是會換行的,其有一個默認參數 end,如果像例子中,我們把 end 參數顯示的置為"",那麼 print 函數執行完後,就不會換行了,這樣就達到了九九乘法表的效果了

17.filter、map、reduce 的作用

filter 函數用於過濾序列,它接收一個函數和一個序列,把函數作用在序列的每個元素上,然後根據返回值是True還是False決定保留還是丟棄該元素

mylist = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]

list(filter( lambdax: x% 2== 1, mylist))

output

[1, 3, 5, 7, 9]

保留奇數列表

map 函數傳入一個函數和一個序列,並把函數作用到序列的每個元素上,返回一個可疊代對象

mylist = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]

list(map( lambdax: x* 2, mylist))

output

[2, 4, 6, 8, 10, 12, 14, 16, 18]

reduce 函數用於遞歸計算,同樣需要傳入一個函數和一個序列,並把函數和序列元素的計算結果與下一個元素進行計算

fromfunctools importreduce

reduce( lambdax, y: x+y, range( 101))

output

5050

可以看出,上面的三個函數與匿名函數相結合使用,可以寫出強大簡潔的代碼

18.re 的 match 和 search 區別

match函數隻檢測要匹配的字符是不是在 string 的開始位置匹配,search會掃描整個 string 查找匹配

19.面向對象中 __new__ 和 __init__ 區別

__new__ 是在實例創建之前被調用的,因為它的任務就是創建實例然後返回該實例對象,是個靜態方法。 __init__ 是當實例對象創建完成後被調用的,然後設置對象屬性的一些初始值,通常用在初始化一個類實例的時候,是一個實例方法

20.三元運算規則a, b = 1, 2

# 若果 a>b 成立 就輸出 a-b 否則 a+b

h = a-b ifa>b elsea+b

output

3

21.生成隨機數print(random.random)

print(random.randint( 1, 100))

print(random.uniform( 1, 5))

output

0.03765019937131564

18

1.8458555362279228

22.zip 函數用法

zip 函數將可疊代的對象作為參數,將對象中對應的元素打包成一個個元組,然後返回由這些元組組成的列表

list1 = [ 'zhangfei', 'guanyu', 'liubei', 'zhaoyun']

list2 = [ 0, 3, 2, 4]

list(zip(list1, list2))

output

[('zhangfei', 0), ('guanyu', 3), ('liubei', 2), ('zhaoyun', 4)]

23.range 和 xrange 的區別

range([start,] stop[, step]),根據start與stop指定的範圍以及step設定的步長,生成一個序列。而 xrange 生成一個生成器,可以很大的節約內存

24.with 方法打開文件的作用

開文件在進行讀寫的時候可能會出現一些異常狀況,如果按照常規的 f.open 寫法,我們需要 try,except,finally,做異常判斷,並且文件最終不管遇到什麼情況,都要執行 finally f.close 關閉文件,with 方法幫我們實現了 finally 中 f.close

25.什麼是正則的貪婪匹配

Python 中默認是貪婪匹配模式

貪婪模式:正則表達式一般趨向於最大長度匹配

非貪婪模式:在整個表達式匹配成功的前提下,儘可能少的匹配

26.為什麼不建議函數的默認參數傳入可變對象

例如:

deftest(L=[]):

L.append( 'test')

print(L)

output

test # ['test']

test # ['test', 'test']

默認參數是一個列表,是可變對象[],Python 在函數定義的時候,默認參數 L 的值就被計算出來了,是[],每次調用函數,如果 L 的值變了,那麼下次調用時,默認參數的值就已經不再是[]了

27.字符串轉列表mystr = '1,2,3'

mystr.split( ',')

output

['1', '2', '3']

28.字符串轉整數mylist = [ '1', '2', '3']

list(map( lambdax: int(x), mylist))

output

[1, 2, 3]

29.刪除列表中的重複值mylist = [ 1, 2, 3, 4, 5, 5]

list(set(mylist))

30.字符串單詞統計fromcollections importCounter

mystr = 'sdfsfsfsdfsd,were,hrhrgege.sdfwe!sfsdfs'

Counter(mystr)

output

Counter({ 's': 9,

'd': 5,

'f': 7,

',': 2,

'w': 2,

'e': 5,

'r': 3,

'h': 2,

'g': 2,

'.': 1,

'!': 1})

31.列表推導,求奇偶數[x forx inrange( 10) ifx% 2== 1]

output

[1, 3, 5, 7, 9]

32.一行代碼展開列表list1 = [[ 1, 2],[ 3, 4],[ 5, 6]]

[j fori inlist1 forj ini]

output

[1, 2, 3, 4, 5, 6]

33.實現二分法查找函數

二分查找算法也稱折半查找,基本思想就是折半,對比大小後再折半查找,必須是有序序列才可以使用二分查找

遞歸算法

defbinary_search(data, item):

# 遞歸

n = len(data)

ifn > 0:

mid = n // 2

ifdata[mid] == item:

returnTrue

elifdata[mid] > item:

returnbinary_search(data[:mid], item)

else:

returnbinary_search(data[mid+ 1:], item)

returnFalse

list1 = [ 1, 4, 5, 66, 78, 99, 100, 101, 233, 250, 444, 890]

binary_search(list1, 999)

非遞歸算法

defbinary_search(data, item):

# 非遞歸

n = len(data)

first = 0

last = n - 1

whilefirst <= last:

mid = (first + last)// 2

ifdata[mid] == item:

returnTrue

elifdata[mid] > item:

last = mid - 1

else:

first = mid + 1

returnFalse

list1 = [ 1, 4, 5, 66, 78, 99, 100, 101, 233, 250, 444, 890]

binary_search(list1, 99)

34.字典和 json 轉換

字典轉 json

importjson

dict1 = { 'zhangfei': 1, "liubei": 2, "guanyu": 4, "zhaoyun": 3}

myjson = json.dumps(dict1)

myjson

output

'{"zhangfei": 1, "liubei": 2, "guanyu": 4, "zhaoyun": 3}'

json 轉字典

mydict = json.loads(myjson)

mydict

output

{'zhangfei': 1, 'liubei': 2, 'guanyu': 4, 'zhaoyun': 3}

35.列表推導式、字典推導式和生成器importrandom

td_list=[i fori inrange( 10)]

print( "列表推導式", td_list, type(td_list))

ge_list = (i fori inrange( 10))

print( "生成器", ge_list)

dic = {k:random.randint( 4, 9) fork in[ "a", "b", "c", "d"]}

print( "字典推導式",dic,type(dic))

output

列表推導式 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

生成器 at 0x0139F070>

字典推導式 {'a': 6, 'b': 5, 'c': 8, 'd': 9}

36.簡述 read、readline、readlines 的區別

read 讀取整個文件

readline 讀取下一行,使用生成器方法

readlines 讀取整個文件到一個疊代器以供我們遍歷

37.打亂一個列表list2 = [ 1, 2, 3, 4, 5, 6]

random.shuffle(list2)

print(list2)

output

[4, 6, 5, 1, 2, 3]

38.反轉字符串str1 = 'luobodazahui'

str1[:: -1]

output

'iuhazadoboul'

39.單下劃線和雙下劃線的作用

__foo__ :一種約定,Python 內部的名字,用來區別其他用戶自定義的命名,以防衝突,就是例如 __init__ , __del__ , __call__ 些特殊方法

_foo :一種約定,用來指定變量私有。不能用 from module import * 導入,其他方面和公有變量一樣訪問

__foo :這個有真正的意義:解析器用 _classname__foo 來代替這個名字,以區別和其他類相同的命名,它無法直接像公有成員一樣隨便訪問,通過對象名 ._ 類名 __xxx 這樣的方式可以訪問

40.新式類和舊式類

a. 在 python 里凡是繼承了 object 的類,都是新式類

b. Python3 里只有新式類

c. Python2 裡面繼承 object 的是新式類,沒有寫父類的是經典類

d. 經典類目前在 Python 里基本沒有應用

41.Python 面向對象中的繼承有什麼特點

a. 同時支持單繼承與多繼承,當只有一個父類時為單繼承,當存在多個父類時為多繼承

b. 子類會繼承父類所有的屬性和方法,子類也可以覆蓋父類同名的變量和方法

c. 在繼承中基類的構造( __init__ )方法不會被自動調用,它需要在其派生類的構造中專門調用

d. 在調用基類的方法時,需要加上基類的類名前綴,且需要帶上 self 參數變量。區別於在類中調用普通函數時並不需要帶上 self 參數

42.super 函數的作用

super 函數是用於調用父類(超類)的一個方法

classA:

deffuncA(self):

print( "this is func A")

classB(A):

deffuncA_in_B(self):

super(B, self).funcA

deffuncC(self):

print( "this is func C")

ins = B

ins.funcA_in_B

ins.funcC

output

this is func A

this is func C

43.類中的各種函數

主要分為實例方法、類方法和靜態方法

實例方法

定義:第一個參數必須是實例對象,該參數名一般約定為「self」,通過它來傳遞實例的屬性和方法(也可以傳類的屬性和方法)

調用:只能由實例對象調用

類方法

定義:使用裝飾器@classmethod。第一個參數必須是當前類對象,該參數名一般約定為「cls」,通過它來傳遞類的屬性和方法(不能傳實例的屬性和方法)

調用:實例對象和類對象都可以調用

靜態方法

定義:使用裝飾器@staticmethod。參數隨意,沒有「self」和「cls」參數,但是方法體中不能使用類或實例的任何屬性和方法

調用:實例對象和類對象都可以調用

靜態方法是類中的函數,不需要實例。靜態方法主要是用來存放邏輯性的代碼,主要是一些邏輯屬於類,但是和類本身沒有交互。即在靜態方法中,不會涉及到類中的方法和屬性的操作。可以理解為將靜態方法存在此類的名稱空間中

類方法是將類本身作為對象進行操作的方法。他和靜態方法的區別在於:不管這個方式是從實例調用還是從類調用,它都用第一個參數把類傳遞過來

44.如何判斷是函數還是方法

與類和實例無綁定關係的 function 都屬於函數(function)

與類和實例有綁定關係的 function 都屬於方法(method)

普通函數:

deffunc1:

pass

print(func1)

output

0x01379348>

類中的函數:

classPeople(object):

deffunc2(self):

pass

@staticmethod

deffunc3:

pass

@classmethod

deffunc4(cls):

pass

people = People

print(people.func2)

print(people.func3)

print(people.func4)

output

>

>

45.isinstance 的作用以及與 type的區別

isinstance 函數來判斷一個對象是否是一個已知的類型,類似 type

區別:

type 不會認為子類是一種父類類型,不考慮繼承關係

isinstance 會認為子類是一種父類類型,考慮繼承關係

classA(object):

pass

classB(A):

pass

a = A

b = B

print(isinstance(a, A))

print(isinstance(b, A))

print(type(a) == A)

print(type(b) == A)

output

True

True

True

False

46.單例模式與工廠模式

單例模式:主要目的是確保某一個類只有一個實例存在

工廠模式:包涵一個超類,這個超類提供一個抽象化的接口來創建一個特定類型的對象,而不是決定哪個對象可以被創建

47.查看目錄下的所有文件importos

print(os.listdir( '.'))

48.計算1到5組成的互不重複的三位數# 1到5組成的互不重複的三位數

k = 0

fori inrange( 1, 6):

forj inrange( 1, 6):

forz inrange( 1, 6):

if(i != j) and(i != z) and(j != z):

k += 1

ifk% 6:

print( "%s%s%s"%(i, j, z), end= "|")

else:

print( "%s%s%s"%(i, j, z))

output

123|124|125|132|134|135

142|143|145|152|153|154

213|214|215|231|234|235

241|243|245|251|253|254

312|314|315|321|324|325

341|342|345|351|352|354

412|413|415|421|423|425

431|432|435|451|452|453

512|513|514|521|523|524

531|532|534|541|542|543

49.去除字符串首尾空格str1 = " hello nihao "

str1.strip

output

'hello nihao'

50.去除字符串中間的空格str2 = "hello you are good"

print(str2.replace( " ", ""))

"".join(str2.split( " "))

output

helloyouaregood

'helloyouaregood'

51. 字符串格式化方式

使用 % 操作符

print( "This is for %s, and %s"%( "Python", "You"))

output

This is for Python

This is for Python, and You

str.format

在 Python3 中,引入了這個新的字符串格式化方法

print( "This is my {}".format( "chat"))

print( "This is {name}, hope you can {do}".format(name= "zhouluob", do= "like"))

output

This is my chat

This is zhouluob, hope you can like

f-strings

在 Python3-6 中,引入了這個新的字符串格式化方法

name = "luobodazahui"

print( f"hello {name}" )

output

hello luobodazahui

一個複雜些的例子:

defmytest(name, age):

returnf"hello {name}, you are {age}years old!"

people = mytest( "luobo", 20)

print(people)

output

hello luobo, you are 20 years old!

52. 將"hello world"轉換為首字母大寫"Hello World"(不使用 title 函數)str1 = "hello world"

print(str1.title)

" ".join(list(map( lambdax: x.capitalize, str1.split( " "))))

output

Hello World

'Hello World'

53. 一行代碼轉換列表中的整數為字符串

如:[1, 2, 3] -> ["1", "2", "3"]

list1 = [ 1, 2, 3]

list(map( lambdax: str(x), list1))

output

['1', '2', '3']

54. 合併兩個元組到字典

如:("zhangfei", "guanyu"),(66, 80) -> {'zhangfei': 66, 'guanyu': 80}

a = ( "zhangfei", "guanyu")

b = ( 66, 80)

dict(zip(a,b))

output

{'zhangfei': 66, 'guanyu': 80}

55. 給出如下代碼的輸入,並簡單解釋

例子1:

a = ( 1, 2, 3,[ 4, 5, 6, 7], 8)

a[ 3] = 2

output

---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

in

1 a = (1,2,3,[4,5,6,7],8)

----> 2 a[3] = 2

3 #a

TypeError: 'tuple' object does not support item assignment

例子2:

a = ( 1, 2, 3,[ 4, 5, 6, 7], 8)

a[ 3][ 2] = 2

a

output

(1, 2, 3, [4, 5, 2, 7], 8)

從例子1的報錯中也可以看出,tuple 是不可變類型,不能改變 tuple 里的元素,例子2中,list 是可變類型,改變其元素是允許的

56. Python 中的反射

反射就是通過字符串的形式,導入模塊;通過字符串的形式,去模塊尋找指定函數,並執行。利用字符串的形式去對象(模塊)中操作(查找/獲取/刪除/添加)成員,一種基於字符串的事件驅動!

簡單理解就是用來判斷某個字符串是什麼,是變量還是方法

classNewClass(object):

def__init__(self, name, male):

self.name = name

self.male = male

defmyname(self):

print( f'My name is {self.name}' )

defmymale(self):

print( f'I am a {self.male}' )

people = NewClass( 'luobo', 'boy')

print(hasattr(people, 'name'))

print(getattr(people, 'name'))

setattr(people, 'male', 'girl')

print(getattr(people, 'male'))

output

True

luobo

girl

getattr,hasattr,setattr,delattr 對模塊的修改都在內存中進行,並不會影響文件中真實內容

57. 實現一個簡單的 API

使用 flask 構造 web 伺服器

fromflask importFlask, request

app = Flask(__name__)

@app.route('/', methods=['POST'])

defsimple_api:

result = request.get_json

returnresult

if__name__ == "__main__":

app.run

58. metaclass 元類

類與實例:

首先定義類以後,就可以根據這個類創建出實例,所以:先定義類,然後創建實例

類與元類:

先定義元類, 根據 metaclass 創建出類,所以:先定義 metaclass,然後創建類

classMyMetaclass(type):

def__new__(cls, class_name, class_parents, class_attr):

class_attr[ 'print'] = "this is my metaclass's subclass %s"%class_name

returntype.__new__(cls, class_name, class_parents, class_attr)

classMyNewclass(object, metaclass=MyMetaclass):

pass

myinstance = MyNewclass

myinstance. print

output

"this is my metaclass's subclass MyNewclass"

59. sort 和 sorted 的區別

sort 是可變對象列表(list)的方法,無參數,無返回值,sort 會改變可變對象

dict1 = { 'test1': 1, 'test2': 2}

list1 = [ 2, 1, 3]

print(list1.sort)

list1

output

None

[1, 2, 3]

sorted 是產生一個新的對象。sorted(L) 返回一個排序後的L,不改變原始的L,sorted 適用於任何可疊代容器

dict1 = { 'test1': 1, 'test2': 2}

list1 = [ 2, 1, 3]

print(sorted(dict1))print(sorted(list1))

output

['test1', 'test2']

[1, 2, 3]

60. Python 中的 GIL

GIL 是 Python 的全局解釋器鎖,同一進程中假如有多個線程運行,一個線程在運行 Python 程序的時候會占用 Python 解釋器(加了一把鎖即 GIL),使該進程內的其他線程無法運行,等該線程運行完後其他線程才能運行。如果線程運行過程中遇到耗時操作,則解釋器鎖解開,使其他線程運行。所以在多線程中,線程的運行仍是有先後順序的,並不是同時進行

61. 產生8位隨機密碼importrandom

"".join(random.choice(string.printable[: -7]) fori inrange( 8))

output

'd5^NdNJp'

62. 輸出原始字符print( 'hello\nworld')

print( b'hello\nworld')

print( r'hello\nworld')

output

hello

world

b'hello\nworld'

hello\nworld

63. 列表內,字典按照 value 大小排序list1 = [{ 'name': 'guanyu', 'age': 29},

{ 'name': 'zhangfei', 'age': 28},

{ 'name': 'liubei', 'age': 31}]

sorted(list1, key= lambdax:x[ 'age'])

output

[{'name': 'zhangfei', 'age': 28},

{'name': 'guanyu', 'age': 29},

{'name': 'liubei', 'age': 31}]

64. 簡述 any 和 all 方法

all 如果存在 0 Null False 返回 False,否則返回 True;any 如果都是 0,None,False,Null 時,返回 True

print(all([ 1, 2, 3, 0]))

print(all([ 1, 2, 3]))

print(any([ 1, 2, 3, 0]))

print(any([ 0, None, False]))

output

False

True

True

False

65. 反轉整數defreverse_int(x):

ifnotisinstance(x, int):

returnFalse

if-10< x < 10:

returnx

tmp = str(x)

iftmp[ 0] != '-':

tmp = tmp[:: -1]

returnint(tmp)

else:

tmp = tmp[ 1:][:: -1]

x = int(tmp)

return-x

reverse_int( -23837)

output

-73832

首先判斷是否是整數,再判斷是否是一位數字,最後再判斷是不是負數

66. 函數式編程

函數式編程是一種抽象程度很高的編程範式,純粹的函數式程式語言編寫的函數沒有變量,因此,任意一個函數,只要輸入是確定的,輸出就是確定的,這種純函數稱之為沒有副作用。而允許使用變量的程序設計語言,由於函數內部的變量狀態不確定,同樣的輸入,可能得到不同的輸出,因此,這種函數是有副作用的。由於 Python 允許使用變量,因此,Python 不是純函數式程式語言

函數式編程的一個特點就是,允許把函數本身作為參數傳入另一個函數,還允許返回一個函數!

函數作為返回值例子:

defsum(*args):

definner_sum:

tmp = 0

fori inargs:

tmp += i

returntmp

returninner_sum

mysum = sum( 2, 4, 6)

print(type(mysum))

mysum

output

12

67. 簡述閉包

如果在一個內部函數裡,對在外部作用域(但不是在全局作用域)的變量進行引用,那麼內部函數就被認為是閉包(closure) 附上函數作用域圖片

閉包特點

1.必須有一個內嵌函數

2.內嵌函數必須引用外部函數中的變量

3.外部函數的返回值必須是內嵌函數

68. 簡述裝飾器

裝飾器是一種特殊的閉包,就是在閉包的基礎上傳遞了一個函數,然後覆蓋原來函數的執行入口,以後調用這個函數的時候,就可以額外實現一些功能了

一個列印 log 的例子:

importtime

deflog(func):

definner_log(*args, **kw):

print( "Call: {}".format(func.__name__))

returnfunc(*args, **kw)

returninner_log

@log

deftimer:

print(time.time)

timer

output

Call: timer

1560171403.5128365

本質上,decorator就是一個返回函數的高階函數

69. 協程的優點

子程序切換不是線程切換,而是由程序自身控制

沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯

不需要多線程的鎖機制,因為只有一個線程,也不存在同時寫變量衝突,在協程中控制共享資源不加鎖

70. 實現一個斐波那契數列

斐波那契數列:

又稱黃金分割數列,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上,斐波納契數列以如下被以遞歸的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)

生成器法:

deffib(n):

ifn == 0:

returnFalse

ifnotisinstance(n, int) or(abs(n) != n): # 判斷是正整數

returnFalse

a, b = 0, 1

whilen:

a, b = b, a+b

n -= 1

yielda

[i fori infib( 10)]

output

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

遞歸法:

deffib(n):

ifn == 0:

returnFalse

ifnotisinstance(n, int) or(abs(n) != n):

returnFalse

ifn <= 1:

returnn

returnfib(n -1)+ fib(n -2)

[fib(i) fori inrange( 1, 11)]

output

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

71. 正則切分字符串importre

str1 = 'hello world:luobo dazahui'

result = re.split( r":| ", str1)

print(result)

output

['hello', 'world', 'luobo', 'dazahui']

72. yield 用法

yield 是用來生成疊代器的語法,在函數中,如果包含了 yield,那麼這個函數就是一個疊代器。當代碼執行至 yield 時,就會中斷代碼執行,直到程序調用 next 函數時,才會在上次 yield 的地方繼續執行

defforyield:

print( "start test yield")

whileTrue:

result = yield5

print( "result:", result)

g = foryield

print(next(g))

print( "*"* 20)

print(next(g))

output

start test yield

5

********************

result: None

5

可以看到,第一個調用 next 函數,程序只執行到了 "result = yield 5" 這裡,同時由於 yield 中斷了程序,所以 result 也沒有被賦值,所以第二次執行 next 時,result 是 None

73. 冒泡排序list1 = [ 2, 5, 8, 9, 3, 11]

defpaixu(data, reverse=False):

ifnotreverse:

fori inrange(len(data) - 1):

forj inrange(len(data) - 1- i):

ifdata[j] > data[j+ 1]:

data[j], data[j+ 1] = data[j+ 1], data[j]

returndata

else:

fori inrange(len(data) - 1):

forj inrange(len(data) - 1- i):

ifdata[j] < data[j+ 1]:

data[j], data[j+ 1] = data[j+ 1], data[j]

returndata

print(paixu(list1, reverse= True))

output

[11, 9, 8, 5, 3, 2]

74. 快速排序

快排的思想:首先任意選取一個數據(通常選用數組的第一個數)作為關鍵數據,然後將所有比它小的數都放到它前面,所有比它大的數都放到它後面,這個過程稱為一趟快速排序,之後再遞歸排序兩邊的數據

挑選基準值:從數列中挑出一個元素,稱為"基準"(pivot)

分割:重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準後面(與基準值相等的數可以到任何一邊)

在這個分割結束之後,對基準值的排序就已經完成

遞歸排序子序列:遞歸地將小於基準值元素的子序列和大於基準值元素的子序列排序

list1 = [ 8, 5, 1, 3, 2, 10, 11, 4, 12, 20]

defpartition(arr,low,high):

i = ( low -1) # 最小元素索引

pivot = arr[high]

forj inrange(low , high):

# 當前元素小於或等於 pivot

ifarr[j] <= pivot:

i = i+ 1

arr[i],arr[j] = arr[j],arr[i]

arr[i+ 1],arr[high] = arr[high],arr[i+ 1]

return( i+ 1)

defquicksort(arr,low,high):

iflow < high:

pi = partition(arr,low,high)

quicksort(arr, low, pi -1)

quicksort(arr, pi+ 1, high)

quicksort(list1, 0, len(list1) -1)

print(list1)

output

[1, 2, 3, 4, 5, 8, 10, 11, 12, 20]

75. requests 簡介

該庫是發起 HTTP 請求的強大類庫,調用簡單,功能強大

importrequests

url = "http://www.luobodazahui.top"

response = requests.get(url) # 獲得請求

response.encoding = "utf-8"# 改變其編碼

html = response.text # 獲得網頁內容

binary__content = response.content # 獲得二進位數據

raw = requests.get(url, stream= True) # 獲得原始響應內容

headers = { 'user-agent': 'my-test/0.1.1'} # 定製請求頭

r = requests.get(url, headers=headers)

cookies = { "cookie": "# your cookie"} # cookie的使用

r = requests.get(url, cookies=cookies)

76. 比較兩個 json 數據是否相等dict1 = { "zhangfei": 12, "guanyu": 13, "liubei": 18}

dict2 = { "zhangfei": 12, "guanyu": 13, "liubei": 18}

defcompare_dict(dict1, dict2):

issame = []

fork indict1.keys:

ifk indict2:

ifdict1[k] == dict2[k]:

issame.append( 1)

else:

issame.append( 2)

else:

issame.append( 3)

print(issame)

sum_except = len(issame)

sum_actually = sum(issame)

ifsum_except == sum_actually:

print( "this two dict are same!")

returnTrue

else:

print( "this two dict are not same!")

returnFalse

test = compare_dict(dict1, dict2)

output

[1, 1, 1]

this two dict are same!

77. 讀取鍵盤輸入input 函數

defforinput:

input_text = input

print( "your input text is: ", input_text)

forinput

output

hello

your input text is: hello

78. enumerate

enumerate 函數用於將一個可遍歷的數據對象(如列表、元組或字符串)組合為一個索引序列,同時列出數據和數據下標,一般用在 for 循環當中

data1 = [ 'one', 'two', 'three', 'four']

fori, enu inenumerate(data1):

print(i, enu)

output

0 one

1 two

2 three

3 four

79. pass 語句

pass 是空語句,是為了保持程序結構的完整性。pass 不做任何事情,一般用做占位語句

defforpass(n):

ifn == 1:

pass

else:

print( 'not 1')

forpass( 1)

80. 正則匹配郵箱importre

email_list= [ "[email protected]", "[email protected]", "[email protected]", "[email protected]"]

foremail inemail_list:

ret = re.match( "[\w]{4,20}@(.*)\.com$",email)

ifret:

print( "%s 是符合規定的郵件地址,匹配後結果是:%s"% (email,ret.group))

else:

print( "%s 不符合要求"% email)

output

[email protected] 是符合規定的郵件地址,匹配後結果是:[email protected]

[email protected] 不符合要求

[email protected] 不符合要求

[email protected] 是符合規定的郵件地址,匹配後結果是:[email protected]

81. 統計字符串中大寫字母的數量str2 = 'werrQWSDdiWuW'

counter = 0

fori instr2:

ifi.isupper:

counter += 1

print(counter)

output

6

82. json 序列化時保留中文

普通序列化:

importjson

dict1 = { 'name': '蘿蔔', 'age': 18}

dict1_new = json.dumps(dict1)

print(dict1_new)

output

{"name": "蘿蔔", "age": 18}

保留中文

importjson

dict1 = { 'name': '蘿蔔', 'age': 18}

dict1_new = json.dumps(dict1, ensure_ascii= False)

print(dict1_new)

output

{"name": "蘿蔔", "age": 18}

83. 簡述繼承

一個類繼承自另一個類,也可以說是一個孩子類/派生類/子類,繼承自父類/基類/超類,同時獲取所有的類成員(屬性和方法)

繼承使我們可以重用代碼,並且還可以更方便地創建和維護代碼

Python 支持以下類型的繼承:

單繼承- 一個子類類繼承自單個基類

多重繼承- 一個子類繼承自多個基類

多級繼承- 一個子類繼承自一個基類,而基類繼承自另一個基類

分層繼承- 多個子類繼承自同一個基類

混合繼承- 兩種或兩種以上繼承類型的組合

84. 什麼是猴子補丁

猴子補丁是指在運行時動態修改類和模塊

猴子補丁主要有以下幾個用處:

在運行時替換方法、屬性等

在不修改第三方代碼的情況下增加原來不支持的功能

在運行時為內存中的對象增加 patch 而不是在磁碟的原始碼中增加

85. help 函數和 dir 函數

help 函數返回幫助文檔和參數說明:

help(dict)

output

Help on class dict in module builtins:

class dict(object)

| dict -> new empty dictionary

| dict(mapping) -> new dictionary initialized from a mapping object's

| (key, value) pairs

| dict(iterable) -> new dictionary initialized as if via:

| d = {}

| for k, v in iterable:

| d[k] = v

| dict(**kwargs) -> new dictionary initialized with the name=value pairs

| in the keyword argument list. For example: dict(one=1, two=2)

......

dir 函數返回對象中的所有成員 (任何類型)

dir(dict)

output

['__class__',

'__contains__',

'__delattr__',

'__delitem__',

'__dir__',

'__doc__',

'__eq__',

'__format__',

'__ge__',

'__getattribute__',

'__getitem__',

......

86. 解釋 Python 中的 // , % 和 ** 運算符

// 運算符執行地板除法,返回結果的整數部分 (向下取整)

% 是取模符號,返回除法後的餘數

** 符號表示取冪. a**b 返回 a 的 b 次方

print( 5// 3)

print( 5/ 3)

print( 5% 3)

print( 5** 3)

output

1

1.6666666666666667

2

125

87. 主動拋出異常

使用 raise

deftest_raise(n):

ifnotisinstance(n, int):

raiseException( 'not a int type')

else:

print( 'good')

test_raise( 8.9)

output

---------------------------------------------------------------------------

Exception Traceback (most recent call last)

in

4 else:

5 print('good')

----> 6 test_raise(8.9)

in test_raise(n)

1 def test_raise(n):

2 if not isinstance(n, int):

----> 3 raise Exception('not a int type')

4 else:

5 print('good')

Exception: not a int type

88. tuple 和 list 轉換tuple1 = ( 1, 2, 3, 4)

list1 = list(tuple1)

print(list1)

tuple2 = tuple(list1)

print(tuple2)

output

[1, 2, 3, 4](1, 2, 3, 4)

89. 簡述斷言

Python 的斷言就是檢測一個條件,如果條件為真,它什麼都不做;反之它觸發一個帶可選錯誤信息的 Asserti

deftestassert(n):

assertn == 2, "n is not 2"

print( 'n is 2')

testassert( 1)

output

---------------------------------------------------------------------------

Asserti Traceback (most recent call last)

in

2 assert n == 2, "n is not 2"

3 print('n is 2')

----> 4 testassert(1)

in testassert(n)

1 def testassert(n):

----> 2 assert n == 2, "n is not 2"

3 print('n is 2')

4 testassert(1)

Asserti: n is not 2

90. 什麼是異步非阻塞

同步異步指的是調用者與被調用者之間的關係

所謂同步,就是在發出一個功能調用時,在沒有得到結果之前,該調用就不會返回,一旦調用返回,就得到了返回值

異步的概念和同步相對,調用在發出之後,這個調用就直接返回了,所以沒有返回結果。當該異步功能完成後,被調用者可以通過狀態、通知或回調來通知調用者

阻塞非阻塞是線程或進程之間的關係

阻塞調用是指調用結果返回之前,當前線程會被掛起(如遇到io操作)。調用線程只有在得到結果之後才會返回。函數只有在得到結果之後才會將阻塞的線程激活

非阻塞和阻塞的概念相對應,非阻塞調用指在不能立刻得到結果之前也會立刻返回,同時該函數不會阻塞當前線程

91. 什麼是負索引

Python 中的序列是有索引的,它由正數和負數組成。正的數字使用'0'作為第一個索引,'1'作為第二個索引,以此類推

負數的索引從'-1'開始,表示序列中的最後一個索引,' - 2'作為倒數第二個索引,依次類推

92. 退出 Python 後,內存是否全部釋放

不是的,那些具有對象循環引用或者全局命名空間引用的變量,在 Python 退出時往往不會被釋放

另外不會釋放 C 庫保留的部分內容

93. Flask 和 Django 的異同

Flask 是 「microframework」,主要用來編寫小型應用程式,不過隨著 Python 的普及,很多大型程序也在使用 Flask。同時,在 Flask 中,我們必須使用外部庫

Django 適用於大型應用程式。它提供了靈活性,以及完整的程序框架和快速的項目生成方法。可以選擇不同的資料庫,URL結構,模板樣式等

94. 創建刪除作業系統上的文件importos

f = open( 'test.txt', 'w')

f.close

os.listdir

os.remove( 'test.txt')

95. 簡述 logging 模塊

logging 模塊是 Python 內置的標準模塊,主要用於輸出運行日誌,可以設置輸出日誌的等級、日誌保存路徑、日誌文件回滾等;相比 print,具備如下優點:

可以通過設置不同的日誌等級,在 release 版本中只輸出重要信息,而不必顯示大量的調試信息

print 將所有信息都輸出到標準輸出中,嚴重影響開發者從標準輸出中查看其它數據;logging 則可以由開發者決定將信息輸出到什麼地方,以及怎麼輸出

簡單配置:

importlogging

logging.debug( "debug log")

logging.info( "info log")

logging.warning( "warning log")

logging.error( "error log")

logging.critical( "critica log")

output

WARNING:root:warning log

ERROR:root:error log

CRITICAL:root:critica log

默認情況下,只顯示了大於等於WARNING級別的日誌。logging.basicConfig函數調整日誌級別、輸出格式等

96. 統計字符串中單詞出現次數fromcollections importCounter

str1 = "nihsasehndciswemeotpxc"

print(Counter(str1))

output

Counter({'s': 3, 'e': 3, 'n': 2, 'i': 2, 'h': 2, 'c': 2, 'a': 1, 'd': 1, 'w': 1, 'm': 1, 'o': 1, 't': 1, 'p': 1, 'x': 1})

97. 正則 re.complie 的作用

re.compile 是將正則表達式編譯成一個對象,加快速度,並重複使用

98. try except else finally 的意義

try..except..else 沒有捕獲到異常,執行 else 語句

try..except..finally 不管是否捕獲到異常,都執行 finally 語句

99.反轉列表

使用切片:

$ python -m timeit -n 1000000-s 'import numpy as np''mylist=list(np.arange(0, 200))''mylist[::-1]'

1000000loops, best of 5: 15.6usec per loop

使用 reverse:

$ python -m timeit -n 1000000-s 'import numpy as np''mylist=list(np.arange(0, 200))''mylist.reverse'

1000000loops, best of 5: 10.7usec per loop

這兩種方法都可以反轉列表,但需要注意的是內置函數 reverse 會更改原始列表,而切片方法會創建一個新列表。

顯然,內置函數 reverse 比列表切片方法更快!

100. 字符串中數字替換

使用 re 正則替換

importre

str1 = '我是周蘿蔔,今年18歲'

result = re.sub( r"\d+", "20",str1)

print(result)

output

我是周蘿蔔,今年20歲

綜合篇:網絡編程101. 簡述 OSI 七層協議

是網絡傳輸協議,人為的把網絡傳輸的不同階段劃分成不同的層次

七層劃分為:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層

五層劃分為:應用層、傳輸層、網絡層、數據鏈路層、物理層

物理層:網線,電纜等物理設備

數據鏈路層:Mac 地址

網絡層:IP 地址

傳輸層:TCP,UDP 協議

應用層:FTP 協議,Email,WWW 等

102. 三次握手、四次揮手的流程

都發生在傳輸層

三次握手:

第三次握手:主機 A 收到後檢查 ack number 是否正確,即第一次發送的 seq number+1,以及位碼 ack 是否為 1,若正確,主機 A 會再發送 ack number=(主機 B 的 seq+1),ack=1,主機 B 收到後確認 seq 值與 ack=1 則連接建立成功,兩個主機均進入 ESTABLISHED 狀態

以上完成三次握手,主機 A 與主機 B 開始傳送數據

四次揮手:

因為 TCP 連接是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務後就能發送一個 FIN 來終止這個方向的連接。收到一個 FIN 只意味著這一方向上沒有數據流動,一個 TCP 連接在收到一個 FIN 後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉

伺服器 A 發送一個 FIN,用來關閉 A 到伺服器 B 的數據傳送。伺服器 B 收到這個 FIN,它發回一個 ACK,確認序號為收到的序號加1。和 SYN 一樣,一個 FIN 將占用一個序號

伺服器 B 關閉與伺服器 A 的連接,發送一個 FIN 給伺服器 A

伺服器 A 發回 ACK 報文確認,並將確認序號設置為收到序號加1

103. 什麼是 C/S 和 B/S 架構

B/S 又稱為瀏覽器/伺服器模式。比如各種網站,jupyter notebook 等。優點:零安裝,維護簡單,共享性好。缺點:安全性較差,個性化不足

C/S 又稱為客戶端/伺服器模式。比如微信客戶端,Oracle 客戶端等。優點:安全性好,數據傳輸較快,穩定。缺點:對 PC 機作業系統等有要求,當客戶端較多時,伺服器端負載較大

104. TCP 和 UDP 的區別

TCP 和 UDP 都是 OSI 模型中運輸層的協議。TCP 提供可靠的通信傳輸,而 UDP 則常被用於廣播和細節控制交給應用的通信傳輸。UDP 不提供複雜的控制機制,利用 IP 提供面向無連接的通信服務。TCP 充分實現了數據傳輸時各種控制功能,可以進行丟包的重發控制,還可以對次序亂掉的分包進行順序控制

TCP 應用:FTP 傳輸,點對點簡訊等

UDP 應用:媒體流等

105. 區域網和廣域網

廣域網(WAN,Wide Area Network)也稱遠程網(long haul network )。通常跨接很大的物理範圍,所覆蓋的範圍從幾十公里到幾千公里,它能連接多個城市或國家,或橫跨幾個洲並能提供遠距離通信,形成國際性的遠程網絡

域網(Local Area Network,LAN)是指在某一區域內由多台計算機互聯成的計算機組。一般是方圓幾千米以內。區域網可以實現文件管理、應用軟體共享、印表機共享、工作組內的日程安排、電子郵件和傳真通信服務等功能。區域網是封閉型的,可以由辦公室內的兩台計算機組成,也可以由一個公司內的上千台計算機組成

106. arp 協議

ARP(Address Resolution Protocol)即地址解析協議, 用於實現從 IP 地址到 MAC 地址的映射,即詢問目標 IP 對應的 MAC 地址

107. 什麼是 socket?簡述基於 TCP 協議的套接字通信流程

socket 是對 TCP/IP 協議的封裝,它的出現只是使得程式設計師更方便地使用 TCP/IP 協議棧而已。socket 本身並不是協議,它是應用層與 TCP/IP 協議族通信的中間軟體抽象層,是一組調用接口(TCP/IP網絡的API函數)

「TCP/IP 只是一個協議棧,就像作業系統的運行機制一樣,必須要具體實現,同時還要提供對外的操作接口。 這個就像作業系統會提供標準的編程接口,比如win32編程接口一樣。TCP/IP 也要提供可供程式設計師做網絡開發所用的接口,這就是 Socket 編程接口。」

Server:

importsocket

importthreading

deftcplink(sock, addr):

print( 'Accept new connection from %s:%s...'% addr)

sock.send( b'Welcome!')

whileTrue:

data = sock.recv( 1024)

time.sleep( 1)

ifnotdata ordata.decode( 'utf-8') == 'exit':

break

sock.send(( 'Hello, %s!'% data.decode( 'utf-8')).encode( 'utf-8'))

sock.close

print( 'Connection from %s:%s closed.'% addr)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 監聽埠:

s.bind(( '127.0.0.1', 9999))

s.listen( 5)

print( 'Waiting for connection...')

whileTrue:

# 接受一個新連接:

sock, addr = s.accept

# 創建新線程來處理TCP連接:

t = threading.Thread(target=tcplink, args=(sock, addr))

t.start

Client:

importsocket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 建立連接:

s.connect(( '127.0.0.1', 9999))

# 接收歡迎消息:

print(s.recv( 1024).decode( 'utf-8'))

fordata in[ b'Michael', b'Tracy', b'Sarah']:

# 發送數據:

s.send(data)

print(s.recv( 1024).decode( 'utf-8'))

s.send( b'exit')

s.close

例子來源於廖雪峰的官網

108. 簡述 進程、線程、協程的區別以及應用場景

進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。每個進程都有自己的獨立內存空間,不同進程通過進程間通信來通信

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源

協程是一種用戶態的輕量級線程,協程的調度完全由用戶控制。協程擁有自己的寄存器上下文和棧

多進程:密集 CPU 任務,需要充分使用多核 CPU 資源(伺服器,大量的並行計算)的時候,用多進程。 缺陷:多個進程之間通信成本高,切換開銷大

多線程:密集 I/O 任務(網絡 I/O,磁碟 I/O,資料庫 I/O)使用多線程合適。缺陷:同一個時間切片只能運行一個線程,不能做到高並行,但是可以做到高並發

協程:又稱微線程,在單線程上執行多個任務,用函數切換,開銷極小。不通過作業系統調度,沒有進程、線程的切換開銷。缺陷:單線程執行,處理密集 CPU 和本地磁碟 IO 的時候,性能較低。處理網絡 I/O 性能還是比較高

多線程請求返回是無序的,哪個線程有數據返回就處理哪個線程,而協程返回的數據是有序的

109. 如何使用線程池和進程池

池的功能是限制啟動的進程數或線程數。當並發的任務數遠遠超過了計算機的承受能力時,即無法一次性開啟過多的進程數或線程數時,就應該用池的概念將開啟的進程數或線程數限制在計算機可承受的範圍內

多進程

frommultiprocessing importPool

importos

importtime

importrandom

deflong_time_task(name):

print( 'Run task %s (%s)...'% (name, os.getpid))

start = time.time

time.sleep(random.random * 3)

end = time.time

print( 'Task %s runs %0.2f seconds.'% (name, (end - start)))

deftest_pool:

print( 'Parent process %s.'% os.getpid)

p = Pool( 4)

fori inrange( 5):

p.apply_async(long_time_task, args=(i,))

print( 'Waiting for all subprocesses done...')

p.close

p.join

print( 'All subprocesses done.')

if__name__ == '__main__':

test_pool

output

Parent process 32432.

Waiting for all subprocesses done...

Run task 0 (15588)...

Run task 1 (32372)...

Run task 2 (12440)...

Run task 3 (18956)...

Task 2 runs 0.72 seconds.

Run task 4 (12440)...

Task 3 runs 0.82 seconds.

Task 1 runs 1.21 seconds.

Task 0 runs 3.00 seconds.

Task 4 runs 2.95 seconds.

All subprocesses done.

apply_async(func[, args[, kwds]]) :使用非阻塞方式調用 func(並行執行,堵塞方式必須等待上一個進程退出才能執行下一個進程),args 為傳遞給 func 的參數列表,kwds 為傳遞給 func 的關鍵字參數列表;close:關閉 Pool,使其不再接受新的任務;terminate:不管任務是否完成,立即終止;join:主進程阻塞,等待子進程的退出, 必須在 close 或 terminate 之後使用

也可以使用 concurrent.futures 模塊提供的功能來實現

deftest_future_process:

print( 'Parent process %s.'% os.getpid)

p = ProcessPoolExecutor( 4)

fori inrange( 5):

p.submit(long_time_task, i)

p.shutdown(wait= True)

print( 'Finish')

if__name__ == '__main__':

# test_pool

test_future_process

output

Parent process 29368.

Run task 0 (32148)...

Run task 1 (31552)...

Run task 2 (24012)...

Run task 3 (29408)...

Task 2 runs 0.52 seconds.

Run task 4 (24012)...

Task 3 runs 0.86 seconds.

Task 1 runs 1.81 seconds.

Task 0 runs 1.83 seconds.

Task 4 runs 1.69 seconds.

Finish

多線程

defsayhello(a):

print( "hello: "+ a)

start = time.time

time.sleep(random.random * 3)

end = time.time

print( 'Task %s runs %0.2f seconds.'% (a, (end - start)))

deftest_future_thread:

seed = [ "a", "b", "c", "d"]

start = time.time

withThreadPoolExecutor( 3) asexecutor:

fori inseed:

executor.submit(sayhello, i)

end = time.time

print( "Thread Run Time: "+ str(end - start))

output

hello: a

hello: b

hello: c

Task a runs 0.40 seconds.

hello: d

Task b runs 0.56 seconds.

Task d runs 1.70 seconds.

Task c runs 2.92 seconds.

Thread Run Time: 2.9195945262908936

可以看出,由於是創建了限制為3的線程池,所以只有三個任務在同時執行

110. 進程之間如何進行通信defwrite(q):

print( "write(%s), 父進程為(%s)"% (os.getpid, os.getppid))

fori in"Python":

print( "Put %s to Queue"% i)

q.put(i)

defread(q):

print( "read(%s), 父進程為(%s)"% (os.getpid, os.getppid))

fori inrange(q.qsize):

print( "read 從 Queue 獲取到消息: %s"% q.get( True))

deftest_commun:

print( "(%s) start"% os.getpid)

q = Manager.Queue

pw = Process(target=write, args=(q, ))

pr = Process(target=read, args=(q, ))

pw.start

pr.start

pw.join

pr.terminate

output

(23544) start

write(29856), 父進程為(23544)

Put P to Queue

Put y to Queue

Put t to Queue

Put h to Queue

Put o to Queue

Put n to Queue

read(25016), 父進程為(23544)

read 從 Queue 獲取到消息:P

read 從 Queue 獲取到消息:y

read 從 Queue 獲取到消息:t

read 從 Queue 獲取到消息:h

read 從 Queue 獲取到消息:o

read 從 Queue 獲取到消息:n

Python 的 multiprocessing 模塊包裝了底層的機制,提供了 Queue、Pipes 等多種方式來交換數據

111. 進程鎖和線程鎖

進程鎖:是為了控制同一作業系統中多個進程訪問一個共享資源,只是因為程序的獨立性,各個進程是無法控制其他進程對資源的訪問的,但是可以使用本地系統的信號量控制。信號量(Semaphore),有時被稱為信號燈,是在多線程環境下使用的一種設施,是可以用來保證兩個或多個關鍵代碼段不被並發調用

線程鎖:當多個線程幾乎同時修改一個共享數據的時候,需要進行同步控制,線程同步能夠保證多個線程安全的訪問競爭資源(全局內容),最簡單的同步機制就是使用互斥鎖。某個線程要更改共享數據時,先將其鎖定,此時資源的狀態為鎖定狀態,其他線程就能更改,直到該線程將資源狀態改為非鎖定狀態,也就是釋放資源,其他的線程才能再次鎖定資源。互斥鎖保證了每一次只有一個線程進入寫入操作。從而保證了多線程下數據的安全性

112. 什麼是並發和並行

並行:多個 CPU 核心,不同的程序就分配給不同的 CPU 來運行。可以讓多個程序同時執行

並發:單個 CPU 核心,在一個時間切片里一次只能運行一個程序,如果需要運行多個程序,則串行執行

113. threading.local 的作用

ThreadLocal 叫做線程本地變量,ThreadLocal 在每一個變量中都會創建一個副本,每個線程都可以訪問自己內部的副本變量,對其他線程時不可見的,修改之後也不會影響到其他線程

114. 什麼是域名解析

域名解析是指將域名解析為 IP 地址。也有反向的「逆解析」,將 IP 通過 DNS 伺服器查找到對應的域名地址

DNS 是域名系統 (Domain Name System),域名系統為網際網路上的主機分配域名地址和 IP 地址。用戶使用域名地址,該系統就會自動把域名地址轉為 IP 地址

115. LVS 是什麼及作用

LVS 是 Linux Virtual Server 的簡寫,意即 Linux 虛擬伺服器,是一個虛擬的伺服器集群系統,即負載均衡伺服器

LVS 工作模式分為 NAT 模式、TUN 模式、以及 DR 模式

116. Nginx 的作用

Nginx 主要功能:1、反向代理 2、負載均衡 3、HTTP 伺服器(包含動靜分離) 4、正向代理

正向代理:某些情況下,代理用戶去訪問伺服器,需要手動設置代理伺服器的 IP 和埠號

反向代理:是用來代理伺服器的,代理要訪問的目標伺服器。代理伺服器接受請求,然後將請求轉發給內部網絡的伺服器(集群化),並將從伺服器上得到的結果返回給客戶端,此時代理伺服器對外就表現為一個伺服器

負載均衡伺服器類似於 LVS HTTP 伺服器類似於 Tomcat 等

117. keepalived 及 HAProxy

HAProxy 提供高可用性、負載均衡,以及基於 TCP 和 HTTP 的應用程式代理。keepalived 是集群管理中保證集群高可用的一個服務軟體,其功能類似於 heartbeat,用來防止單點故障

118. 什麼是 rpc

RPC 是指遠程過程調用,也就是說兩台伺服器 A,B,一個應用部署在 A 伺服器上,想要調用 B 伺服器上應用提供的函數/方法,由於不在一個內存空間,不能直接調用,需要通過網絡來表達調用的語義和傳達調用的數據

119. 從瀏覽器輸入一個網址到展示網址頁面的過程

瀏覽器通過 DNS 伺服器查找到域名對應的 IP 地址

瀏覽器給 IP 對應的 web 伺服器發送 HTTP 請求

web 伺服器接收到 HTTP 請求後,返迴響應給瀏覽器

瀏覽器接收到響應後渲染頁面

120. 什麼是cdn

CDN 的全稱是 Content Delivery Network,即內容分髮網絡。CDN 是構建在網絡之上的內容分髮網絡,依靠部署在各地的邊緣伺服器,通過中心平台的負載均衡、內容分發、調度等功能模塊,使用戶就近獲取所需內容,降低網絡擁塞,提高用戶訪問響應速度和命中率。CDN 的關鍵技術主要有內容存儲和分發技術

綜合篇:資料庫和框架121. 列舉常見的資料庫

關係型資料庫:MySQL,Oracle,SQLServer,SQLite,DB2

非關係型資料庫:MongoDB,Redis,HBase,Neo4j

122. 資料庫設計三大範式

建立科學的,規範的的資料庫是需要滿足一些規範的,以此來優化數據數據存儲方式,在關係型資料庫中這些規範就可以稱為範式

第一範式:當關係模式 R 的所有屬性都不能在分解為更基本的數據單位時,稱 R 是滿足第一範式的,簡記為 1NF

關係模式R的所有屬性不能再分解

第二範式:如果關係模式 R 滿足第一範式,並且 R 的所有非主屬性都完全依賴於 R 的每一個候選關鍵屬性,稱 R 滿足第二範式,簡記為 2NF

非主屬性都要依賴於每一個關鍵屬性

三範式:設 R 是一個滿足第一範式條件的關係模式,X 是 R 的任意屬性集,如果 X 非傳遞依賴於 R 的任意一個候選關鍵字,稱 R 滿足第三範式,簡記為 3NF

數據不能存在傳遞關係,即每個屬性都跟主鍵有直接關係而不是間接關係

123. 什麼是資料庫事務

事務(Transaction)是並發控制的基本單位。所謂的事務,它是一個操作序列,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位

在關係數據庫中,一個事務可以是一條 SQL 語句、一組 SQL 語句或整個程序。四個屬性:原子性,一致性,隔離性和持久性

124. MySQL 索引種類

MySQL 目前主要有以下幾種索引類型:

  • 普通索引

  • 唯一索引

  • 主鍵索引

  • 組合索引

  • 全文索引

普通索引

唯一索引

主鍵索引

組合索引

全文索引

一對一關係示例:一個學生對應一個學生檔案材料,或者每個人都有唯一的身份證編號

一對多關係示例:一個學生只屬於一個班,但是一個班級有多名學生

多對多關係示例:一個學生可以選擇多門課,一門課也有多名學生

126. 簡述觸發器、函數、視圖、存儲過程

觸發器:觸發器是一個特殊的存儲過程,它是資料庫在 insert、update、delete 的時候自動執行的代碼塊

函數:資料庫中提供了許多內置函數,還可以自定義函數,實現 sql 邏輯

視圖:視圖是由查詢結果形成的一張虛擬表,是表通過某種運算得到的一個投影

存儲過程:把一段代碼封裝起來,當要執行這一段代碼的時候,可以通過調用該存儲過程來實現(經過第一次編譯後再次調用不需要再次編譯,比一個個執行 sql 語句效率高)

127. 常用 SQL 語句

DML(數據操作語言)

  • SELECT - 從資料庫表中獲取數據

  • UPDATE - 更新資料庫表中的數據

  • DELETE - 從資料庫表中刪除數據

  • INSERT INTO - 向資料庫表中插入數據

SELECT - 從資料庫表中獲取數據

UPDATE - 更新資料庫表中的數據

DELETE - 從資料庫表中刪除數據

INSERT INTO - 向資料庫表中插入數據

DDL(數據定義語言)

  • CREATE DATABASE - 創建新資料庫

  • ALTER DATABASE - 修改資料庫

  • CREATE TABLE - 創建新表

  • ALTER TABLE - 變更(改變)資料庫表

  • DROP TABLE - 刪除表

  • CREATE INDEX - 創建索引(搜索鍵)

  • DROP INDEX - 刪除索引

CREATE DATABASE - 創建新資料庫

ALTER DATABASE - 修改資料庫

CREATE TABLE - 創建新表

ALTER TABLE - 變更(改變)資料庫表

DROP TABLE - 刪除表

CREATE INDEX - 創建索引(搜索鍵)

DROP INDEX - 刪除索引

定義主鍵和外鍵主要是為了維護關係數據庫的完整性 主鍵是能確定一條記錄的唯一標識。不能重複,不允許為空

外鍵用於與另一張表關聯。是能確定另一張表記錄的欄位,用於保持數據的一致性

主鍵外鍵索引定義唯一標識一條記錄,不能重複,不允許為空表的外鍵是另一表的主鍵,外鍵可以重複,可以是空值該欄位沒有重複值,但可以有空值作用用來保證數據完整性用來和其他表建立聯繫提高查詢排序的速度個數只能有一個可有多個可有多個

129. 如何開啟 MySQL 慢日誌查詢

修改配置文件,然後重啟服務生效

在linux下,vim /etc/my.cnf,在[mysqld]內容項下增加:slow_query_log = ON long_query_time = 2 # 查詢超過2秒的就會記錄

命令行,但是重啟服務後會失效 SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 2;

130. MySQL 資料庫備份命令

mysqldump -u 用戶名 -p 資料庫名 > 導出的文件名

131. char 和 varchar 的區別

char:存儲定長數據很方便,CHAR 欄位上的索引效率級高,必須在括號里定義長度,可以有默認值,比如定義 char(10)

varchar:存儲變長數據,但存儲效率沒有 CHAR 高,必須在括號里定義長度,可以有默認值

132. 最左前綴原則

mysql 建立多列索引(聯合索引)有最左前綴的原則,即最左優先,如:

如果有一個2列的索引(col1,col2),則已經對(col1)、(col1,col2)上建立了索引

如果有一個3列索引(col1,col2,col3),則已經對(col1)、(col1,col2)、(col1,col2,col3)上建立了索引

133. 無法命中索引的情況

使用or關鍵字會導致無法命中索引

左前導查詢會導致無法命中索引,如 like '%a' 或者 like '%a%' 單列索引的索引列為 null 時全值匹配會使索引失效,組合索引全為 null 時索引失效

組合索引不符合左前綴原則的列無法命中索引,如我們有4個列 a、b、c、d,我們創建一個組合索引 INDEX(a,b,c,d),那麼能命中索引的查詢為 a,ab,abc,abcd,除此之外都無法命中索引

強制類型轉換會導致索引失效

負向查詢條件會導致無法使用索引,比如 NOT IN,NOT LIKE,!= 等 如果 mysql 估計使用全表掃描要比使用索引快,則不使用索引

134. 資料庫讀寫分離

讀寫分離,就是將資料庫分為了主從庫,一個主庫用於寫數據,多個從庫完成讀數據的操作,主從庫之間通過某種機制進行數據的同步,是一種常見的資料庫架構

135. 資料庫分庫分表

資料庫水平切分,是一種常見的資料庫架構,是一種通過算法,將資料庫進行分割的架構。一個水平切分集群中的每個資料庫,通常稱為一個「分片」。每一個分片中的數據沒有重合,所有分片中的數據並集組成全部數據。

水平切分分為庫內分表和分庫分表,是根據表內數據內在的邏輯關係,將同一個表按不同的條件分散到多個資料庫或多個表中,每個表中只包含一部分數據,從而使得單個表的數據量變小,達到分布式的效果

136. redis 和 memcached 比較

redis 和 memcached 都是將數據存放在內存中,都是內存資料庫。不過 memcached 還可用於緩存其他東西,例如圖片、視頻等等

redis 不僅僅支持簡單的 k/v 類型的數據,同時還提供 list,set,hash 等數據結構的存儲

分布式設定, 都可以做一主多從或一主一從

存儲數據安全,memcached 掛掉後,數據完全丟失;redis 可以定期保存到磁碟(持久化)

災難恢復,memcached 掛掉後,數據不可恢復; redis 數據丟失後可以通過 aof 恢復

137. redis中資料庫默認是多少個 db 及作用

redis 默認有16個資料庫,每個資料庫中的數據都是隔離的,這樣,在存儲數據的時候,就可以指定把不同的數據存儲到不同的資料庫中。且只有單機才有,如果是集群就沒有資料庫的概念

138. redis 有哪幾種持久化策略

RDB 持久化:是將 Reids 在內存中的資料庫記錄定時 dump 到磁碟上的持久化 AOF(append only file)持久化:將 Reids 的操作日誌以追加的方式寫入文件

139. redis 支持的過期策略

通用的三種過期策略

定時刪除 在設置 key 的過期時間的同時,為該 key 創建一個定時器,讓定時器在 key 的過期時間來臨時,對 key 進行刪除

惰性刪除 key 過期的時候不刪除,每次從資料庫獲取 key 的時候去檢查是否過期,若過期,則刪除,返回 null

定期刪除 每隔一段時間執行一次刪除過期 key 操作

redis 採用惰性刪除+定期刪除策略

140. 如何保證 redis 中的數據都是熱點數據

限定 Redis 占用的內存,Redis 會根據自身數據淘汰策略,加載熱數據到內存。所以,計算一下所有熱點數據大約占用的內存,然後設置一下 Redis 內存限制即可

141. Python 操作 redis

使用 redis 第三方庫來操作

importredis

# 創建一個 redis 連接池

defredis_conn_pool:

pool = redis.ConnectionPool(host= 'redis-host', port=redis-port,

decode_responses= True, password= 'redis-pwd')

r = redis.Redis(connection_pool=pool)

returnr

142. 基於 redis 實現發布和訂閱if__name__ == "__main__":

conn = redis.Redis(host= '',

port= 12143, password= '')

ps = conn.pubsub

ps.subscribe( 'chat') # 從 chat 訂閱消息

foritem inps.listen: # 監聽狀態:有消息發布了就拿過來

ifitem[ 'type'] == 'message':

print(item)

print(item[ 'channel'])

print(item[ 'data'])

發布者

if__name__ == "__main__":

number_list = [ '300033', '300032', '300031', '300030']

signal = [ '1', '-1', '1', '-1']

pool = redis.ConnectionPool(host= 'redis-12143.c8.us-east-1-3.ec2.cloud.redislabs.com', port= 12143,

decode_responses= True, password= 'pkAWNdYWfbLLfNOfxTJinm9SO16eSJFx')

r = redis.Redis(connection_pool=pool)

fori inrange(len(number_list)):

value_new = str(number_list[i]) + ' '+ str(signal[i])

print(value_new)

r.publish( "chat", value_new)

143. 如何高效的找到 redis 中的某個 KEYimportredis

con = redis.Redis

con.keys(pattern= 'key*') # *代表通配符

144. 基於 redis 實現先進先出、後進先出及優先級隊列classZhan:

def__init__(self,conn):

self.conn = conn

defpush(self,val):

self.conn.rpush( 'aaa',val)

defpop(self):

returnself.conn.rpop( 'aaa')

classDui:

def__init__(self,conn):

self.conn = conn

defpush(self,val):

self.conn.rpush( 'bbb',val)

defget(self):

returnself.conn.lpop( 'bbb')

classXu:

def__init__(self,conn):

self.conn = conn

defpush(self,val,count):

self.conn.zadd( 'ccc',val,count)

defget(self):

a = self.conn.zrange( 'ccc', 0, 0)[ 0]

self.conn.zrem( 'ccc', a)

returna

145. redis 如何實現主從複製

在從伺服器中配置 SLAVEOF 127.0.0.1 6380 # 主伺服器 IP,埠

146. 循環獲取 redis 中某個非常大的列表數據deflist_iter(name):

"""

自定義redis列表增量疊代

:param name: redis中的name,即:疊代name對應的列表

:return: yield 返回 列表元素

"""

list_count = r.llen(name)

forindex inxrange(list_count):

yieldr.lindex(name, index)

147. redis 中的 watch 的命令的作用

watch 用於在進行事務操作的最後一步也就是在執行 exec 之前對某個 key 進行監視,如果這個被監視的 key 被改動,那麼事務就被取消,否則事務正常執行

148. redis 分布式鎖

為 redis 集群設計的鎖,防止多個任務同時修改資料庫,其本質就是為集群中的每個主機設置一個會超時的字符串,當集群中有一半多的機器設置成功後就認為加鎖成功,直至鎖過期或解鎖不會有第二個任務加鎖成功

149. http 協議

超文本傳輸協議(HTTP,HyperText Transfer Protocol)是網際網路上應用最為廣泛的一種網絡協議。HTTP 是一個客戶端和伺服器端請求和應答的標準。客戶端是終端用戶,伺服器端是網站。一般由 HTTP 客戶端發起一個請求,建立一個到伺服器指定埠(默認是80埠)的 TCP 連接,HTTP 伺服器則在那個埠監聽客戶端發送過來的請求,並給與響應

150. uwsgi,uWSGI 和 WSGI 的區別

WSGI:全稱是 Web Server Gateway Interface,是一種描述 web server 如何與 web application 通信的規範。django,flask 等都遵循該協議

uwsgi:是伺服器和服務端應用程式的一種協議,規定了怎麼把請求轉發給應用程式和返回; uwsgi 是一種線路協議而不是通信協議,在此常用於在 uWSGI 伺服器與其他網絡伺服器的數據通信

uWSGI:是一個 Web 伺服器,它實現了 WSGI 協議、uwsgi、http 等協議。Nginx 中 HttpUwsgiModule 的作用是與 uWSGI 伺服器進行交換

151. HTTP 狀態碼

1xx: 信息

2xx:成功

3xx:重定向

4xx:客戶端錯誤

5xx:伺服器錯誤

152. HTTP常見請求方式

GET,POST,PUT,DELETE,PATCH 等

153. 響應式布局

響應式布局是 Ethan Marcotte 在2010年5月份提出的一個概念,簡而言之,就是一個網站能夠兼容多個終端——而不是為每個終端做一個特定的版本

154. 實現一個簡單的 AJAX 請求

AJAX 是一種在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。

AJAX = 異步 Java 和 XML

$( function( ) {

$( '#send').click( function( ) {

$.ajax({

type: "GET",

url: "test.json",

data: { username:$( "#username").val, content:$( "#content").val},

dataType: "json",

success: function( data) {

$( '#resText').empty; //清空resText裡面的所有內容

varhtml = '';

$.each(data, function( commentIndex, comment) {

html += '

'+ comment[ 'username']

+ ':

+ comment[ 'content']

+ '

';

});

$( '#resText').html(html);

}

});

});

});

155. 同源策略

同源策略限制了從同一個源加載的文檔或腳本如何與來自另一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制

如果兩個頁面的協議,埠(如果有指定)和主機都相同,則兩個頁面具有相同的源。我們也可以把它稱為「協議/主機/埠 tuple」,或簡單地叫做「tuple". ("tuple" ,「元」,是指一些事物組合在一起形成一個整體,比如(1,2)叫二元,(1,2,3)叫三元)

156. 什麼是 CORS

CORS 全稱是跨域資源共享(Cross-Origin Resource Sharing),是一種 AJAX 跨域請求資源的方式,支持現代瀏覽器

157. 什麼是 CSRF

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF

158. 前端實現輪詢、長輪詢

輪詢

varxhr = new;

setInterval( function( ) {

xhr.open( 'GET', '/user');

xhr.onreadystatechange = function( ) {

};

xhr.send;

}, 1000)

長輪詢

functionajax( ) {

varxhr = new;

xhr.open( 'GET', '/user');

xhr.onreadystatechange = function( ) {

ajax;

};

xhr.send;

}

159. 簡述 MVC 和 MTV

所謂 MVC 就是把 web 應用分為模型(M),控制器(C),視圖(V)三層,他們之間以一種插件似的,松耦合的方式連接在一起。模型負責業務對象與資料庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調用模型和視圖完成用戶的請求

Django 中的 MTV 模式:

Model(模型):負責業務對象與資料庫的對象(ORM)

Template(模版):負責如何把頁面展示給用戶

View(視圖):負責業務邏輯,並在適當的時候調用 Model 和 Template,本質上與 MVC 相同

160. 接口的冪等性

接口冪等性就是用戶對於同一操作發起的一次請求或者多次請求的結果是一致的,不會因為多次點擊而產生了副作用

161. Flask 框架的優勢

簡潔,輕巧,擴展性強,自由度高

162. 什麼是 ORM

ORM 的全稱是 Object Relational Mapping,即對象關係映射。它的實現思想就是將關係數據庫中表的數據映射成為對象,以對象的形式展現,這樣開發人員就可以把對資料庫的操作轉化為對這些對象的操作

163. PV、UV 的含義

PV:是(page view)訪問量,頁面瀏覽量或點擊量,衡量網站用戶訪問的網頁數量。在一定統計周期內用戶每打開或刷新一個頁面就記錄1次,多次打開或刷新同一頁面則瀏覽量累計

UV:是(Unique Visitor)獨立訪客,統計一段時間內訪問某站點的用戶數(以cookie為依據)

164. supervisor 的作用

supervisor 管理進程,是通過 fork/exec 的方式將這些被管理的進程當作 supervisor 的子進程來啟動,所以我們只需要將要管理進程的可執行文件的路徑添加到 supervisor 的配置文件中即可

165. 使用 ORM 和原生 SQL 的優缺點

優點:

  • 方便的使用面向對象,語句清晰

  • 有效的防止 SQL 注入

  • 方便動態構造語句,對於不同的表的相同操作採用多態實現更優雅;

  • 一定程度上方便重構數據層

  • 方便設置設置鉤子函數

方便的使用面向對象,語句清晰

有效的防止 SQL 注入

方便動態構造語句,對於不同的表的相同操作採用多態實現更優雅;

一定程度上方便重構數據層

方便設置設置鉤子函數

缺點:

  • 不太容易處理複雜查詢語句

  • 性能較直接用 SQL 差

不太容易處理複雜查詢語句

性能較直接用 SQL 差

Admin 組件:是對 model 中對應的數據表進行增刪改查提供的組件

model 組件:負責操作資料庫

form 組件:生成 HTML 代碼;數據有效性校驗;校驗信息返回並展示

ModelForm 組件:用於資料庫操作,也可用於用戶請求的驗證

167. 列舉 Django 中執行原生 sql 的方法

使用 execute 執行自定義的 SQL 直接執行 SQL 語句(類似於 pymysql 的用法)

fromdjango.db importconnection

cursor = connection.cursor

cursor.execute( "SELECT DATE_FORMAT(create_time, '%Y-%m') FROM blog_article;")

ret = cursor.fetchall

print(ret)

  • 使用 extra 方法:queryset.extra(select={"key": "原生的SQL語句"})

  • 使用 raw 方法

  • 執行原始 sql 並返回模型

  • 依賴於 model 模型,多用於查詢操作

使用 extra 方法:queryset.extra(select={"key": "原生的SQL語句"})

使用 raw 方法

執行原始 sql 並返回模型

依賴於 model 模型,多用於查詢操作

cookie 是保存在瀏覽器端的鍵值對,可以用來做用戶認證

sesseion 是將用戶的會話信息保存在服務端,key 值是隨機產生的字符串,value 值是 session 的內容,依賴於 cookie 將每個用戶的隨機字符串保存到用戶瀏覽器中

169. beautifulsoup 模塊的作用

BeautifulSoup 庫是解析、遍歷、維護「標籤樹」的功能庫

url = "http://www.baidu.com/"

request = requests.get(url)

html = request.content

soup = BeautifulSoup(html, "html.parser", from_encoding= "utf-8")

170. Selenium 模塊簡述

Selenium 是模擬操作瀏覽器的庫,可以根據我們的指令,讓瀏覽器自動加載頁面,獲取需要的數據,甚至頁面截屏,或者判斷網站上某些動作是否發生等

fromselenium importwebdriver

browser = webdriver.Chrome

browser.get( 'https://www.taobao.com')

print(browser.page_source) # browser.page_source 是獲取網頁的全部 html

browser.close

點這裡關注我,記得標星哦~

CDA課程諮詢

文章來源: https://twgreatdaily.com/zh-cn/c6b5e0d5146470da82c6f0ac272ca291.html