文章目錄
- 基礎知識題
- 看程序寫結果題
- 編程題
以下是總結的一些常見的Python基礎面試題,幫助大家回顧基礎知識,了解面試套路。會一直保持更新狀態。
PS:加粗為需要注意的點。
基礎知識題
1、深拷貝和淺拷貝的區別是什么?
深拷貝是將對象本身復制給另一個對象。這意味著如果對對象的副本進行更改時不會影響原對象。
淺拷貝是將對象的引用復制給另一個對象。因此,如果我們在副本中進行更改,則會影響原對象。
**2、能否解釋一下 *args 和 kwargs?
如果我們不知道將多少個參數傳遞給函數,比如當我們想傳遞一個列表或一個元組值時,就可以使用*args。
當我們不知道將會傳入多少關鍵字參數時,使用**kwargs 會收集關鍵字參數。
2.1、arg和 *kwarg作用?
萬能參數,解決了函數參數不固定的問題
*arg:會把位置參數轉化為tuple(非鍵值對的參數組)
**kwarg:會把關鍵字參數轉化為dict(鍵值對參數組)
3、Python和Java、PHP、C、C#、C++等其他語言的對比?
- python代碼,簡介,明確,優雅,簡單易懂
- 開發效率高
- 可擴展性強
4、簡述解釋型和編譯型編程語言?
解釋型:在執行程序時,計算機才一條一條的將代碼解釋成機器語言給計算機來執行
編譯型:是把源程序的每一條語句都編譯成機器語言,并保存成二進制文件,這樣計算機運行該程序時可以直接以機器語言來運行此程序,運行速度很快。
5、Python解釋器種類以及特點?(知道即可)
Cpython,IPython,Jpython,pypy,Ironpython
Python是一門解釋器語言,代碼想運行,必須通過解釋器執行,Python存在多種解釋器,分別基于不同語言開發,每個解釋器有不同的特點,但都能正常運行Python代碼,以下是常用的五種Python解釋器:
CPython:當 從Python官方網站下載并安裝好Python2.7后,就直接獲得了一個官方版本的解釋器:Cpython,這個解釋器是用C語言開發的,所以叫 CPython,在命名行下運行python,就是啟動CPython解釋器,CPython是使用最廣的Python解釋器。
IPython:IPython是基于CPython之上的一個交互式解釋器,也就是說,IPython只是在交互方式上有所增強,但是執行Python代碼的功能和CPython是完全一樣的,好比很多國產瀏覽器,雖然外觀不同,但內核其實是調用了IE。
PyPy:PyPy是另一個Python解釋器,它的目標是執行速度,PyPy采用JIT技術,對Python代進行動態編譯,所以可以顯著提高Python代碼的執行速度。
Jython:Jython是運行在Java平臺上的Python解釋器,可以直接把Python代碼編譯成Java字節碼執行。
IronPython:IronPython和Jython類似,只不過IronPython是運行在微軟.Net平臺上的Python解釋器,可以直接把Python代碼編譯成.Net的字節碼。
在Python的解釋器中,使用廣泛的是CPython,對于Python的編譯,除了可以采用以上解釋器
進行編譯外,技術高超的開發者還可以按照自己的需求自行編寫Python解釋器來執行Python代碼,十分的方便!
6、位和字節的關系?
一個字節=8位
7、b、B、KB、MB、GB 的關系?
1B(字節) = 8b(位)
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
8、請至少列舉5個 PEP8 規范(知道)
- 縮進:每一級4個縮進。連續跨行應該使用圓括號或大括號或者使用懸掛縮進。
- 代碼長度約束
一行列數:PEP8 規定最大為79列,如果拼接url很容易超限
一個函數:不可以超過30行;直觀來講就是完整顯示一個函數一個屏幕就夠了,不需要上下拖動 一個類:不要超過200行代碼,不要超過10個方法
一個模塊:不要超過500行 - import
不要在一句import中引用多個庫 - 命名規范
- 注釋
總體原則,錯誤的注釋不如沒有注釋。所以當一段代碼發生變化時,第一件事就是要修改注釋!
9、通過代碼實現如下轉換(知道即可)
二進制轉換成十進制:v = “0b1111011”
print(int('0b1111011',2))
十進制轉換成二進制:v = 18
print(bin(18))
八進制轉換成十進制:v = “011”
print(int('011',8))
十進制轉換成八進制:v = 30
print(oct(30))
十六進制轉換成十進制:v = “0x12”
print(int('0x12',16))
十進制轉換成十六進制:v = 87
print(hex(87))
10、ascii、unicode、utf-8、gbk 區別?(知道即可)
- ASCII碼:使用一個字節編碼,所以它的范圍基本是只有英文字母、數字和一些特殊符號 ,只有256個字符。
- Unicode:能夠表示全世界所有的字節
- GBK:是只用來編碼漢字的,GBK全稱《漢字內碼擴展規范》,使用雙字節編碼。
- UTF-8:是一種針對Unicode的可變長度字符編碼,又稱萬國碼。
11、列舉 Python2和Python3的區別?
- 默認編碼:2–>ascii,3–>utf-8
- print的區別:python2中print是一個語句,不論想輸出什么,直接放到print關鍵字后面即可。python3里,print()是一個函數,像其他函數一樣,print()需要你將要輸出的東西作為參數傳給它。
- input的區別:
python2有兩個全局函數,用在命令行請求用戶輸入。第一個叫input(),它等待用戶輸入一個python表達式(然后返回結果)。
第二個叫做raw_input(),用戶輸入什么他就返回什么。 python3 通過input替代了他們。 - 字符串:python2中有兩種字符串類型:Unicode字符串和非Unicode字符串。Python3中只有一種類型:Unicode字符串。
- xrange()
python2里,有兩種方法獲得一定范圍內的數字:range(),返回一個列表,還有xrange(),返回一個迭代器。
python3 里,range()返回迭代器,xrange()不再存在。
12、xrange和range的區別?
python2里,有兩種方法獲得一定范圍內的數字:range(),返回一個列表,還有xrange(),返回一個迭代器。
python3 里,range()返回迭代器,xrange()不再存在。
13、文件操作時:xreadlines和readlines的區別?
readlines返回一個list,xreadlines方法返回一個生成器
14、字符串、列表、元組、字典每個常用的5個方法?
字符串:repleace,strip,split,upper,lower,join,find,index…
replace(old, new [, max])
把將字符串中的 str1 替換成 str2,如果 max 指定,則替換不超過 max 次。
strip([chars])#去空格及特殊符號
在字符串上執行 lstrip()和 rstrip()
s.strip().lstrip().rstrip(',')
split(str="", num=string.count(str))
num=string.count(str)) 以 str 為分隔符截取字符串,如果 num 有指定值,則僅截取 num+1 個子字符串
join(seq)
以指定字符串作為分隔符,將 seq 中所有的元素(的字符串表示)合并為一個新的字符串
find(str, beg=0 end=len(string))
檢測 str 是否包含在字符串中,如果指定范圍 beg 和 end ,則檢查是否包含在指定范圍內,如果包含返回開始的索引值,否則返回-1
index(str, beg=0, end=len(string))
跟find()方法一樣,只不過如果str不在字符串中會報一個異常.
sStr1 = 'strchr'
sStr2 = 's'
nPos = sStr1.index(sStr2)
print nPos
列表:append,pop,insert,remove,reverse,sort,count,index…
增:
list.append(obj)
在列表末尾添加新的對象
list.insert(index, obj)
將對象插入列表
刪:
list.pop([index=-1])
移除列表中的一個元素(默認最后一個元素),并且返回該元素的值
list.remove(obj)
移除列表中某個值的第一個匹配項
改:
list.reverse()
反向列表中元素
#將字符串反轉
st=List(s)
result=“”.join(st.reverse())
查:
list.sort(cmp=None, key=None, reverse=False)
對原列表進行排序
list.count(obj)
統計某個元素在列表中出現的次數
元組:index,count,len(),dir()
元組不可更改所以只能查
查:
max(tuple)
返回元組中元素最大值。
字典:get,keys,values,pop,popitems,clear,update,items…
查:
radiansdict.get(key, default=None)
返回指定鍵的值,如果值不在字典中返回default值
radiansdict.keys()
返回一個迭代器,可以使用 list() 來轉換為列表
radiansdict.values()
返回一個迭代器,可以使用 list() 來轉換為列表
radiansdict.items()
以列表返回可遍歷的(鍵, 值) 元組數組
刪:
pop(key[,default])
刪除字典給定鍵 key 所對應的值,返回值為被刪除的值。key值必須給出。 否則,返回default值
popitem()
隨機返回并刪除字典中的一對鍵和值(一般刪除末尾對)
radiansdict.clear()
刪除字典內所有元素
改:
radiansdict.update(dict2)
把字典dict2的鍵/值對更新到dict里
直接增/改
dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
dict['Age'] = 8; # 更新 Age
dict['School'] = "菜鳥教程" # 添加信息
print ("dict['Age']: ", dict['Age'])
print ("dict['School']: ", dict['School'])
15、lambda表達式格式以及應用場景?
lambda函數賦值給其他函數
表達式格式:lambda后面跟一個或多個參數,緊跟一個冒號,以后是一個表達式。冒號前是參數,冒號后是返回值。例如:lambda x : 2x
**應用場景:**經常與一些內置函數相結合使用,比如說map(),filter(),sorted(),reduce()等
frame.applymap(lambda x: '%.2f' % x)
frame.apply(lambda x: x.max() - x.min())
16、Pandas 中map, applymap and apply的區別
- apply()是一種讓函數作用于列或者行(一維向量)操作(重點:選取數據的某行或者列)
- applymap()是一種讓函數作用于DataFrame每一個元素的操作(選取的是所有數據即Dataframe)
- map是一種讓函數作用于Series每一個元素的操作(數據選取的是某行或某列(即Series),然后對其中的每個元素進行操作)
總結:要對數據進行應用函數時,先看數據結構是DataFrame還是Series,Series結構直接用map(),DataFrame結構的話再看是要按行還是按列進行操作來選擇對應的函數即可。重點還是取決于數據源是什么數據結構,然后你想做什么樣的操作。
map(function, iterable, …)
map()函數接收兩個參數,一個是函數,一個是可迭代的對象,map將傳入的函數依次作用到序列的每個元素,并把結果作為新的list返回。
基本等價于 [f(x) for x in interable]
17、pass的作用?
- 空語句 do nothing
- 保證格式完整
- 保證語義完整
18、is和==的區別?
is:判斷內存地址是否相等
==:判斷數值是否相等
19、Python垃圾回收機制?(知道即可)
python采用的是引用計數機制為主,標記-清除和分代收集(隔代回收、分代回收)兩種機制為輔的策略
計數機制
Python的GC模塊主要運用了引用計數來跟蹤和回收垃圾。在引用計數的基礎上,還可以通過“標記-清除”解決容器對象可能產生的循環引用的問題。通過分代回收以空間換取時間進一步提高垃圾回收的效率。
標記-清除:
標記-清除的出現打破了循環引用,也就是它只關注那些可能會產生循環引用的對象
缺點:該機制所帶來的額外操作和需要回收的內存塊成正比。
隔代回收
原理:將系統中的所有內存塊根據其存活時間劃分為不同的集合,每一個集合就成為一個“代”,垃圾收集的頻率隨著“代”的存活時間的增大而減小。也就是說,活得越長的對象,就越不可能是垃圾,就應該減少對它的垃圾收集頻率。那么如何來衡量這個存活時間:通常是利用幾次垃圾收集動作來衡量,如果一個對象經過的垃圾收集次數越多,可以得出:該對象存活時間就越長。
20、python的可變類型和不可變類型?
數據字符串賦新值時,只是開辟了新的空間創建了一個新值,并未更改舊值。
不可變類型(數字、字符串、元組、不可變集合)
可變類型(列表、字典、可變集合)
21、列舉常見的內置函數?
map,filter(當返回值為正數時才返回函數結果進入下個元素的計算),zip,len,bin,oct,hex,int,float,bool,sum,min,max,str,list,tuple,dict,range,next,hash,help,id…
enumerate,reduce,eval,format
map() 會根據提供的函數對指定序列做映射。
第一個參數 function 以參數序列中的每一個元素調用 function 函數,返回包含每次 function 函數返回值的新列表。
map(function, iterable, …)
參數
? function – 函數
? iterable – 一個或多個序列
返回值
Python 2.x 返回列表。
Python 3.x 返回迭代器。
迭代器是訪問集合元素的一種方式。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會后退。
>>>def square(x) : # 計算平方數
... return x ** 2 ...
>>> map(square, [1,2,3,4,5]) # 計算列表各個元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函數
[1, 4, 9, 16, 25]
# 提供了兩個列表,對相同位置的列表數據進行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
filter() 函數用于過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。
該接收兩個參數,第一個為函數,第二個為序列,序列的每個元素作為參數傳遞給函數進行判,然后返回 True 或 False,最后將返回 True 的元素放到新列表中。
參數
? function – 判斷函數。
? iterable – 可迭代對象。
返回值
返回列表。
def is_odd(n):
return n % 2 == 1
newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(newlist)
輸出結果 :
[1, 3, 5, 7, 9]
zip() 函數用于將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。
如果各個迭代器的元素個數不一致,則返回列表長度與最短的對象相同,利用 * 號操作符,可以將元組解壓為列表。
zip 語法:
zip([iterable, …])
參數說明:
? iterabl – 一個或多個迭代器;
返回值
返回元組列表。
>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包為元組的列表 [(1, 4), (2, 5), (3, 6)]
>>> zip(a,c) # 元素個數與最短的列表一致 [(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped) # 與 zip 相反,*zipped 可理解為解壓,返回二維矩陣式 [(1, 2, 3), (4, 5, 6)]
bin() 返回一個整數 int 或者長整數 long int 的二進制表示.
參數
x – int 或者 long int 數字
返回值
字符串。
>>>bin(10)
'0b1010'
>>> bin(20)
'0b10100'
oct() 函數將一個整數轉換成8進制字符串。
>>>oct(10)
'012'
>>> oct(20)
'024'
>>> oct(15)
'017'
>>>
hex() 函數用于將10進制整數轉換成16進制,以字符串形式表示。
>>>hex(255)
'0xff'
>>> hex(-42)
'-0x2a'
>>> hex(1L)
'0x1L'
>>> hex(12)
'0xc'
>>> type(hex(12))
<class 'str'> # 字符串
hash() 用于獲取取一個對象(字符串或者數值等)的哈希值。
hash 語法:
hash(object)
參數說明:
? object – 對象;
返回值
返回對象的哈希值。
>>>hash('test') # 字符串
2314058222102390712
>>> hash(1) # 數字
1
>>> hash(str([1,2,3])) # 集合
1335416675971793195
>>> hash(str(sorted({'1':1}))) # 字典
7666464346782421378
>>
enumerate(sequence, [start=0])
enumerate() 函數用于將一個可遍歷的數據對象(如列表、元組或字符串)組合為一個索引序列,同時列出數據和數據下標,一般用在 for 循環當中。
參數
sequence – 一個序列、迭代器或其他支持迭代對象。
start – 下標起始位置。
返回值
返回 enumerate(枚舉) 對象。
for 循環使用 enumerate
>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
... print i, element
...
0 one
1 two
2 three
eval(expression[, globals[, locals]])
eval() 函數用來執行一個字符串表達式,并返回表達式的值。
參數
? expression – 表達式。
? globals – 變量作用域,全局命名空間,如果被提供,則必須是一個字典對象。
? locals – 變量作用域,局部命名空間,如果被提供,可以是任何映射對象。
返回值
返回表達式計算結果。
>>>x = 7
>>> eval( '3 * x' )
21
>>> eval('pow(2,2)')
4
str.format()
格式化字符串的函數 str.format(),它增強了字符串格式化的功能。
基本語法是通過 {} 和 : 來代替以前的 % 。
format 函數可以接受不限個參數,位置可以不按順序。
實例
>>>"{} {}".format("hello", "world") # 不設置指定位置,按默認順序 'hello world' >>> "{0} {1}".format("hello", "world") # 設置指定位置 'hello world'
>>> "{1} {0} {1}".format("hello", "world") # 設置指定位置 'world hello world'
reduce(function, iterable[, initializer])
reduce() 函數會對參數序列中元素進行累積。
函數將一個數據集合(鏈表,元組等)中的所有數據進行下列操作:用傳給 reduce 中的函數 function(有兩個參數)先對集合中的第 1、2 個元素進行操作,得到的結果再與第三個數據用 function 函數運算,最后得到一個結果。
參數
? function – 函數,有兩個參數
? iterable – 可迭代對象
? initializer – 可選,初始參數
返回值
返回函數計算結果。
實例
以下實例展示了 reduce() 的使用方法:
>>>def add(x, y) : # 兩數相加
... return x + y ...
>>> reduce(add, [1,2,3,4,5]) # 計算列表和:1+2+3+4+5
15
>>> reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函數
15
class set([iterable])
set() 函數創建一個無序不重復元素集,可進行關系測試,刪除重復數據,還可以計算交集、差集、并集等。
參數說明:
? iterable – 可迭代對象對象;
返回值
返回新的集合對象。
實例
以下實例展示了 set 的使用方法:
>>>x = set('runoob')
>>>y = set('google')
>>> x, y
(set(['b', 'r', 'u', 'o', 'n']), set(['e', 'o', 'g', 'l'])) # 重復的被刪除
>>> x & y # 交集
set(['o'])
>>> x | y # 并集
set(['b', 'e', 'g', 'l', 'o', 'n', 'r', 'u'])
>>> x - y # 差集
set(['r', 'b', 'u', 'n'])
>>>
22、filter、map、reduce的作用?
- filter(function,iterable)過濾函數
map(function,iterable)循環函數
reduce(function, iterable)累積函數
23、如何安裝第三方模塊?以及用過哪些第三方模塊?
pip3 install 模塊名
24、至少列舉8個常用模塊都有那些?
os,sys,time,random,re,hashlib,logging,json,pickle…
- os模塊提供了不少與操作系統相關聯的函數.
- sys通用工具腳本經常調用命令行參數.
- re模塊為高級字符串處理提供了正則表達式工具。對于復雜的匹配和處理,正則表達式提供了簡潔、優化的解決方案:
- random提供了生成隨機數的工具。
- re的match和search區別?
- match:從字符串的開頭位置匹配,必須以此為開頭
- search:從開頭開始查,找到符合的就返回結果
25、如何實現 “1,2,3” 變成 [‘1’,‘2’,‘3’] ?
a = "1,2,3"
list = a.split(",")
print(list)
26、如何實現[‘1’,’2’,’3’]變成[1,2,3] ?
li = ['1','2','3']
series = pd.Series(li)
series=list(series.map(lambda x:int(x)))
print(series)
27、比較: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的區別?
a = [1,2,3]正常的列表
b = [(1),(2),(3)] 雖然列表的每個元素加上了括號,但是當括號內只有一個元素并且沒有逗號時,其數據類型是元素本身的數據類型
b = [(1,),(2,),(3,)]列表中的元素類型都是元組類型
28、如何在函數中設置一個全局變量 ?
使用python的內置語法 globals 全局變量
29、logging模塊的作用?以及應用場景?
logging模塊的作用:
- 程序調試
- 了解軟件程序運行情況,是否正常
- 軟件程序運行故障分析與問題定位
應用場景:網站的運維工作,程序實時監控
30、常用字符串格式化哪幾種?
1、%s %d
print("這位同學叫%s,年齡是%d歲" %('小明',10))
2、format格式化輸出
print("這位同學叫{name},年齡是{age}歲".format(name="小明", age=18))
3、print(f'內容{變量名}')
31、簡述 生成器、迭代器、可迭代對象 以及應用場景?
生成器:在 Python 中,一邊循環一邊計算的機制,稱為生成(generator),通過next()取值,兩種表現形式
1、將列表生成式的[]改為()
2、含有yield關鍵字的函數
應用場景:優化代碼,節省內存
帶有 yield 的函數在 Python 中被稱之為 generator(生成器)
迭代器:是訪問集合元素的一種方式。迭代器同時實現了__iter__和__next__方法
可迭代對象:只要實現了__iter__方法的對象就是可迭代對象
32、談談你對閉包的理解?
在一個外函數中定義了一個內函數,內函數里運用了外函數的臨時變量,并且外函數的返回值是內函數的引用。這樣就構成了一個閉包。
一般情況下,在我們認知當中,如果一個函數結束,函數的內部所有東西都會釋放掉,還給內存,局部變量都會消失。
但是閉包是一種特殊情況,如果外函數在結束的時候發現有自己的臨時變量將來會在內部函數中用到,就把這個臨時變量綁定給了內部函數,然后自己再結束。
def A(x):def B():print(x)return B
A(7)()#7
33、os和sys模塊的作用?
os模塊負責程序與操作系統的交互,提供了訪問操作系統底層的接口;
sys模塊負責程序與python解釋器的交互,提供了一系列的函數和變量,用于操控python的運行時環境。
34、如何使用python刪除一個文件?
import os
os.remove(r'path')
35、談談你對面向對象的理解?
面向對象的程序設計的核心是對象(上帝式思維),要理解對象為何物,必須把自己當成上帝,上帝眼里世間存在的萬物皆為對象,
不存在的也可以創造出來。對象是特征和技能的結合,其中特征和技能分別對應對象的數據屬性和方法屬性。
優點是:解決了程序的擴展性。對某一個對象單獨修改,會立刻反映到整個體系中,如對游戲中一個人物參數的特征和技能修改都很容易。
缺點:可控性差,無法向面向過程的程序設計流水線式的可以很精準的預測問題的處理流程與結果,
面向對象的程序一旦開始就由對象之間的交互解決問題,即便是上帝也無法預測最終結果。
應用場景:需求經常變化的軟件,一般需求的變化都集中在用戶層,互聯網應用,企業內部軟件,游戲等都是面向對象的程序設計大顯身手的好地方。
36、Python面向對象中的繼承有什么特點?
- 在繼承中基類的構造(init()方法)不會被自動調用,它需要在其派生類的構造中親自專門調用。
- 在調用基類的方法時,需要加上基類的類名前綴,且需要帶上self參數變量。
區別于在類中調用普通函數時并不需要帶上self參數 - Python總是首先查找對應類型的方法,如果它不能在派生類中找到對應的方法,它才開始到基類中逐個查找。(先在本類中查找調用的方法,找不到才去基類中找)。
37、面向對象中super的作用?
- super在面向對象繼承類中代指父類,書寫方法super(類名,self).屬性或者方法或super().屬性或者方法
- super方法可以增加類之間調用的靈活性,當父類名發生變化時不必修改
- super方法在類的多繼承時可以簡化代碼,避免代碼冗余
- super機制里可以保證公共父類僅被執行一次,執行的順序遵循MRO,廣度優先查詢方法
38、是否使用過functools中的函數?其作用是什么?
functools用于高階函數:指那些作用于函數或者返回其他函數的函數。通常情況下,只要是可以被當做函數調用的對象就是這個模塊的目標。
39、列舉面向對象中帶雙下劃線的特殊方法,如: new 、 init
new:構造方法,創建一個對象,實例化時第一個被執行,返回一個創建好的對象及__init__(self)的self,只有繼承了object的類才會有這個方法
init:初始化方法,__init__在__new__的基礎上完成一些其它初始化的動作,__init__沒有返回值
40、如何判斷是函數還是方法?
函數和方法都封裝了一些獨立的功能,如果在類中定義的函數那就是方法(對象或者類名點方法名調用),
否則就是函數(函數名()直接調用)
41、靜態方法和類方法區別?
靜態方法:是既不是用類中的屬性又不使用對象中的屬性,由類或者對象調用的方法,依賴python裝飾器@staticmethod來實現
類方法:只使用類中的靜態變量,一般都是由類調用,依賴python裝飾器@classmethod來實現
42、列舉面向對象中的特殊成員以及應用場景?
- call:對象的構造方法,對象加上(),可以觸發這個類的__call__方法。
- len:內置函數的len函數是依賴類中的__len__方法
- eq:判斷值是否相等的時候依賴__eq__方法
- hash:判斷hash值是否相等的時候依賴__hash__方法(拓展:set的去重機制其實就是根據__hash__和__eq__方法實現的)
- str:和str() print() %s 都是息息相關的,返回值一定是字符串類型
- repr:和 repr() %r都是息息相關的,在沒有__str__方法時,repr__可以完全取代__str。
- del 析構方法,對應著一個對象的刪除之前執行的內容
43、什么是反射?以及應用場景?(知道)
定義:通過用字符串數據類型的變量名來訪問這個變量的值,在python面向對象中的反射,通過字符串的形式操作對象相關的屬性或方法(如eval(),exec()).
應用場景:用于處理通過用戶輸入,文件讀取,或者網絡傳輸所得到的字符串形式的指令來完成對應的操作
44、metaclass作用?以及應用場景?(知道)
metaclass,直譯為元類,簡單的解釋就是:當我們定義了類以后,就可以根據這個類創建出實例,
所以:先定義類,然后創建實例。但是如果我們想創建出類呢?那就必須根據metaclass創建出類,換句話說,你可以把類看成是metaclass創建出來的“實例”
45、isinstance作用以及應用場景?
isinstance作用是來判斷一個對象是否是一個已知的類型
46、異常處理寫法以及如何主動拋出異常(應用場景)
異常處理的常規寫法:
try:#執行的主體函數
except Exception as e:print(str(e))主動拋出異常:
raise TypeError('出現了不可思議的異常')#TypeError可以是任意的錯誤類型
47、簡述 yield和yield from關鍵字。
yield 是一個類似 return 的關鍵字,只是這個函數返回的是個生成器當你調用這個函數的時候,函數內部的代碼并不立馬執行 ,這個函數只是返回一個生成器對象,當你使用for進行迭代的時候,函數中的代碼才會執行
yield from 的主要功能是打開雙向通道,把最外層的調用方與最內層的子生成器連接起來,這樣二者可以直接發送和產出值,還可以直接傳入異常,而不用在位于中間的協程中添加大量處理異常的樣板代碼。
有了這個結構,協程可以通過以前不可能的方式委托職責。
48、解釋 Python 中的三元表達式
與 C++不同, 在 Python 中我們不需要使用 ? 符號,而是使用如下語法:
[on true] if [expression]else [on false]
如果 [expression] 為真, 則 [on true] 部分被執行。如果表示為假則 [on false] 部分被執行
49、解釋繼承
一個類繼承自另一個類,也可以說是一個孩子類/派生類/子類,繼承自父類/基類/超類,同時獲取所有的類成員(屬性和方法)。
繼承使我們可以重用代碼,并且還可以更方便地創建和維護代碼。Python 支持以下類型的繼承:
- 單繼承- 一個子類類繼承自單個基類
- 多重繼承- 一個子類繼承自多個基類
- 多級繼承- 一個子類繼承自一個基類,而基類繼承自另一個基類
- 分層繼承- 多個子類繼承自同一個基類
- 混合繼承- 兩種或兩種以上繼承類型的組合
關于繼承的更多內容參考 Python Inheritance( https://data-flair.training/blogs/python-inheritance/)
50、什么是 Flask?
Flask 是一個使用 Python 編寫的輕量級 Web 應用框架,使用 BSD 授權。其 WSGI 工具箱采用 Werkzeug,模板引擎則使用 Jinja2。除了 Werkzeug 和 Jinja2 以外幾乎不依賴任何外部庫。因為 Flask 被稱為輕量級框架。
Flask 的會話會話使用簽名 cookie 來允許用戶查看和修改會話內容。它會記錄從一個請求到另一個請求的信息。但如果要修改會話,則必須有密鑰 Flask.secret_key。
51、當退出 Python 時是否釋放所有內存分配?
答案是否定的。那些具有對象循環引用或者全局命名空間引用的變量,在 Python 退出是往往不會被釋放
另外不會釋放 C 庫保留的部分內容。
52、解釋 Python 中的//,%和運算符**
//運算符執行地板除法,返回結果的整數部分 (向下取整)。
**符號表示取冪. a**b 返回 a 的 b 次方
% 是取模符號。返回除法后的余數。
53、什么是pickling和unpickling?
Pickle模塊讀入任何Python對象,將它們轉換成字符串,然后使用dump函數將其轉儲到一個文件中——這個過程叫做pickling。
反之從存儲的字符串文件中提取原始Python對象的過程,叫做unpickling。
54、將字符串str1的前三位替換為‘R’:
3*’R’+str1[3:]
創建一個與Str1順序相反的字符串
方法一(推薦):
Str1[::-1]
方法二:
l=list(Str1)
l.reverse()#reverse應用于list
print(“”.join(l))
看程序寫結果題
55、求結果
v = dict.fromkeys(['k1','k2'],[])
v['k1'].append(666)
print(v)
v['k1'] = 777
print(v)答案:{'k1':[666],'k2':[666]}
{'k1':777,'k2':[666]}
解析:formkeys()默認參數為可變數據類型時有坑
56、求結果:
def num():
return [lambda x: i*x for i in range(4)]
print([m(2) for m in num()])答案:[6, 6, 6, 6]
解析: 問題的本質在與python中的屬性查找規則,LEGB(local,enclousing,global,bulitin),
在上面的例子中,i就是在閉包作用域(enclousing),而Python的閉包是 遲綁定 ,
這意味著閉包中用到的變量的值,是在內部函數被調用時查詢得到的
所以:[lambda x: i*x for i in range(4)]打印出來是含有四個內存地址的列表,每個內存地址中的i在本內存中都沒有被定義,而是通過閉包作用域中的i值,當for循環執行結束后,i的值等于3,所以再執行[m(2) for m in num()]時,每個內存地址中的i值等于3,當x等于2時,打印出來的結果都是6,從而得到結果[6, 6, 6, 6]。
57、求結果:
a. [ i % 2 for i in range(10) ] ===>[0,1,0,1,0,1,0,1,0,1]
b. ( i % 2 for i in range(10) )===>返回一個生成器的內存地址
58、求結果:
a. 1 or 2 =========>1
b. 1 and 2 ========>2
c. 1 < (2==2)======>false
d. 1 < 2 == 2======>ture
59、def func(a,b=[]) 這種寫法有什么坑?
def func(a,b=[]):b.append(a)print(b)
函數的第二個默認參數是一個list,當第一次執行的時候實例化了一個list,
第二次執行還是用第一次執行的時候實例化的地址存儲,以后每次實例化都是
60、關于Fliter&lambda的題目
輸出nums的值:
nums = range(2,20)
for i in nums:nums = filter(lambda x:x==i or x % i,nums)#注意lambda輸出為非空時,才能進入下個數進行計算(即x%i的值為非空時才返回值進入下個數的運算)
所以滿足x==i且x%i的值為正數時才執行fliter函數。
輸出結果:
61、關于dict的一些操作
key = 'abcde'
value = range(1, 6)
b0=dict(zip(key, value))
b1=range(10)
b2=[i for i in b1 if i in b0]
print(b2)
#for s in b0返回的是對應的dict的鍵值即索引值
print([b0[s] for s in b0])
b3=[b0[s] for s in b0]
b4=[i for i in b1 if i in b3]
print(b4)
b5={i:i*i for i in b1}
print(b5)
b6=[[i*i] for i in b1]
print(b6)
輸出:
編程題
1、請編寫一個函數實現將IP地址轉換成一個整數。
如 10.3.9.12 轉換規則為:
10 00001010
3 00000011
9 00001001
12 00001100
再將以上二進制拼接起來計算十進制結果:00001010 00000011 00001001 00001100 = ?
答案:
def func(x):lis = x.strip().split('.')
#注意這種連貫用法(直接將for循環接函數處理,需要用[]括起來)li = [bin(int(i)) for i in lis]
#replace的參數為str類型;li2 = [i.replace('0b',(10-len(i))*'0') for i in li]
#join參數為list類型;return int(''.join(li2),2)ret = func('10.3.9.12')
print(ret)
2、一行代碼實現9*9乘法表。
lis = ['%s*%s=%s'%(i,j,i*j) for i in range(1,10) for j in range(i,10)]
3、如何用一行代碼生成[1,4,9,16,25,36,49,64,81,100] ?
li = [x*x for x in range(1,11)]
4、一行代碼實現刪除列表中重復的值 ?
li = [1, 1, 1, 23, 3, 4, 4]
new_li = list(set(li))
5、請用代碼簡答實現stack 。
def Stack(object):def __init__(self):self.stack = []def push(self,value):# 進棧self.stack.append(value)def pop(self):# 出棧if self.stack:self.stack.pop()else:raise LookupError('stack is empty!')def is_empty(self):# 查看stack是否為空return bool(self.stack)def top(self):# 取出stack中最新的值return self.stack[-1]
6、用Python實現一個二分查找的函數。
lis = [0, 1, 3, 4, 5, 6, 7, 9, 10, 11,12,16,17]
def two_find(x, lis, start=0, end=None):if end == None:end = len(lis) - 1num = (end - start) // 2 + startif end > start:if lis[num] > x:return two_find(x, lis, start=start, end=num)elif lis[num] < x:return two_find(x, lis, start=num + 1, end=end)elif lis[num] == x:return numelif lis[end] == x:return endelse:return None
print(two_find(17, lis))
7、如何生成一個隨機數?
import random
def rdm(n):lis = []for i in range(n):n = random.randint(1,9)lis.append(str(n))s = ''.join(lis)return int(s)
print(rdm(3))
8、1、2、3、4、5 能組成多少個互不相同且無重復的三位數
count = 0
for i in range(1,6):for j in range(1,6):for k in range(1,6):if (i != j) and (i != k) and (j != k):count += 1if count % 6:print(f'{i}{j}{k}', end='|')else:print(f'{i}{j}{k}')
print(count)
9、用盡量多的方法實現單例模式。
1、基于__new__()方法
class Person:def __new__(cls, *args, **kwargs):if not hasattr(cls,cls._instance):cls._instance = super().__new__(cls)return cls._instance
2、基于模塊導入方式,現在一個py文件中寫好一個類,實例化一個對象。以后用這個類直接導入這個模塊就是單例模式。3、基于裝飾器方法實現
def singleton(cls, *args, **kwargs):instance_dic = {}def inner(*args, **kwargs):if cls not in instance_dic:instance_dic['cls'] = cls(*args, **kwargs)return instance_dic['cls']return inner
@singleton
class Person:pass
裝飾器的寫法以及應用場景。
裝飾器的寫法:
def wrapper(func):
def inner(*args,**kwargs):
'被裝飾之前的操作'
ret = func(*args,**kwargs)
'被裝飾之后的操作'
return ret
return inner
裝飾器的應用場景:
比如注冊登錄、插入日志,性能測試,事務處理,緩存等等場景
10、判斷一個數是否是質數
def isPrime(num):if num<=3:return num>1for i in range(2,num):if(num%i==0):return Falsereturn Trueprint(isPrime(4))