python面試題目彙總
參考:https://www.cnblogs.com/JetpropelledSnake/p/9396511.html#_label1
1、常見的PEP8規範?
縮排:4個空格
空行:函式與函式之間空兩行,類內部的函式之間空一行
命名:
1、函式名小寫,可採用下劃線加字母;類名單詞第一個字母大寫,採用駝峰式命名;
2、命名必須有意義,可識別性,不能重複;
長度:每行長度不能超過79,可以採用下劃線隔開並另起一行
空格:逗號之後和操作符前後採用空格隔開;
import:不要一次匯入多個不是一個型別的庫;
常量採用大寫
2、進位制之間轉換?
bin:十進位制轉二進位制,例如 bin(10)=0b1010
oct:十進位制轉八進位制, octonary number system(八進位制)
hex:十進位制轉十六進位制,hexadecimal
int:將對應的進位制轉換成十進位制
手動轉換參考:
3、請編寫一個函式實現將IP地址轉換成一個整數?
def convert_to_int(ip):
lst = [int(item) for item in ip.split('.') if item]
return sum(lst)
4、python最大遞迴層數?996
def foo(n): print(n) n += 1 foo(n) if __name__ == '__main__': foo(1)
5、and or or?
x or y:若x為真,則為x,否則為y;
x and y:若x為真,則為y,反之為x。
x and y or z:等價於 x and (y or z)
6、按位運算子:
二進位制下運算子號。
&:按位與,都為1則為1
例如 print(10&8)=0b1010 & 0b1000 = 0b1000 = 8
|:有一個為真則為真
:當兩個對應的二進位制相異時,則結果為1,例如print(10^8)=0b0010=2
7、ascii、unicode、utf8、gbk的區別?
都是編碼型別,都包含二進位制與字元的對應關係。
ascii:僅僅包含 阿拉伯字母以及某些運算子與二進位制的對應關係,最早的編碼型別,但最多隻能表示一個位元組。
unicode:全球通用的編碼,包含所有字元與二進位制的對應關係;任何字元==2Bytes,所以用來儲存英文字元浪費空間。
gbk:本國語言與二進位制的對應關係,每個國家都有自己的GBK編碼,沒有統一起來。一箇中文字元2Bytes,一個英文字元1Bytes。
utf8:unicode的升級版本,一箇中文字元3Bytes,英文字元1Bytes,歐洲字元==2Bytes。
8、位元組碼和機器碼的區別?
機器碼:Native code,原生碼,cpu可以直接解讀的資料,執行速度最快;
位元組碼:Byte-code中間狀態的二進位制程式碼(檔案),需要直譯器轉譯才難成為機器碼。
9、is 和 ==?
is比較的是記憶體地址,可以用id()檢視;
==比較的是 值是否相等。
10、可變資料型別和不可變資料型別?
可變資料型別:該資料型別對應的變數的值發生改變,那麼它對應的記憶體地址也會發生改變。例如:list、dict、set。
不可變資料型別:該資料型別對應的值發生改變,它對應的記憶體地址不會發生改變,例如:str,int,float,tuple。
12、小資料池子
int和str,都存在一個小資料池,在這個範圍內,若變數值相同,都會指向同一個記憶體地址。
int小資料池:int在【-5,256】範圍內,建立相同的數字會指向同一個記憶體地址,超過了這個範圍,就會指向不同的地址。
字串小資料池範圍:
1、不能有空格:若有空格,則指向兩個記憶體地址;
2、不能包含特殊字元,若包含特殊字元,則指向兩個記憶體地址。
12、三元運算寫法以及應用場景?
結構:結果1 + if + 條件 + else + 結果2,若條件為True,則返回結果1,反之返回結果2。
13、py2和py3的區別?
print格式不同。
range()不同:在py2中是range是列表,xrange才是生成器,在py3只有range且是生成器。
預設編碼不同:py2的預設編碼是ascii,py3的預設編碼是utf8。
14、一行程式碼實現數值交換?
a,b=b,a
15、列舉布林值為False的常見值?
可以通過三元表示式判斷,例如:'true' if 1 else 'else'
數字型別:0為False,其餘的為True
None為False
列表、tupe、字典、set等:長度為0為false
16、list、str、tuple、dict每個常用的5個方法?
str:字串為不可變型別,沒有增刪改查
統計:
count(s):統計s出現的次數
查詢:
index(s):在指定的索引範圍內從左到右找出元素s的索引並返回;
find(s,begin,end):同index方法;
格式輸出:
lower():將字母改為小寫格式;
upper():將字母改為大寫格式;
capitalize():將首個字母改為大寫;
strip():刪除字串兩側的空格並返回,但是不改變原字串;
format():
In [32]: '{}-{}-{}'.format('alex','kate','bo')
Out[32]: 'alex-kate-bo'
In [33]: '{1}-{0}-{2}'.format('alex','kate','bo')
Out[33]: 'kate-alex-bo'
swapcase(): 大小寫反轉。
型別轉換:
s.split(sep):轉換成列表
替換:
s.replace(old,new)
判斷is系列:
isdigits()
isalpha()
isnumeric()
islowe()
isupper()
判斷開頭和結尾:
startwith(s)
endwith(s)
list:可變資料型別,可以進行增刪改查
建立列表:list('iterable')
增加:
append(s):在列表右側追加元素;
extend(iterable):迴圈可迭代物件並新增到列表中,例如:[1].extend('abcd')=[1,'a','b','c','d'];
刪除:
pop(index):根據index刪除元素並返回index;
clear():刪除所有元素;
remove(s):從左至右刪除找到的第一個元素,沒找到匹配的元素則ValueError異常;
統計:
count(s):統計s出現的次數
排序:
sort(reverse=False):升序,可以指定為降序
reverse():僅僅顛倒當前列表順序
字典dict:
建立字典:
{}.fromkeys(iterable,val)
增加或修改:
d.update({'k1':'v2'}):若字典d存在鍵k1,則更新其值為v2;若不存在鍵k1,則增加鍵值對;
d.setdefault('k1','v2'):若字典d存在k1,則返回其對應的值,若不存在,則增加鍵值對{'k1':'v2'}
刪除:
d.pop('k1'):若k1存在,則刪除該鍵值對,並返回value;若不存在,則報KeyError異常。
d.clear():清空字典;
d.popitem():隨機刪除鍵值對;
查詢:
get('k1','not found')
d.keys():結構類似[k1,k2,k3],主要這個不是列表,還需要經過轉換才難成為列表
d.values():結構類似[v1,v2,v3]
d.items():返回結構類似 [(k1,v2),(k2,v2)]
tuple元組:不可變資料型別
建立字典:tuple(iterable)
統計:
count(s)
index(s)
集合set:無序,且不重複
增加:
add(item)
s.update(s1)
s.union(s1)
刪除:
discard(item)
差集:
s1中但是s2中沒有的元素:s1.difference(s2) == s1 - s2
交集:
s1.intersection(s2)
也可以運用 +、- 運算子。
17、lambda表示式以及應用場景?
函式名=lambda 引數(多個時以逗號隔開):返回值
f=lambda x, y : x*y
引數可以有多個,且只能寫一行。
18、pass的作用?
保證程式結構完整,無其他任何作用。
19、*args 和 **kwargs作用?
在函式不確定有多少個引數時候,可以採用可變引數。
*args會將接收到的所有的位置引數轉換成列表格式,存放在函式內部作用域內;
**kwargs會將接收到的鍵值對引數轉換成字典格式,存放在函式內部作用域內。
20、深淺拷貝:
淺拷貝只是增加了一個指標指向一個存在的記憶體地址。
而深拷貝是增加了一個指標並且重新開闢一個記憶體空間。
單層
import copy
# 淺拷貝
li1 = [1, 2, 3]
li2 = li1.copy()
li1.append(4)
print(li1, li2) # [1, 2, 3, 4] [1, 2, 3,4]
# 深拷貝
li1 = [1, 2, 3]
li2 = copy.deepcopy(li1)
li1.append(4)
print(li1, li2) # [1, 2, 3, 4] [1, 2, 3]
#多層
import copy
# 淺拷貝 指向共有的地址
li1 = [1, 2, 3,[4,5],6]
li2 = li1.copy()
li1[3].append(7)
print(li1, li2) # [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5, 7], 6]
# 深拷貝 重指向
li1 = [1, 2, 3,[4,5],6]
li2 = copy.deepcopy(li1)
li1[3].append(7)
print(li1, li2) # [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5], 6]
21、python垃圾回收機制?
參考:
http://www.cnblogs.com/Xjng/p/5128269.html
http://python.jobbole.com/87843/
1、引用計數:
python裡每一個東西都是物件,當物件多了一個引用,則此物件的(PyObject)的計數變數(ob_refcnt)+1,反之-1,
當ob—refcnt=0,此物件會被系統回收;
迴圈引用:
當物件A和B相互引用,但是沒有外部再引用它們任何一個,它們的引用計數雖然都為1,但顯然應該被回收。
2、標記清除:
解決迴圈引用的問題,主要是list、set、dict、instance等容器物件,步驟:
I、先標記上所有活動物件
II、再將所有未活動的物件清除
怎麼標記?
從根物件(全域性變數、呼叫棧、暫存器)出發,以引用作為線,來連線記憶體中的物件。
缺點:簡單粗暴,清除非活動物件前必須順序掃描整個堆記憶體。
3、分代回收:
將記憶體根據物件存活的時間由短到長分為三代:年輕代、中年代、老年代,垃圾回收頻率以此減少,所以老年代的物件可能存活於系統的整個記憶體空間。
以空間換時間,具體步驟如下:
新建立的物件會被存放在年輕代,當連結串列總數(gc計數器)達到上限時,會觸發垃圾回收(gc.collect),將那些非活動物件和迴圈引用的物件回收,將剩餘的活動物件轉移到中年代,以此類推。
22、匿名函式的應用?
題目1:求結果
def multipliers():
# 返回包含四個匿名函式的列表
return [lambda x:i*x for i in range(4)]
# 注意,若返回生成器,則結果未[0,2,4,6]
print([m(2) for m in multipliers()])
由於函式未被呼叫,迴圈中的i值未被寫入函式,經過多次替代,迴圈結束後i值為3,
故結果為:6,6,6,6
題目2:現有兩個元組(('a'),('b')),(('c'),('d')),請使用python中匿名函式生成列表[{'a':'c'},{'b':'d'}]