最近小編在逛各大博客網(wǎng)站的時(shí)候總是會(huì)看到這么一個(gè)問(wèn)題:Python 學(xué)到什么程度可以面試工作,程度這個(gè)詞,衡量起來(lái)總是很難去把握那么一個(gè)點(diǎn),小編在這給大家搜集了一些 Python 常見(jiàn)的面試題,如果你能夠掌握了那么你去找一個(gè)初級(jí) Python 開(kāi)發(fā)崗相信不是問(wèn)題。推薦好課:Python3 進(jìn)階、Python Django框架
一、基礎(chǔ)知識(shí)
1. 列出 5 個(gè)常用 Python 標(biāo)準(zhǔn)庫(kù)?
import os
import sys
import re
import math
import time
import datetime
import random
import threading
import multiprocessing
2. Python 的內(nèi)建數(shù)據(jù)類型有哪些?
int、float、complex # 數(shù)值型
bool # 布爾型
str # 字符串
list # 列表
tuple # 元組
dict # 字典
3. 簡(jiǎn)述 with 方法打開(kāi)處理文件幫我我們做了什么?
- with 語(yǔ)句適用于對(duì)資源進(jìn)行訪問(wèn)的場(chǎng)合,確保不管使用過(guò)程中是否發(fā)生異常都會(huì)執(zhí)行必要的清理操作,釋放資源,比如文件使用后自動(dòng)關(guān)閉、線程中鎖的自動(dòng)獲取和釋放等;
- with 語(yǔ)句即
上下文管理器
,在程序中用來(lái)表示代碼執(zhí)行過(guò)程中所處的前后環(huán)境。上下文管理器:含有__enter__
和__exit__
方法的對(duì)象就是上下文管理器。
- enter():在執(zhí)行 with 語(yǔ)句之前,首先執(zhí)行該方法,通常返回一個(gè)實(shí)例對(duì)象,如果 with 語(yǔ)句有 as 目標(biāo),則將對(duì)象賦值給 as 目標(biāo)。
- exit():在執(zhí)行 with 語(yǔ)句結(jié)束后,自動(dòng)調(diào)用__exit__()方法,用戶釋放資源,若此方法返回布爾值 True,程序會(huì)忽略異常。
- 使用環(huán)境:文件讀寫(xiě)、線程鎖的自動(dòng)釋放等。
with context_expression [as target(s)]:
with-body
這里 context_expression 要返回一個(gè)上下文管理器對(duì)象,該對(duì)象并不賦值給as子句中的 target(s),而是會(huì)將上下文管理器的__enter__() 方法的返回值賦值給target(s)。
4. Python 的可變和不可變數(shù)據(jù)類型?
- 不可變數(shù)據(jù)類型:即數(shù)據(jù)被創(chuàng)建之后,數(shù)據(jù)的值將不再發(fā)生改變,有數(shù)值、字符、元祖類型;
- 可變數(shù)據(jù)類型:數(shù)據(jù)別創(chuàng)建之后,數(shù)據(jù)的值可以發(fā)生變化,有列表、字典、集合類型。
import datetime
import time
print(time.time()) # 時(shí)間戳
print(time.strftime("%Y-%m-%d %H:%M:%S %w", time.localtime())) # 年月日時(shí)分秒
print(datetime.datetime.now()) # 年月日時(shí)分秒
6. 統(tǒng)計(jì)字符串每個(gè)單詞出現(xiàn)的次數(shù)。
def word_amount(sentence):
split_list = sentence.split()
dict_result = {}
for word_name in split_list:
if word_name not in dict_result.keys():
dict_result[word_name] = 1
else:
dict_result[word_name] += 1
return dict_result
if __name__ == '__main__':
sentence = "I can because i think i can"
dict_result = word_amount(sentence)
print(dict_result)
或者:
if __name__ == '__main__':
sentence = "I can because i think i can"
result = {word: sentence.split().count(word) for word in set(sentence.split())}
print(result)
或者:
from collections import Counter
if __name__ == '__main__':
sentence = "I can because i think i can"
counts = Counter(sentence.split())
print(counts)
7. 用 python 刪除文件和用 linux 命令刪除文件方法。
import os
os.remove("demo.txt")
8. 寫(xiě)一段自定義異常代碼?
class printException(Exception):
pass
def testRaise():
raise printException('printErr')
if __name__ == '__main__':
try:
testRaise()
except printException, e:
print e
9. 舉例說(shuō)明異常模塊中 try except else finally 的相關(guān)意義。
def read_filedata(file_name):
file_obj = ""
try:
# 需要檢測(cè)的異常代碼片段
file_obj = open(file_name, "r")
result_data = file_obj.read()
except IOError, e:
# 發(fā)生“IOError”異常進(jìn)行處理的代碼片段
file_obj = "文件不存在:"+ str(e)
else:
# 沒(méi)有引發(fā)“IOError”異常執(zhí)行的代碼片段,返回讀取到的數(shù)據(jù)
return result_data
finally:
# 不管有沒(méi)有引發(fā)錯(cuò)誤都會(huì)執(zhí)行的代碼片段,isinstance()用于判斷一個(gè)數(shù)據(jù)類型
if isinstance(file_obj, str):
return file_obj
elif isinstance(file_obj, file):
file_obj.close()
else:
return "未知錯(cuò)誤,請(qǐng)檢查您的代碼..."
if __name__ == '__main__':
result = read_filedata("abc.txt")
print(result)
10. 遇到 bug 如何處理?
- 首先查看報(bào)錯(cuò)信息,根據(jù)報(bào)錯(cuò)信息找到相應(yīng)代碼,通常一般的數(shù)據(jù)結(jié)構(gòu)或者算法錯(cuò)誤只要找到報(bào)錯(cuò)代碼就可以順利解決;
- 如果遇到暫時(shí)不能解決的錯(cuò)誤先不要慌,我們可以使用編譯器的 Debug 模式或者自己在代碼中加注斷點(diǎn)進(jìn)行代碼排查;
- 如果依然不能解決 bug,我們可以拷貝報(bào)錯(cuò)信息,在搜索引擎中進(jìn)行搜索。沒(méi)有人寫(xiě)代碼不出 bug,如果你在一個(gè) bug 上耗費(fèi)時(shí)間超過(guò)半小時(shí),可以與其他同事探討(注意節(jié)制,可能有些費(fèi)同事);
- 另辟蹊徑:方法總比困難多,在進(jìn)行快速開(kāi)發(fā)時(shí),我們應(yīng)該優(yōu)先實(shí)現(xiàn)功能而不是拘泥于運(yùn)行效率,所以遇到一些暫時(shí)不能解決的 BUG 可以考慮另外的實(shí)現(xiàn)方法。
二、語(yǔ)言特性
1. 談?wù)剬?duì) Python 的了解和其他語(yǔ)言的區(qū)別?
Python 是一門(mén)語(yǔ)法簡(jiǎn)潔優(yōu)美,功能強(qiáng)大無(wú)比,應(yīng)用領(lǐng)域非常廣泛,具有強(qiáng)大完備的第三方庫(kù)的一門(mén)強(qiáng)類型
的動(dòng)態(tài)
,可移植,可擴(kuò)展,可嵌入的解釋型
編程語(yǔ)言。
強(qiáng)類型語(yǔ)言、弱類型語(yǔ)言的區(qū)別:
- 如果語(yǔ)言經(jīng)常隱式地轉(zhuǎn)換變量的類型,那這個(gè)語(yǔ)言就是
弱類型語(yǔ)言
,如果很少會(huì)這樣做,那就是強(qiáng)類型語(yǔ)言
。Python 很少會(huì)隱式地轉(zhuǎn)換變量的類型,所以 Python 是強(qiáng)類型的語(yǔ)言。
- 強(qiáng)類型語(yǔ)言和弱類型原因其判斷的根本是是否會(huì)隱式進(jìn)行語(yǔ)言類型轉(zhuǎn)變。強(qiáng)類型原因在速度上可能略遜于弱類型語(yǔ)言,但是強(qiáng)類型定義語(yǔ)帶來(lái)的嚴(yán)謹(jǐn)性又避免了不必要的錯(cuò)誤。
- 強(qiáng)類型語(yǔ)言包括:Java、.net、Python、C++ 等語(yǔ)言。其中 Python 是動(dòng)態(tài)語(yǔ)言,是強(qiáng)類型定義語(yǔ)言,是類型安全的語(yǔ)言,Java 是靜態(tài)語(yǔ)言,是強(qiáng)類型定義語(yǔ)言,也是類型安全的語(yǔ)言;弱類型語(yǔ)言包括:VB,PHP,JavaScript 等語(yǔ)言。其中 VBScript 是動(dòng)態(tài)語(yǔ)言,是一種類型不安全的原因。
動(dòng)態(tài)語(yǔ)言、靜態(tài)語(yǔ)言的區(qū)別:
動(dòng)態(tài)類型語(yǔ)言
:動(dòng)態(tài)性語(yǔ)言是指在運(yùn)行期間才去做數(shù)據(jù)類型檢查的語(yǔ)言,也就是說(shuō)動(dòng)態(tài)類型語(yǔ)言編程時(shí),永遠(yuǎn)不用給任何變量指定數(shù)據(jù)類型,該語(yǔ)言會(huì)在第一次賦值給變量時(shí),在內(nèi)部將數(shù)據(jù)類型記錄下來(lái)**。Python 和 Ruby 就是一種典型的動(dòng)態(tài)類型語(yǔ)言,其他的各種腳本語(yǔ)言如 VBScript 也多少屬于動(dòng)態(tài)類型語(yǔ)言。
靜態(tài)類型語(yǔ)言
:靜態(tài)類型語(yǔ)言與動(dòng)態(tài)類則剛好相反,它的數(shù)據(jù)類型在編譯期間檢查,也就是說(shuō)在寫(xiě)程序時(shí)要聲明所有變量的數(shù)據(jù)類型,C/C++ 是靜態(tài)類型語(yǔ)言的典型代表,其他靜態(tài)語(yǔ)言還有 C#、Java 等。
- 對(duì)于動(dòng)態(tài)語(yǔ)言與靜態(tài)語(yǔ)言的區(qū)分,其根本在于數(shù)據(jù)類型是在運(yùn)行期間檢查還是在編譯期間檢查。
編譯型語(yǔ)言、解釋型語(yǔ)言的區(qū)別:
編譯型語(yǔ)言
:需要將一段程序直接翻譯成機(jī)器碼(對(duì)于 C/C++ 這種非跨平臺(tái)的語(yǔ)言)或者中間碼 (Java 這種跨平臺(tái)語(yǔ)言,需要虛擬機(jī)再將中間碼印射成機(jī)器碼)。一般需經(jīng)過(guò)編譯 (compile)、鏈接 (linker) 這兩個(gè)步驟。編譯是把源代碼編譯成機(jī)器碼,鏈接是把各個(gè)模塊的機(jī)器碼和依賴庫(kù)串連起來(lái)生成可執(zhí)行文件。
解釋型語(yǔ)言
:使用解釋器將源碼逐行解釋成機(jī)器碼并立即執(zhí)行,不會(huì)進(jìn)行整體性的編譯和鏈接處理,相比編譯型語(yǔ)言省了道工序。
- 一個(gè)像是吃飯等菜都上全了再開(kāi)動(dòng),一個(gè)像是吃火鍋,邊涮邊吃,時(shí)機(jī)不一樣。
- 解釋型語(yǔ)言的優(yōu)點(diǎn):跨平臺(tái)容易,只需提供特定平臺(tái)的解釋器;缺點(diǎn):每次運(yùn)行的時(shí)候都要解釋一遍,性能上不如編譯型語(yǔ)言。
2. 簡(jiǎn)述解釋型和編譯型編程語(yǔ)言?
可參考上一條的解釋內(nèi)容。
3. Python 的解釋器種類以及相關(guān)特點(diǎn)?
CPython
:官方版本的解釋器。這個(gè)解釋器是用C語(yǔ)言開(kāi)發(fā)的,所以叫 CPython。在命令行下運(yùn)行 python 就是啟動(dòng) CPython 解釋器。CPython 是使用最廣的 Python 解釋器。
IPython
:IPython 是基于 CPython 之上的一個(gè)交互式解釋器,也就是說(shuō),IPython 只是在交互方式上有所增強(qiáng),但是執(zhí)行 Python 代碼的功能和 CPython 是完全一樣的。CPython 用>>>作為提示符,而 IPython 用I n [序號(hào)]: 作為提示符。
PyPy
:它的目標(biāo)是執(zhí)行速度。PyPy 采用J IT 技術(shù),對(duì) Python 代碼進(jìn)行動(dòng)態(tài)編譯(注意不是解釋),所以可以顯著提高 Python 代碼的執(zhí)行速度。絕大部分 Python 代碼都可以在 PyPy 下運(yùn)行,但是 PyPy 和 CPython 有一些是不同的,這就導(dǎo)致相同的 Python 代碼在兩種解釋器下執(zhí)行可能會(huì)有不同的結(jié)果。
Jython
:Jython 是運(yùn)行在 Java 平臺(tái)上的 Python 解釋器,可以直接把 Python 代碼編譯成 Java 字節(jié)碼執(zhí)行。
IronPython
:IronPython 和 Jython 類似,只不過(guò) IronPython 是運(yùn)行在微軟 .Net 平臺(tái)上的 Python 解釋器,可以直接把Python 代碼編譯成 .Net 的字節(jié)碼。
4. 說(shuō)說(shuō)你知道的 Python3 和 Python2 之間的區(qū)別?
編碼
:Python2 的默認(rèn)編碼是 asscii,這也是導(dǎo)致 Python2 中經(jīng)常遇到編碼問(wèn)題的原因之一,至于是為什么會(huì)使用 asscii 作為默認(rèn)編碼,原因在于 Python 這門(mén)語(yǔ)言誕生的時(shí)候還沒(méi)出現(xiàn) Unicode。Python3 默認(rèn)采用了 UTF-8 作為默認(rèn)編碼,因此你不再需要在文件頂部寫(xiě) # coding=utf-8 了。
字符串
:Python2 中字符的類型,str:已經(jīng)編碼后的字節(jié)序列,unicode:編碼前的文本字符;而 Python3 中字符的類型,str:編碼過(guò)的 unicode 文本字符,bytes:編碼前的字節(jié)序列。
可以認(rèn)為字符串有兩種狀態(tài),即文本狀態(tài)和字節(jié)(二進(jìn)制)狀態(tài)。Python2 和 Python3 中的兩種字符類型都分別對(duì)應(yīng)這兩種狀態(tài),然后相互之間進(jìn)行編解碼轉(zhuǎn)化。編碼就是將字符串轉(zhuǎn)換成字節(jié)碼,涉及到字符串的內(nèi)部表示;解碼就是將字節(jié)碼轉(zhuǎn)換為字符串,將比特位顯示成字符。
在 Python2 中,str 和 unicode 都有 encode 和 decode 方法。但是不建議對(duì) str 使用 encode,對(duì) unicode 使用 decode, 這是Python2 設(shè)計(jì)上的缺陷。Python3 則進(jìn)行了優(yōu)化,str 只有一個(gè) encode 方法將字符串轉(zhuǎn)化為一個(gè)字節(jié)碼,而且 bytes 也只有一個(gè) decode 方法將字節(jié)碼轉(zhuǎn)化為一個(gè)文本字符串。
print
:Python2 中的 print 是語(yǔ)句;Python3 中的 print 是函數(shù)。例如:
>>> print("hello", "world")
('hello', 'world')
# py3
>>> print("hello", "world")
hello world
這個(gè)例子就比較明顯了,在 py2 中,print 語(yǔ)句后面接的是一個(gè)元組對(duì)象,而在 py3 中,print 函數(shù)可以接收多個(gè)位置參數(shù)。如果希望在 Python2 中把 print 當(dāng)函數(shù)使用,那么可以導(dǎo)入 future 模塊中的 print_function。
import
:python2 默認(rèn)是按照相對(duì)路徑導(dǎo)入模塊和包,python3 默認(rèn)則是按照絕對(duì)路徑導(dǎo)入。
input
:Python3:input 解析輸入為str字符型;Python2:input 解析輸入為int型,raw_input 解析輸入為 str 類型。
算法符
:在 Python2 中,/ 執(zhí)行傳統(tǒng)除法,對(duì)于整數(shù)執(zhí)行截?cái)喑?,浮點(diǎn)數(shù)執(zhí)行浮點(diǎn)除法(保留小數(shù)部分,即使整除);// 執(zhí)行 Floor 除法,截除掉余數(shù)并且針對(duì)整數(shù)操作數(shù)返回一個(gè)整數(shù),如果有任何一個(gè)操作數(shù)是浮點(diǎn)數(shù),則返回一個(gè)浮點(diǎn)數(shù)。在 Python3 中,/ 總是執(zhí)行真除法,不管操作數(shù)的類型,都會(huì)返回包含任何余數(shù)的浮點(diǎn)結(jié)果;// 執(zhí)行 Floor 除法,截除掉余數(shù)并且針對(duì)整數(shù)操作數(shù)返回一個(gè)整數(shù),如果有任何一個(gè)操作數(shù)是浮點(diǎn)數(shù),則返回一個(gè)浮點(diǎn)數(shù)。
int/long
:Python3 里,只有一種整數(shù)類型 int,大多數(shù)情況下,它很像 Python2 里的長(zhǎng)整型。Python2 有為非浮點(diǎn)數(shù)準(zhǔn)備的 int 和 long 類型。int 類型的最大值不能超過(guò) sys.maxint,而且這個(gè)最大值是平臺(tái)相關(guān)的。
True和False
:在 Python2 中,True 和 False 是兩個(gè)全局變量(名字),在數(shù)值上分別對(duì)應(yīng) 1 和 0,既然是變量,那么它們就可以指向其它對(duì)象。Python3 修正了這個(gè)缺陷,True 和 False 變?yōu)閮蓚€(gè)關(guān)鍵字,永遠(yuǎn)指向兩個(gè)固定的對(duì)象,不允許再被重新賦值。
迭代器
:在 Python2 中很多返回列表對(duì)象的內(nèi)置函數(shù)和方法在 Python3 都改成了返回類似于迭代器的對(duì)象,因?yàn)榈鞯亩栊约虞d特性使得操作大數(shù)據(jù)更有效率。
例如:Python2 中使用 xrange() 來(lái)創(chuàng)建一個(gè)迭代器對(duì)象,使用 range() 創(chuàng)建一個(gè) list 數(shù)組(要生成很大的數(shù)字序列的時(shí)候,用 xrange 會(huì)比 range 性能優(yōu)很多,因?yàn)椴恍枰簧蟻?lái)就開(kāi)辟一塊很大的內(nèi)存空間);Python3 中使用 range() 創(chuàng)建迭代器對(duì)象,移除了 xrange() 方法。
另外,字典對(duì)象的 dict.keys()、dict.values() 方法都不再返回列表,而是以一個(gè)類似迭代器的 view 對(duì)象返回。高階函數(shù) map、filter、zip 返回的也都不是列表對(duì)象了。Python2 的迭代器必須實(shí)現(xiàn) next 方法,而 Python3 改成了__iter__()、next。
nonlocal
:在 Python2 中可以在函數(shù)里面可以用關(guān)鍵字 global 聲明某個(gè)變量為全局變量,但是在嵌套函數(shù)中,想要給一個(gè)變量聲明為非局部變量是沒(méi)法實(shí)現(xiàn)的,在 Pyhon3,新增了關(guān)鍵字 nonlcoal,一般使用在閉包中的,使變量使用外層的同名變量。
LEGB
作用域的理解:python3 的 local, global, nonlocal 簡(jiǎn)析
5. Python3 和 Python2 中 int 和 long 區(qū)別?
可參考上一條的解釋內(nèi)容。
6. xrange 和 range 的區(qū)別?
可參考上上一條的解釋內(nèi)容。