非常全面的Python常見基礎面試題及答案
Python
1 Python垃圾回收機制是什麼
作為Python的使用者來說,Python中的垃圾回收主要以引用計數為主,再引入標記、清除,分代為輔來解決循環引用的問題。
一個對象被引用時,引用計數加1,當對象被del時,引用計數減去1,為0時,對象就被清除,一般情況下用戶不會去操作Python 的垃圾回收機制,但它留有API接口。
2 元組和列表的區別
主要區別是列表是可變的,而元組是不可變的。
>>> mylist=[1,3,3] >>> mylist[1]=2 >>> mytuple=(1,3,3) >>> mytuple[1]=2 Traceback (most recent call last): File "<pyshell#97>", line 1, in <module>
3 元組可以作為字典的key?
首先一個對象能不能作為字典的key, 就取決於其有沒有__hash__方法。 所以除瞭容器對象(list/dict/set)和內部包含容器對象的tuple 是不可作為字典的key, 其他的對象都可以。
4 進程 線程 協程
4.1 進程
1、操作系統進行資源分配和調度的基本單位,多個進程之間相互獨立
2、穩定性好,如果一個進程崩潰,不影響其他進程,但是進程消耗資源大,開啟的進程數量有限制
4.2 線程
1、CPU進行資源分配和調度的基本單位,線程是進程的一部分,是比進程更小的能獨立運行的基本單位,一個進程下的多個線程可以共享該進程的所有資源
2、如果IO操作密集,則可以多線程運行效率高,缺點是如果一個線程崩潰,都會造成進程的崩潰
4.3 協程
1、子程序調用總是一個入口,一次返回,調用順序是明確的。而協程的調用和子程序不同。
2、協程看上去也是子程序,但執行過程中,在子程序內部可中斷,然後轉而執行別的子程序,在適當的時候再返回來接著執行。
5 賦值、淺拷貝和深拷貝
深拷貝就是將一個對象拷貝到另一個對象中,這意味著如果你對一個對象的拷貝做出改變時,不會影響原對象。在Python中,我們使用函數deepcopy()執行深拷貝
淺拷貝則是將一個對象的引用拷貝到另一個對象上,所以如果我們在拷貝中改動,會影響到原對象
6 GIL
GIL是python的全局解釋器鎖,同一進程中假如有多個線程運行,一個線程在運行python程序的時候會霸占python解釋器(加瞭一把鎖即GIL),使該進程內的其他線程無法運行,等該線程運行完後其他線程才能運行。如果線程運行過程中遇到耗時操作,則解釋器鎖解開,使其他線程運行。所以在多線程中,線程的運行仍是有先後順序的,並不是同時進行。
多進程中因為每個進程都能被系統分配資源,相當於每個進程有瞭一個python解釋器,所以多進程可以實現多個進程的同時運行,缺點是進程系統資源開銷大
7 列表去重
先通過轉換為集合去重,在轉列表
8 最常用的排序算法及其復雜度
8.1 冒泡排序
外層循環從1到n-1,內循環從當前外層的元素的下一個位置開始,依次和外層的元素比較,出現逆序就交換,通過與相鄰元素的比較和交換來把小的數交換到最前面。
def bubbleSort(array): if len(array) < 2: return array else: isSorted = False counter = 0 while not isSorted: isSorted = True for idx in range(len(array) - 1 - counter): if array[idx] > array[idx + 1]: isSorted = False (array[idx + 1], array[idx]) = (array[idx], array[idx + 1]) counter += 1 return array
8.3 快速排序
通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。
1、選定Pivot中心軸
2、從R指針開始,將大於Pivot的數字放在Pivot的右邊
3、將小於Pivot的數字放在Pivot的左邊
4、分別對左右子序列重復前三步操作
def quickSort(array): print(array) if len(array) < 2: return array else: pivot_index = 0 pivot = array[pivot_index] less_part = [i for i in array[pivot_index+1:] if i <= pivot] large_part = [i for i in array[pivot_index+1:] if i > pivot] return quickSort(less_part) + [pivot] + quickSort(large_part)
9 閉包
函數的返回值是函數對象,隻有外部函數才可以對他進行訪問,提高瞭安全性
10 with
with語句的使用,可以簡化瞭代碼,有效避免資源泄露的發生
打開文件在進行讀寫的時候可能會出現一些異常狀況,如果按照常規的f.open
寫法,我們需要try,except,finally,做異常判斷,並且文件最終不管遇到什麼情況,都要執行finally f.close()關閉文件,with方法幫我們實現瞭finally中f.close
11 實例方法 靜態方法
實例方法隻能被實例調用,靜態方法(@由staticmethod裝飾器的方法)、類方法(由@classmethod裝飾器的方法),可以被類或類的實例對象調用。
1、實例方法,第一個參數必須要默認傳遞實例對象,一般使用self。
2、靜態方法,參數沒有必要。
3、類方法,第一個參數必須要默認傳遞,一般使用cls。
12 迭代器和生成器
12.1 迭代器
迭代器是一個可以記住遍歷的位置的對象。
迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器隻能往前不會後退。
迭代器有兩個基本的方法:iter() 和 next()。
字符串,列表或元組對象都可用於創建迭代器:
>>> list=[1,2,3,4] >>> it = iter(list) # 創建迭代器對象 >>> print (next(it)) # 輸出迭代器的下一個元素 1 >>> print (next(it)) 2 >>>
12.2 生成器
使用瞭yield的函數被稱為生成器
生成器是一個返回迭代器的函數,隻能用於迭代操作,更簡單點理解生成器就是一個迭代器
在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續運行
13 匿名函數
print [(lambda x:x*x)(x)for x in range(5)] [0, 1, 4, 9, 16, 25]
14 map reduce filter
14.1 map
對可迭代對象中的每個元素進行相同的操作
def fn(x): return x+1 resp = map(fn,li) print(list(resp)) [2, 3, 4]
14.2 reduce
從左到右對一個序列的項累計地應用有兩個參數的函數,以此合並序列到一個單一值。(例如累加或累乘列表元素等等)
from functools import reduce nums=[1, 2, 3, 4] def fn(x, y): return x * y resp = reduce(fn, nums) print(resp) 24
14.3 filter
filter函數用於過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。該接收兩個參數: 第一個為函數,第二個為序列,序列的每個元素作為參數傳遞給函數進行判,然後返回 True 或 False,最後將返回 True 的元素放到新列表
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def fn(a): return a%2 == 1 newlist = filter(fn, a) newlist = [i for i in newlist] print(newlist) ## 輸出: [1, 3, 5, 7, 9]
Django
1 什麼是wsgi
Python Web Server Gateway Interface,翻譯過來是Python web服務器網關接口,實際上就是一種協議,我們的應用(Django,Flask)實現瞭WSGI,就可以配合實現瞭WSGI(uWSGI,gunicorn)的服務器工作瞭
2 django請求的生命周期
- 前端發送請求
- wsgi, 他就是socket服務端,用於接收用戶請求並將請求進行初次封裝,然後將請求交給web框架(Flask、Django)
- 中間件處理請求,幫助我們對請求進行校驗或在請求對象中添加其他相關數據,例如:csrf、request.session
- 路由匹配,根據當前請求的URL找到視圖函數,如果是FBV寫法,通過判斷method兩類型,找到對應的視圖函數;如果是CBV寫法,匹配成功後會自動去找dispatch方法,然後Django會通過dispatch反射的方式找到類中對應的方法並執行
- 視圖函數,在視圖函數中進行業務邏輯的處理,可能涉及到:orm、view視圖將數據渲染到template模板
- 視圖函數執行完畢之後,會把客戶端想要的數據返回給dispatch方法,由dispatch方法把數據返回經客戶端
- 中間件處理響應
- wsgi,將響應的內容發送給瀏覽器
- 瀏覽器渲染
3 列舉django的內置組件
- Admin: 對model中對應的數據表進行增刪改查提供的組件
- model:負責操作數據庫
- form:1.生成HTML代碼 2.數據有效性校驗 3校驗信息返回並展示
- ModelForm: 即用於數據庫操作,也可用於用戶請求的驗證
4 列舉django中間件的5個方法?以及django中間件的應用場景
- process_request : 請求進來時,權限認證
- process_view : 路由匹配之後,能夠得到視圖函數
- process_exception : 異常時執行
- process_template_responseprocess : 模板渲染時執行
- process_response : 請求有響應時執行
5 簡述什麼是FBV和CBV
FBV和CBV本質是一樣的,基於函數的視圖叫做FBV,基於類的視圖叫做CBV
在python中使用CBV的優點:
- 提高瞭代碼的復用性,可以使用面向對象的技術,比如Mixin(多繼承)
- 可以用不同的函數針對不同的HTTP方法處理,而不是通過很多if判斷,提高代碼可讀性
6 django的request對象是在什麼時候創建的
class WSGIHandler(base.BaseHandler): request = self.request_class(environ)
請求走到WSGIHandler類的時候,執行cell方法,將environ封裝成瞭request
7 如何在CBV添加裝飾器
7.1 方法
from django.utils.decorators import method_decorator @method_decorator(check_login) def post(self, request): ...
7.2 dispatch
@method_decorator(check_login) def dispatch(self, request, *args, **kwargs):
7.3 類
@method_decorator(check_login, name="get") @method_decorator(check_login, name="post") class HomeView(View): ...
8 列舉django orm 中所有的方法
<1> all(): 查詢所有結果
<2> filter(**kwargs): 它包含瞭與所給篩選條件相匹配的對象。獲取不到返回None
<3> get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且隻有一個。
如果符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
<4> exclude(**kwargs): 它包含瞭與所給篩選條件不匹配的對象
<5> order_by(*field): 對查詢結果排序
<6> reverse(): 對查詢結果反向排序
<8> count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。
<9> first(): 返回第一條記錄
<10> last(): 返回最後一條記錄
<11> exists(): 如果QuerySet包含數據,就返回True,否則返回False
<12> values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後得到的
並不是一系 model的實例化對象,而是一個可迭代的字典序列
<13> values_list(*field): 它與values()非常相似,它返回的是一個元組序列,values返回的是一個字典序列
<14> distinct(): 從返回結果中剔除重復紀錄
9 select_related 和 prefetch_related的區別
有外鍵存在時,可以很好的減少數據庫請求的次數,提高性能
select_related 通過多表 join 關聯查詢, 一次性獲得所有數據, 隻執行一次SQL查詢
prefetch_related 分別查詢每個表, 然後根據它們之間的關系進行處理, 執行兩次查詢
10 django 中 csrf 的實現機制
第一步:django第一次響應來自某個客戶端的請求時,後端隨機產生一個token值,把這個token保存在SESSION狀態中;同時,後端把這個token放到cookie中交給前端頁面;
第二步:下次前端需要發起請求(比如發帖)的時候把這個token值加入到請求數據或者頭信息中,一起傳給後端;Cookies:{csrftoken:xxxxx}
第三步:後端校驗前端請求帶過來的token和SESSION裡的token是否一致。
11 django中如何實現orm表中添加數據時創建一條日志記錄
# 使用Django的信號機制,可以在添加、刪除數據前後設置日志記錄: pre_init # Django中的model對象執行其構造方法前,自動觸發 post_init # Django中的model對象執行其構造方法後,自動觸發 pre_save # Django中的model對象保存前,自動觸發 post_save # Django中的model對象保存後,自動觸發 pre_delete # Django中的model對象刪除前,自動觸發 post_delete # Django中的model對象刪除後,自動觸發 # 使用 @receiver(post_save, sender=Myclass) # 信號接收裝飾器。由於內置信號,所以直接接收 def signal_handler(sender, **kwargs): # 接收到信號後,在此處理 logger = logging.getLogger() logger.success('保存成功')
12 django緩存如何設置
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 緩存後臺使用的引擎 'TIMEOUT': 300, # 緩存超時時間(默認300秒,None表示永不過期,0表示立即過期) 'OPTIONS':{ 'MAX_ENTRIES': 300, # 最大緩存記錄的數量(默認300) 'CULL_FREQUENCY': 3, # 緩存到達最大個數之後,剔除緩存個數的比例,即:1/CULL_FREQUENCY(默認3) }, } }
13 django的緩存能使用redis嗎?如果可以的話,如何配置
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} # "PASSWORD": "密碼", } } }
14 django路由系統中name的作用
主要是通過name的值,來查找url地址,可以理解為反射作用。在html模板中使用name來反射url優勢就是後期url規則發生改變之後,隻需調整urls.py即可,所有的模板文件都不需要修改。
15 django rest framework框架中都有那些組件
- 認證
- 權限(授權)
- 用戶訪問次數/頻率限制
- 版本
- 解析器(parser)
- 序列化
- 分頁
- 路由系統
- 視圖
- 渲染器
16 簡述 django rest framework框架的認證流程
- 當用戶進行登錄的時候,運行瞭登錄類的as_view()方法,進入瞭APIView類的dispatch方法
- 執行self.initialize_request這個方法,裡面封裝瞭request和認證對象列表等其他參數
- 執行self.initial方法中的self.perform_authentication,裡面運行瞭user方法
- 再執行瞭user方法裡面的self._authenticate()方法
總結
到此這篇關於Python常見基礎面試題及答案的文章就介紹到這瞭,更多相關Python基礎面試題內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Django框架CBV裝飾器中間件auth模塊CSRF跨站請求問題
- Python Flask請求擴展與中間件相關知識總結
- Django中間件整合Vue攔截器的使用
- Django的基本運用之Django垃圾分類詳解
- Python Django ORM連表正反操作技巧