1.列出 5 個常用 Python 標(biāo)準(zhǔn)庫晨另?
python標(biāo)準(zhǔn)庫就是安裝python時默認(rèn)自帶的庫,常用的標(biāo)準(zhǔn)庫有:sys洞渔、os、math驾锰、random、time走越、datatime椭豫、json、threading旨指、socket等等
2.Python 內(nèi)建數(shù)據(jù)類型有哪些赏酥?
整型、浮點型谆构、布爾型裸扶、復(fù)數(shù)型、列表搬素、元組呵晨、字典、set蔗蹋、字符串
3.簡述 with 方法打開處理文件幫我我們做了什么?
with方法幫我們實現(xiàn)了f.close方法囱淋,關(guān)閉文件
4.列出 Python 中可變數(shù)據(jù)類型和不可變數(shù)據(jù)類型猪杭,為什么?
可變數(shù)據(jù)類型:列表妥衣、元組 不可變數(shù)據(jù)類型:數(shù)字型數(shù)據(jù)類型皂吮、字符串、元組税手。 可變數(shù)據(jù)類型的數(shù)據(jù)蜂筹,值被修改后它在內(nèi)存中地址不會改變,不會產(chǎn)生新的對象芦倒,即使有另外相同值的對象艺挪,也會相對獨立存在,不存在引用計數(shù)兵扬。不可變數(shù)據(jù)類型的數(shù)據(jù)麻裳,在內(nèi)存中值是唯一的,相同值的對象在內(nèi)存中都被視為是同一個對象的不同引用器钟,值一旦被修改則產(chǎn)生新的對象津坑。
5.Python 獲取當(dāng)前日期?
先導(dǎo)入庫:import time
獲取當(dāng)前日期和時間:now_time = time.time()
格式化成我們想要的日期:now_time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
6.統(tǒng)計字符串每個單詞出現(xiàn)的次數(shù)
from collections import Counter
str = 'I can because i think i can'
# counts = Counter(str.split())
s = str.split()
res = {}
for i in s:
if i not in res:
res[i] = 1
else:
res[i] += 1
print(res)
7.用 python 刪除文件和用 linux 命令刪除文件方法
python:os.remove(文件名)
linux: rm 文件名
8.寫一段自定義異常代碼
9.舉例說明異常模塊中 try except else finally 的相關(guān)意義
try和except之間是可能會產(chǎn)生異常的代碼傲霸,如果產(chǎn)生異常疆瑰,且于except后的異常類型一致眉反,則執(zhí)行except和else之間的代碼,如果沒有產(chǎn)生異常穆役,則執(zhí)行else后的代碼寸五,finally后的代碼時無論產(chǎn)不產(chǎn)生異常都會執(zhí)行的代碼
try:
pass
except Exception:
pass
else:
pass
finally:
pass
10.遇到 bug 如何處理
1.IDE調(diào)試 開發(fā)工具斷點調(diào)試
2.print大法 關(guān)鍵參數(shù)輸出調(diào)試
3.日志 通過日志調(diào)試
4.重構(gòu) 如果代碼不長,可以重寫一遍試試
語言特性
1. 談?wù)剬?Python 和其他語言的區(qū)別
答:Python 是一門語法簡潔優(yōu)美,功能強大無比,應(yīng)用領(lǐng)域非常廣泛,具有強大完備的第三方庫孵睬,他是一門強類型的可移植播歼、可擴展,可嵌入的解釋型編程語言掰读,屬于動態(tài)語言秘狞。
拿 C 語言和 Python 比:
Python 的第三方類庫比較齊全并且使用簡潔,很少代碼就能實現(xiàn)一些功能,如果用 C 去實現(xiàn)相同的功能可能就比較復(fù)雜蹈集。但是對于速度來說 Python 的運行速度相較于 C 就比較慢了烁试。所以有利的同時也有弊端,畢竟我們的學(xué)習(xí)成本降低了拢肆。
2. 簡述解釋型和編譯型編程語言
答:解釋型語言是在運行程序的時候才翻譯减响,每執(zhí)行一次,要翻譯一次郭怪,效率較低支示。
編譯型就是直接編譯成機型可以執(zhí)行的,只翻譯一次鄙才,所以效率相對來說較高颂鸿。
3. Python 的解釋器種類以及相關(guān)特點?
答:
- CPython
c 語言開發(fā)的攒庵,使用最廣的解釋器 - IPython
基于 cPython 之上的一個交互式計時器嘴纺,交互方式增強功能和 cPython 一樣 - PyPy
目標(biāo)是執(zhí)行效率,采用 JIT 技術(shù)浓冒。對 Python 代碼進(jìn)行動態(tài)編譯栽渴,提高執(zhí)行效率 - JPython
運行在 Java 上的解釋器,直接把 Python 代碼編譯成 Java 字節(jié)碼執(zhí)行 - IronPython
運行在微軟 .NET 平臺上的解釋器稳懒,把 Python 編譯成 . NET 的字節(jié)碼闲擦。
4. Python3 和 Python2 的區(qū)別?
答:
這里例舉 5 條
- print 在 Python3 中是函數(shù)必須加括號场梆,Python2 中 print 為 class佛致。
- Python2 中使用 xrange,Python3 使用 range辙谜。
- Python2 中默認(rèn)的字符串類型默認(rèn)是 ASCII俺榆,Python3 中默認(rèn)的字符串類型是 Unicode罐脊。
- Python2 中/的結(jié)果是整型萍桌,Python3 中是浮點類型宵溅。
- Python2 中聲明元類:metaclass = MetaClass,Python3 中聲明元類:class newclass(metaclass=MetaClass):pass。
5. Python3 和 Python2 中 int 和 long 區(qū)別上炎?
答:Python2 有 int 和 long 類型。int 類型最大值不能超過 sys.maxint寇损,而且這個最大值是平臺相關(guān)的∩咽常可以通過在數(shù)字的末尾附上一個L來定義長整型浊吏,顯然,它比 int 類型表示的數(shù)字范圍更大救氯。在 Python3 里找田,只有一種整數(shù)類型 int,大多數(shù)情況下着憨,和 Python2中的長整型類似墩衙。
6. xrange 和 range 的區(qū)別?
答:xrange 是在 Python2 中的用法享扔,Python3 中只有 range
xrange 用法與 range 完全相同底桂,所不同的是生成的不是一個 list 對象植袍,而是一個生成器惧眠。
編碼規(guī)范
7. 什么是 PEP8?
答:PEP8 通常會聽別人提到,但是具體的指什么內(nèi)容呢于个,簡單介紹下氛魁。
《Python Enhancement Proposal #8》(8 號 Python 增強提案)又叫 PEP8,他針對的 Python 代碼格式而編訂的風(fēng)格指南厅篓。
8. 了解 Python 之禪么秀存?
答:通過 import this 語句可以獲取其具體的內(nèi)容。它告訴大家如何寫出高效整潔的代碼羽氮。
9. 了解 DocStrings 么或链?
答:DocStrings 文檔字符串是一個重要工具,用于解釋文檔程序档押,幫助你的程序文檔更加簡單易懂澳盐。主要是解釋代碼作用的祈纯。
10. 了解類型注解么?
答:PEP 484 引入了類型提示叼耙,這使得可以對 Python 代碼進(jìn)行靜態(tài)類型檢查腕窥。
在使用 Ide 的時候可以獲取到參數(shù)的類型,更方便傳入?yún)?shù)筛婉。使用格式如下
def foo(num: int) -> None:
print(f"接收到的數(shù)字是:{num}")
介紹下這個簡單例子簇爆,我們可以在函數(shù)的參數(shù)部分使用參數(shù)名+:+類型,來指定參數(shù)可以接受的類型爽撒,這里的話就是 num 參數(shù)為 int 類型入蛆,然后后面->接的是返回值的類型。這里返回值為 None匆浙,然后通過 fstring 格式化字符串輸出傳入的數(shù)字安寺。
11. 例舉你知道 Python 對象的命名規(guī)范,例如方法或者類等
答:
類:總是使用首字母大寫單詞串首尼,如 MyClass挑庶。內(nèi)部類可以使用額外的前
導(dǎo)下劃線。
變量:小寫软能,由下劃線連接各個單詞迎捺。方法名類似
常量:常量名所有字母大寫
12. Python 中的注釋有幾種?
答:總體來說分為兩種查排,單行注釋和多行注釋凳枝。
- 單行注釋在行首是
#
。 - 多行注釋可以使用三個單引號或三個雙引號跋核,包括要注釋的內(nèi)容岖瑰。
13. 如何優(yōu)雅的給一個函數(shù)加注釋?
答:可以使用 docstring 配合類型注解
14. 如何給變量加注釋砂代?
答:可以通過變量名:類型的方式如下
<pre>`a: str = "this is string type"
`</pre>
15. Python 代碼縮進(jìn)中是否支持 Tab 鍵和空格混用蹋订。
答:不允許 tab 鍵和空格鍵混用,這種現(xiàn)象在使用 sublime 的時候尤為明顯刻伊。
一般推薦使用 4 個空格替代 tab 鍵露戒。
16. 是否可以在一句 import 中導(dǎo)入多個庫?
答:可以是可以,但是不推薦捶箱。因為一次導(dǎo)入多個模塊可讀性不是很好智什,所以一行導(dǎo)入一個模塊會比較好。同樣的盡量少用 from modulename import *丁屎,因為判斷某個函數(shù)或者屬性的來源有些困難荠锭,不方便調(diào)試,可讀性也降低了晨川。
17. 在給 Py 文件命名的時候需要注意什么?
答:給文件命名的時候不要和標(biāo)準(zhǔn)庫庫的一些模塊重復(fù)证九,比如 abc键思。
另外要名字要有意義,不建議數(shù)字開頭或者中文命名甫贯。
18. 例舉幾個規(guī)范 Python 代碼風(fēng)格的工具
答:pylint 和 flake8
數(shù)據(jù)類型-字符串
19. 列舉 Python 中的基本數(shù)據(jù)類型吼鳞?
答:
Python3 中有六個標(biāo)準(zhǔn)的數(shù)據(jù)類型:字符串(String)、數(shù)字(Digit)叫搁、列表(List)赔桌、元組(Tuple)、集合(Sets)渴逻、字典(Dictionary)疾党。
20. 如何區(qū)別可變數(shù)據(jù)類型和不可變數(shù)據(jù)類型
答:
從對象內(nèi)存地址方向來說
可變數(shù)據(jù)類型:在內(nèi)存地址不變的情況下,值可改變(列表和字典是可變類型惨奕,但是字典中的 key 值必須是不可變類型)
不可變數(shù)據(jù)類型:內(nèi)存改變雪位,值也跟著改變。(數(shù)字梨撞,字符串雹洗,布爾類型,都是不可變類型)可以通過 id() 方法進(jìn)行內(nèi)存地址的檢測卧波。
21. 將"hello world"轉(zhuǎn)換為首字母大寫"Hello World"
答:
這個得看清題目是要求兩個單詞首字母都要大寫时肿,如果只是第一個單詞首字母大小的話,只使用 capitalize 即可港粱,但是這里是兩個單詞螃成,所以用下面的方法。
"hello world".title()
22. 如何檢測字符串中只含有數(shù)字?
答:可以通過 isdigit 方法查坪,例子如下
s1 = "12223".isdigit()
print(s1)
s2 = "12223a".isdigit()
print(s2)
#結(jié)果如下:
#True
#False
23. 將字符串"ilovechina"進(jìn)行反轉(zhuǎn)
答:
s1 = "ilovechina"[::-1]
print(s1)
24. Python 中的字符串格式化方式你知道哪些寸宏?
答:%s,format偿曙,fstring(Python3.6 開始才支持氮凝,現(xiàn)在推薦的寫法)
25. 有一個字符串開頭和末尾都有空格,比如“ adabdw ”遥昧,要求寫一個函數(shù)把這個字符串的前后空格都去掉覆醇。
答:因為題目要是寫一個函數(shù)所以我們不能直接使用 strip朵纷,不過我們可以把它封裝到函數(shù)啊
def strip_function(s1):
return s1.strip()
s1 = " adabdw "
print(strip_function(s1))
26. 獲取字符串”123456“最后的兩個字符炭臭。
答:切片使用的考察,最后兩個即開始索引是 -2袍辞,代碼如下
a = "123456"
print(a[-2::])
27. 一個編碼為 GBK 的字符串 S鞋仍,要將其轉(zhuǎn)成 UTF-8 編碼的字符串,應(yīng)如何操作搅吁?
答:
a= "S".encode("gbk").decode("utf-8",'ignore')
print(a)
28. (1)s="info:xiaoZhang 33 shandong"威创,用正則切分字符串輸出['info', 'xiaoZhang', '33', 'shandong']落午。(2)a = "你好 中國 ",去除多余空格只留一個空格肚豺。
答:
(1)我們需要根據(jù)冒號或者空格切分
import re
s = "info:xiaoZhang 33 shandong"
res = re.split(r":| ", s)
print(res)
(2)
s = "你好 中國 "
print(" ".join(s.split()))
29. (1) 怎樣將字符串轉(zhuǎn)換為小寫溃斋。 (2) 單引號、雙引號吸申、三引號的區(qū)別梗劫?
答:
(1) 使用字符串的 lower() 方法。
(2)單獨使用單引號和雙引號沒什么區(qū)別截碴,但是如果引號里面還需要使用引號的時候梳侨,就需要這兩個配合使用了,然后說三引號日丹,同樣的三引號也分為三單引號和三雙引號走哺,兩個都可以聲名長的字符串時候使用,如果使用 docstring 就需要使用三雙引號哲虾。
數(shù)據(jù)類型 - 列表
30. 已知 AList = [1,2,3,1,2]丙躏,對 AList 列表元素去重,寫出具體過程束凑。
答:
list(set(AList))
31. 如何實現(xiàn) "1,2,3" 變成 ["1","2","3"]
**答**:
<pre>`s = "1,2,3"
print(s.split(","))
`</pre>
#### 32. 給定兩個 list彼哼,A 和 B,找出相同元素和不同元素
答:
A湘今、B 中相同元素:print(set(A)&set(B))
A敢朱、B 中不同元素:print(set(A)^set(B))
33. [[1,2],[3,4],[5,6]] 一行代碼展開該列表,得出 [1,2,3,4,5,6]
答:
l = [[1,2],[3,4],[5,6]]
x=[j for i in l for j in i]
print(x)
34. 合并列表 [1,5,7,9] 和 [2,2,6,8]
答:使用 extend 和 + 都可以摩瞎。
a = [1,5,7,9]
b = [2,2,6,8]
a.extend(b)
print(a)
35. 如何打亂一個列表的元素拴签?
答:
import random
a = [1, 2, 3, 4, 5]
random.shuffle(a)
print(a)
數(shù)據(jù)類型 - 字典
36. 字典操作中 del 和 pop 有什么區(qū)別
答:del 可以根據(jù)索引(元素所在位置)來刪除的,沒有返回值旗们。
pop 可以根據(jù)索引彈出一個值蚓哩,然后可以接收它的返回值。
37. 按照字典的內(nèi)的年齡排序
d1 = [
{'name':'alice', 'age':38},
{'name':'bob', 'age':18},
{'name':'Carl', 'age':28},
]
答:
d1 = [
{'name': 'alice', 'age': 38},
{'name': 'bob', 'age': 18},
{'name': 'Carl', 'age': 28},
]
print(sorted(d1, key=lambda x:x["age"]))
38. 請合并下面兩個字典 a = {"A":1,"B":2},b = {"C":3,"D":4}
答:
合并字典方法很多上渴,可以使用 a.update(b) 或者下面字典解包的方式
a = {"A":1,"B":2}
b = {"C":3,"D":4}
print({**a,**b})
39. 如何使用生成式的方式生成一個字典岸梨,寫一段功能代碼。
答:
# 需求 3: 把字典的 key 和 value 值調(diào)換稠氮;
d = {'a':'1', 'b':'2'}
print({v:k for k,v in d.items()})
40. 如何把元組 ("a","b") 和元組 (1,2)曹阔,變?yōu)樽值?{"a":1,"b":2}
答
zip 的使用,但是最后記得把 zip 對象再轉(zhuǎn)換為字典隔披。
a = ("a", "b")
b = (1, 2)
print(dict(zip(a, b)))
數(shù)據(jù)類型 - 綜合
41. 下列字典對象鍵類型不正確的是赃份?
A:{1:0,2:0,3:0}
B:{"a":0, "b":0, "c":0}
C: {(1,2):0, (2,3):0}
D: {[1,2]:0, [2,3]:0}
答:D
因為只有可 hash 的對象才能做字典的鍵,列表是可變類型不是可 hash 對象,所以不能用列表做為字典的鍵抓韩。
42. 如何交換字典 {"A":1,"B":2}的鍵和值
答:
s = {"A":1,"B":2}
#方法一:
dict_new = {value:key for key纠永,value in s.items()}
# 方法二:
new_s= dict(zip(s.values(),s.keys()))
43. Python 里面如何實現(xiàn) tuple 和 list 的轉(zhuǎn)換谒拴?
答:
Python 中的類型轉(zhuǎn)換尝江,一般通過類型強轉(zhuǎn)即可完成
tuple 轉(zhuǎn) list 是 list() 方法
list 轉(zhuǎn) tuple 使用 tuple() 方法
44. 我們知道對于列表可以使用切片操作進(jìn)行部分元素的選擇,那么如何對生成器類型的對象實現(xiàn)相同的功能呢英上?
答:
這個題目考察了 Python 標(biāo)準(zhǔn)庫的 itertools 拿埃快的掌握情況,該模塊提供了操作生成器的一些方法善延。 對于生成器類型我們使用 islice 方法來實現(xiàn)切片的功能少态。例子如下
from itertools import islice
gen = iter(range(10)) #iter()函數(shù)用來生成迭代器
#第一個參數(shù)是迭代器,第二個參數(shù)起始索引易遣,第三個參數(shù)結(jié)束索引彼妻,不支持負(fù)數(shù)索引
for i in islice(gen,0,4):
print(i)
45. 請將 [i for i in range(3)] 改成生成器
答:通過把列表生產(chǎn)式的中括號,改為小括號我們就實現(xiàn)了生產(chǎn)器的功能即豆茫,
(i for i in range(3))
46. a="hello" 和 b="你好" 編碼成 bytes 類型
答:
這個題目一共三種方式侨歉,第一種是在字符串的前面加一個 b,第二種可以使用 bytes 方法揩魂,第三種使用字符串 encode 方法幽邓。具體代碼如下,abc 代表三種情況
a = b"hello"
b = bytes("你好", "utf-8")
c = "你好".encode("utf-8")
print(a, b, c)
47. 下面的代碼輸出結(jié)果是什么火脉?
a = (1,2,3,[4,5,6,7],8)
a[2] = 2
答:
我們知道元組里的元素是不能改變的所以這個題目的答案是出現(xiàn)異常牵舵。
48. 下面的代碼輸出的結(jié)果是什么?
a = (1,2,3,[4,5,6,7],8)
a[3][0] = 2
答:前面我說了元組的里元素是不能改變的,這句話嚴(yán)格來說是不準(zhǔn)確的倦挂,如果元組里面元素本身就是可變類型畸颅,比如列表,那么在操作這個元素里的對象時方援,其內(nèi)存地址也是不變的没炒。a[3] 對應(yīng)的元素是列表,然后對列表第一個元素賦值犯戏,所以最后的結(jié)果是:
(1,2,3,[2,5,6,7],8)
操作類題目
49. Python 交換兩個變量的值
答:在 Python 中交換兩個對象的值通過下面的方式即可
a , b = b ,a
但是需要強調(diào)的是這并不是元組解包送火,通過 dis 模塊可以發(fā)現(xiàn),這是交換操作的字節(jié)碼是 ROT_TWO先匪,意思是在棧的頂端做兩個值的互換操作种吸。
50. 在讀文件操作的時候會使用 read、readline 或者 readlines胚鸯,簡述它們各自的作用
答:.read() 每次讀取整個文件骨稿,它通常用于將文件內(nèi)容放到一個字符串變量中笨鸡。如果希望一行一行的輸出那么就可以使用 readline()姜钳,該方法會把文件的內(nèi)容加載到內(nèi)存坦冠,所以對于對于大文件的讀取操作來說非常的消耗內(nèi)存資源,此時就可以通過 readlines 方法哥桥,將文件的句柄生成一個生產(chǎn)器辙浑,然后去讀就可以了。
51. json 序列化時拟糕,可以處理的數(shù)據(jù)類型有哪些判呕?如何定制支持 datetime 類型?
答: 可以處理的數(shù)據(jù)類型是 str送滞、int侠草、list、tuple犁嗅、dict边涕、bool、None,
因為 datetime 類不支持 json 序列化褂微,所以我們對它進(jìn)行拓展功蜓。
# 自定義時間序列化
import json
from datetime import datetime, date
# JSONEncoder 不知道怎么去把這個數(shù)據(jù)轉(zhuǎn)換成 json 字符串的時候
# ,它就會去調(diào) default()函數(shù),所以都是重寫這個函數(shù)來處理它本身不支持的數(shù)據(jù)類型宠蚂,
# default()函數(shù)默#認(rèn)是直接拋異常的式撼。
class DateToJson(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj, date):
return obj.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, obj)
d = {'name': 'cxa', 'data': datetime.now()}
print(json.dumps(d, cls=DateToJson))
52. json 序列化時,默認(rèn)遇到中文會轉(zhuǎn)換成 unicode求厕,如果想要保留中文怎么辦著隆?
答:可以通過 json.dumps 的 ensure_ascii 參數(shù)解決,代碼示例如下:
import json
a=json.dumps({"name":"張三"},ensure_ascii=False)
print(a)
53. 有兩個磁盤文件 A 和 B呀癣,各存放一行字母旅东,要求把這兩個文件中的信息合并(按字母順序排列),輸出到一個新文件 C 中十艾。
答:
#文件 A.txt 內(nèi)容為 ASDCF
#文件 B.txt 內(nèi)容為 EFGGTG
with open("A.txt") as f1:
f1_txt = f1.readline()
with open("B.txt") as f2:
f2_txt = f2.readline()
f3_txt = f1_txt + f2_txt
f3_list = sorted(f3_txt)
with open("C.txt", "a+") as f:
f.write("".join(f3_list))
輸出的文件 C 的內(nèi)容為 ACDEFFGGGST
54. 如果當(dāng)前的日期為 20190530抵代,要求寫一個函數(shù)輸出 N 天后的日期,(比如 N 為 2忘嫉,則輸出 20190601)荤牍。
答:這個題目考察的是 datetime 里的 timedelta 方法的使用,參數(shù)可選庆冕、默認(rèn)值都為 0:datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) 通過這個參數(shù)可以指定不同的日期類型進(jìn)行加減操作康吵,這里我們需要改的是 days,代碼如下
import datetime
def datetime_operate(n: int):
now = datetime.datetime.now() # 獲取當(dāng)前時間
\_new_date = now + datetime.timedelta(days=n) # 獲取指定天數(shù)后的新日期
new_date = \_new_date.strftime("%Y%m%d") # 轉(zhuǎn)換為指定的輸出格式
return new_date
if **name** == '**main**':
print(datetime_operate(4))
55. 寫一個函數(shù)访递,接收整數(shù)參數(shù) n晦嵌,返回一個函數(shù),函數(shù)的功能是把函數(shù)的參數(shù)和 n 相乘并把結(jié)果返回。
答:這個題目考查了閉包的使用代碼示例如下惭载,返回函數(shù)之類型是函數(shù)對象旱函。
def mul_operate(num):
def g(val):
return num * val
return g
m = mul_operate(8)
print(m(5))
56. 下面代碼會存在什么問題,如何改進(jìn)描滔?
def strappend(num):
str='first'
for i in range(num):
str+=str(i)
return str
答:
首先不應(yīng)該使用 Python 的內(nèi)置類似 str 作為變量名這里我把它改為了 s,另外在Python,str 是個不可變對象棒妨,每次迭代都會生成新的存儲空間,num 越大含长,創(chuàng)建的 str 對象就會越多券腔,內(nèi)存消耗越大。使用 yield 改成生成器即可,
還有一點就是命名規(guī)范的位置拘泞,函數(shù)名改為_分割比較好纷纫,完整的代碼如下:
def str_append(num):
s = 'first'
for i in range(num):
s += str(i)
yield s
if **name** == '**main**':
for i in str_append(3):
print(i)
57. 一行代碼輸出 1-100 之間的所有偶數(shù)。
答:可以通過列表生成式陪腌,然后使用與操作如果如 1 與之后結(jié)果為 0 則表明為偶數(shù)涛酗,等于 1 則為奇數(shù)。
# 方法1
print([i for i in range(1, 101) if i & 0x1 == 0])
# 方法2:測試發(fā)現(xiàn)方法二效率更高
print(list(range(2, 101, 2)))
58. with 語句的作用偷厦,寫一段代碼商叹?
with 語句適用于對資源進(jìn)行訪問的場合,確保不管使用過程中是否發(fā)生異常都會執(zhí)行必要的“清理”操作只泼,釋放資源剖笙,比如文件使用后自動關(guān)閉、線程中鎖的自動獲取和釋放等请唱。
其他的內(nèi)容看下面我之前寫的代碼弥咪。
#一般訪問文件資源時我們會這樣處理:
f = open(
'c:\test.txt', 'r')
data = f.read()
f.close()
# 這樣寫沒有錯,但是容易犯兩個毛彩蟆:
# 1. 如果在讀寫時出現(xiàn)異常而忘了異常處理聚至。
# 2. 忘了關(guān)閉文件句柄
#以下的加強版本的寫法:
f = open('c:\test.txt', 'r')
try:
data = f.read()
finally:
f.close()
#以上的寫法就可以避免因讀取文件時異常的發(fā)生而沒有關(guān)閉問題的處理了。代碼長了一些本橙。 #但使用 with 有更優(yōu)雅的寫法:
with open(r'c:\test.txt', 'r') as f:
data = f.read()
#with 的實現(xiàn)
class Test:
def **enter**(self):
print('**enter**() is call!')
return self
def dosomething(self):
print('dosomethong!')
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__() is call!')
print(f'type:{exc_type}')
print(f'value:{exc_value}')
print(f'trace:{traceback}')
print('__exit()__ is call!')
with Test() as sample:
pass
#當(dāng)對象被實例化時扳躬,就會主動調(diào)用**enter**()方法,任務(wù)執(zhí)行完成后就會調(diào)用**exit**()方法甚亭, #另外贷币,注意到,**exit**()方法是帶有三個參數(shù)的(exc_type, exc_value, traceback), #依據(jù)上面的官方說明:如果上下文運行時沒有異常發(fā)生亏狰,那么三個參數(shù)都將置為 None, #這里三個參數(shù)由于沒有發(fā)生異常役纹,的確是置為了 None, 與預(yù)期一致.
# 修改后不出異常了
class Test:
def **enter**(self):
print('**enter**() is call!')
return self
def dosomething(self):
x = 1/0
print('dosomethong!')
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__() is call!')
print(f'type:{exc_type}')
print(f'value:{exc_value}')
print(f'trace:{traceback}')
print('__exit()__ is call!')
return True
with Test() as sample:
59. Python 字典和 json 字符串相互轉(zhuǎn)化方法
答:
在 Python 中使用 dumps 方法 將 dict 對象轉(zhuǎn)為 Json 對象,使用 loads 方法可以將 Json 對象轉(zhuǎn)為 dict 對象暇唾。
dic = {'a': 123, 'b': "456", 'c': "liming"}
json_str = json.dumps(dic)
dic2 = json.loads(json_str)
print(dic2)
打哟俾觥:
'{"a": 123, "b": "456", "c": "liming"}'
{'a': 123, 'b': '456', 'c': 'liming'}
我們再來看一個特殊的例子
import json
dic = {'a': 123, 'b': "456", 'c': "liming"}
dic_str = json.loads(str(dic).replace("'", "\""))
print(dic_str)
下面我解釋下上面代碼是測試什么:
首先 json.loads(jsonstr) 這里面的參數(shù)只能是 jsonstr 格式的字符串.
當(dāng)我們使用 str 將字典 dic 轉(zhuǎn)化為字符串以后辰斋,得到的結(jié)果為:"{'a': 123, 'b': '456', 'c': 'liming'}"。
如果直接使用 json.loads(str(dic)) 你會發(fā)現(xiàn)出現(xiàn)錯誤瘸味,原因就是宫仗,單引號的字符串不符合Json的標(biāo)準(zhǔn)格式所以再次使用了 replace("'", "\"")。得到字典
其實這個例子主要目的是告訴大家 Json 的標(biāo)準(zhǔn)格式是不支持單引號型字符串的硫戈,否則會出現(xiàn)以下錯誤晤愧。
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
60. 請寫一個 Python 邏輯驴一,計算一個文件中的大寫字母數(shù)量
答:
with open('A.txt') as fs:
count = 0
for i in fs.read():
if i.isupper():
count += 1
print(count)
61. 請寫一段 Python連接Mongo數(shù)據(jù)庫潮剪,然后的查詢代碼捉邢。
答:
# -*- coding: utf-8 -*-
# @Author :...
import pymongo
db_configs = {
'type': 'mongo',
'host': '地址',
'port': '端口',
'user': 'spider_data',
'passwd': '密碼',
'db_name': 'spider_data'
}
class Mongo():
def **init**(self, db=db_configs["db_name"], username=db_configs["user"],
password=db_configs["passwd"]):
self.client = pymongo.MongoClient(f'mongodb://{db_configs["host"]}:db_configs["port"]')
self.username = username
self.password = password
if self.username and self.password:
self.db1 = self.client[db].authenticate(self.username, self.password)
self.db1 = self.client[db]
def find_data(self):
# 獲取狀態(tài)為0的數(shù)據(jù)
data = self.db1.test.find({"status": 0})
gen = (item for item in data)
return gen
if **name** == '**main**':
m = Mongo()
print(m.find_data())
62.說一說Redis的基本類型
答:
Redis 支持五種數(shù)據(jù)類型: string(字符串) 星虹、 hash(哈希)褥民、list(列表) 瘾婿、 set(集合) 及 zset(sorted set: 有序集合)潮改。
63. 請寫一段 Python連接Redis數(shù)據(jù)庫的代碼誉尖。
答:
from redis import StrictRedis, ConnectionPool
redis_url="redis://:xxxx@112.27.10.168:6379/15"
pool = ConnectionPool.from_url(redis_url, decode_responses=True)
r= StrictRedis(connection_pool=pool)
64. 請寫一段 Python連接Mysql數(shù)據(jù)庫的代碼罪既。
答:
conn = pymysql.connect(host='localhost',
port=3306, user='root',
passwd='1234', db='user', charset='utf8mb4')#聲明mysql連接對象
cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)#查詢結(jié)果以字典的形式
cursor.execute(sql語句字符串)#執(zhí)行sql語句
conn.close()#關(guān)閉鏈接
65.了解Redis的事務(wù)么
答:
簡單理解,可以認(rèn)為 redis 事務(wù)是一些列 redis 命令的集合铡恕,并且有如下兩個特點:
1.事務(wù)是一個單獨的隔離操作:事務(wù)中的所有命令都會序列化琢感、按順序地執(zhí)行。事務(wù)在執(zhí)行的過程中探熔,不會被其他客戶端發(fā)送來的命令請求所打斷驹针。
2.事務(wù)是一個原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行诀艰。
一般來說柬甥,事務(wù)有四個性質(zhì)稱為ACID,分別是原子性其垄,一致性苛蒲,隔離性和持久性。
一個事務(wù)從開始到執(zhí)行會經(jīng)歷以下三個階段:
開始事務(wù)
命令入隊
-
執(zhí)行事務(wù)
代碼示例:
import redis
import sys
def run():
try:
conn=redis.StrictRedis('192.168.80.41')
# Python中redis事務(wù)是通過pipeline的封裝實現(xiàn)的
pipe=conn.pipeline()
pipe.sadd('s001','a')
sys.exit()
#在事務(wù)還沒有提交前退出绿满,所以事務(wù)不會被執(zhí)行臂外。
pipe.sadd('s001','b')
pipe.execute()
pass
except Exception as err:
print(err)
pass
if name=="main":
run()
`</pre>66.了解數(shù)據(jù)庫的三范式么?
答:
經(jīng)過研究和對使用中問題的總結(jié)喇颁,對于設(shè)計數(shù)據(jù)庫提出了一些規(guī)范寄月,這些規(guī)范被稱為范式
一般需要遵守下面3范式即可:
第一范式(1NF):強調(diào)的是列的原子性,即列不能夠再分成其他幾列无牵。
第二范式(2NF):首先是 1NF漾肮,另外包含兩部分內(nèi)容,一是表必須有一個主鍵茎毁;二是沒有包含在主鍵中的列必須完全依賴于主鍵克懊,而不能只依賴于主鍵的一部分忱辅。
第三范式(3NF):首先是 2NF,另外非主鍵列必須直接依賴于主鍵谭溉,不能存在傳遞依賴墙懂。即不能存在:非主鍵列 A 依賴于非主鍵列 B,非主鍵列 B 依賴于主鍵的情況扮念。67.了解分布式鎖么
答:
分布式鎖是控制分布式系統(tǒng)之間的同步訪問共享資源的一種方式损搬。
對于分布式鎖的目標(biāo),我們必須首先明確三點: 任何一個時間點必須只能夠有一個客戶端擁有鎖柜与。
不能夠有死鎖巧勤,也就是最終客戶端都能夠獲得鎖,盡管可能會經(jīng)歷失敗弄匕。
-
錯誤容忍性要好颅悉,只要有大部分的Redis實例存活,客戶端就應(yīng)該能夠獲得鎖迁匠。
分布式鎖的條件
互斥性:分布式鎖需要保證在不同節(jié)點的不同線程的互斥
可重入性:同一個節(jié)點上的同一個線程如果獲取了鎖之后剩瓶,能夠再次獲取這個鎖。
鎖超時:支持超時釋放鎖城丧,防止死鎖
高效延曙,高可用:加鎖和解鎖需要高效,同時也需要保證高可用防止分布式鎖失效亡哄,可以增加降級枝缔。
支持阻塞和非阻塞:可以實現(xiàn)超時獲取失敗,tryLock(long timeOut)
支持公平鎖和非公平鎖分布式鎖的實現(xiàn)方案
1磺平、數(shù)據(jù)庫實現(xiàn)(樂觀鎖)
2魂仍、基于zookeeper的實現(xiàn)
3、基于Redis的實現(xiàn)(推薦)68.用 Python 實現(xiàn)一個 Reids 的分布式鎖的功能
答:REDIS分布式鎖實現(xiàn)的方式:SETNX + GETSET,NX是Not eXists的縮寫拣挪,如SETNX命令就應(yīng)該理解為:SET if Not eXists擦酌。
多個進(jìn)程執(zhí)行以下Redis命令:<pre>
SETNX lock.foo <current Unix time + lock timeout + 1>
</pre>如果 SETNX 返回1,說明該進(jìn)程獲得鎖菠劝,SETNX將鍵 lock.foo 的值設(shè)置為鎖的超時時間(當(dāng)前時間 + 鎖的有效時間)赊舶。
如果 SETNX 返回0,說明其他進(jìn)程已經(jīng)獲得了鎖赶诊,進(jìn)程不能進(jìn)入臨界區(qū)笼平。進(jìn)程可以在一個循環(huán)中不斷地嘗試 SETNX 操作,以獲得鎖舔痪。<pre>`import time
import redis
from conf.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWORDclass RedisLock:
def init(self):
self.conn = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, db=1)
self._lock = 0
self.lock_key = ""
@staticmethod
def my_float(timestamp):
"""
Args:
timestamp:
Returns:
float 或者 0
如果取出的是 None寓调,說明原本鎖并沒人用,getset 已經(jīng)寫入锄码,返回 0夺英,可以繼續(xù)操作晌涕。
"""
if timestamp:
return float(timestamp)
else: #防止取出的值為 None,轉(zhuǎn)換 float 報錯
return 0@staticmethod def get_lock(cls, key, timeout=10): cls.lock_key = f"{key}_dynamic_lock" while cls._lock != 1: timestamp = time.time() + timeout + 1 cls._lock = cls.conn.setnx(cls.lock_key, timestamp) # if 條件中痛悯,可能在運行到or之后被釋放余黎,也可能在and之后被釋放 # 將導(dǎo)致 get到一個None,float失敗载萌。 if cls._lock == 1 or ( time.time() > cls.my_float(cls.conn.get(cls.lock_key)) and time.time() > cls.my_float(cls.conn.getset(cls.lock_key, timestamp))): break else: time.sleep(0.3) @staticmethod def release(cls): if cls.conn.get(cls.lock_key) and time.time() < cls.conn.get(cls.lock_key): cls.conn.delete(cls.lock_key)
def redis_lock_deco(cls):
def _deco(func):
def deco(args, **kwargs):
cls.get_lock(cls, args[1])
try:
return func(args, **kwargs)
finally:
cls.release(cls)
return **deco
return _deco@redis_lock_deco(RedisLock())
def my_func():
print("myfunc() called.")
time.sleep(20)if name == "main":
my_func()
`</pre>69.寫一段 Python 使用 mongo 數(shù)據(jù)庫創(chuàng)建索引的代碼:
答:
<pre>`# -- coding: utf-8 --
@Time : 2018/12/28 10:01 AM
@Author : cxa
import pymongo
db_configs = {
'type': 'mongo',
'host': '地址',
'port': '端口',
'user': 'spider_data',
'passwd': '密碼',
'db_name': 'spider_data'
}class Mongo():
def init(self, db=db_configs["db_name"], username=db_configs["user"],
password=db_configs["passwd"]):
self.client = pymongo.MongoClient(f'mongodb://{db_configs["host"]}:{db_configs["port"]}')
self.username = username
self.password = password
if self.username and self.password:
self.db1 = self.client[db].authenticate(self.username, self.password)
self.db1 = self.client[db]def add_index(self): """ 通過create_index添加索引 """ self.db1.test.create_index([('name', pymongo.ASCENDING)], unique=True) def get_index(self,): """ 查看索引列表 """ indexlist=self.db1.test.list_indexes() for index in indexlist: print(index)
if name == 'main':
m = Mongo()
m.add_index()
print(m.get_index())
`</pre>高級特性
70. 函數(shù)裝飾器有什么作用惧财?請列舉說明?
答:
裝飾器就是一個函數(shù)扭仁,它可以在不需要做任何代碼變動的前提下給一個函數(shù)增加額外功能垮衷,啟動裝飾的效果。
它經(jīng)常用于有切面需求的場景斋枢,比如:插入日志帘靡、性能測試知给、事務(wù)處理瓤帚、緩存、權(quán)限校驗等場景涩赢。
下面是一個日志功能的裝飾器<pre>`from functools import wraps
def log(label):
def decorate(func):
@wraps(func)
def _wrap(args,kwargs):
try:
func(args,**kwargs)
print("name",func.name)
except Exception as e:
print(e.args)
return _wrap
return decorate@log("info")
def foo(a,b,c):
print(a+b+c)
print("in foo")decorate=decorate(foo)
if name == 'main':
foo(1,2,3)decorate()
`</pre>
71. Python 垃圾回收機制戈次?
答:Python 不像 C++,Java 等語言一樣筒扒,他們可以不用事先聲明變量類型而直接對變量進(jìn)行賦值怯邪。對 Python 語言來講,對象的類型和內(nèi)存都是在運行時確定的花墩。這也是為什么我們稱 Python 語言為動態(tài)類型的原因悬秉。
主要體現(xiàn)在下面三個方法:
1.引用計數(shù)機制
2.標(biāo)記-清除
3.分代回收72. 魔法函數(shù) call怎么使用?
答:
call 可以把類實例當(dāng)做函數(shù)調(diào)用。
使用示例如下<pre>`class Bar:
def call(self, *args, **kwargs):
print('in call')if name == 'main':
b = Bar()
b()
`</pre>73. 如何判斷一個對象是函數(shù)還是方法冰蘑?
答:看代碼已經(jīng)結(jié)果就懂了
<pre>`from types import MethodType, FunctionType
class Bar:
def foo(self):
passdef foo2():
passdef run():
print("foo 是函數(shù)", isinstance(Bar().foo, FunctionType))
print("foo 是方法", isinstance(Bar().foo, MethodType))
print("foo2 是函數(shù)", isinstance(foo2, FunctionType))
print("foo2 是方法", isinstance(foo2, MethodType))if name == 'main':
run()
`</pre>輸出
<pre>
foo 是函數(shù) False foo 是方法 True foo2 是函數(shù) True foo2 是方法 False
</pre>74. @classmethod 和 @staticmethod 用法和區(qū)別
答:
相同之處:@staticmethod 和@classmethod 都可以直接類名.方法名()來調(diào)用和泌,不用在示例化一個類。
@classmethod
我們要寫一個只在類中運行而不在實例中運行的方法祠肥。如果我們想讓方法不在實例中運行武氓,可以這么做:<pre>`def iget_no_of_instance(ins_obj):
return ins_obj.class.no_instclass Kls(object):
no_inst = 0def __init__(self): Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print(iget_no_of_instance(ik1))
`</pre>@staticmethod
經(jīng)常有一些跟類有關(guān)系的功能但在運行時又不需要實例和類參與的情況下需要用到靜態(tài)方法<pre>`IND = 'ON'
class Kls(object):
def init(self, data):
self.data = data@staticmethod def check_ind(): return (IND == 'ON') def do_reset(self): if self.check_ind(): print('Reset done for:', self.data) def set_db(self): if self.check_ind(): self.db = 'New db connection' print('DB connection made for: ', self.data)
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()
`</pre>75. Python 中的接口如何實現(xiàn)?
答:
接口提取了一群類共同的函數(shù)仇箱,可以把接口當(dāng)做一個函數(shù)的集合县恕,然后讓子類去實現(xiàn)接口中的函數(shù)。但是在 Python 中根本就沒有一個叫做 interface 的關(guān)鍵字剂桥,如果非要去模仿接口的概念忠烛,可以使用抽象類來實現(xiàn)。抽象類是一個特殊的類权逗,它的特殊之處在于只能被繼承美尸,不能被實例化垒拢。使用 abc 模塊來實現(xiàn)抽象類。76. Python 中的反射了解么?
答:Python 的反射機制設(shè)定較為簡單火惊,一共有四個關(guān)鍵函數(shù)分別是 getattr求类、hasattr、setattr屹耐、delattr尸疆。
77. metaclass 作用?以及應(yīng)用場景惶岭?
答:
metaclass 即元類寿弱,metaclass 是類似創(chuàng)建類的模板,所有的類都是通過他來 create 的(調(diào)用new)按灶,這使得你可以自由的控制創(chuàng)建類的那個過程症革,實現(xiàn)你所需要的功能。
我們可以使用元類創(chuàng)建單例模式和實現(xiàn) ORM 模式鸯旁。78. hasattr()噪矛、getattr()、setattr() 的用法
答:這三個方法屬于 Python 的反射機制里面的铺罢,hasattr 可以判斷一個對象是否含有某個屬性艇挨,getattr 可以充當(dāng) get 獲取對象屬性的作用。而 setattr 可以充當(dāng) person.name = "liming"的賦值操作韭赘。代碼示例如下:
<pre>`class Person():
def init(self):
self.name = "liming"
self.age = 12def show(self): print(self.name) print(self.age) def set_name(self): setattr(Person, "sex", "男") def get_name(self): print(getattr(self, "name")) print(getattr(self, "age")) print(getattr(self, "sex"))
def run():
if hasattr(Person, "show"):
print("判斷 Person 類是否含有 show 方法")Person().set_name() Person().get_name()
if name == 'main':
run()
`</pre>79. 請列舉你知道的 Python 的魔法方法及用途缩滨。
答:
<pre>`1 init:
類的初始化方法。它獲取任何傳給構(gòu)造器的參數(shù)(比如我們調(diào)用 x = SomeClass(10, ‘foo’) 泉瞻, init就會接到參數(shù) 10 和 ‘foo’ 脉漏。 init在 Python 的類定義中用的最多。2 new:
new是對象實例化時第一個調(diào)用的方法袖牙,它只取下 cls 參數(shù)侧巨,并把其他參數(shù)傳給 init 。 new很少使用贼陶,但是也有它適合的場景刃泡,尤其是當(dāng)類繼承自一個像元組或者字符串這樣不經(jīng)常改變的類型的時候.3 del:
new和 init是對象的構(gòu)造器, del是對象的銷毀器碉怔。它并非實現(xiàn)了語句 del x (因此該語句不等同于 x.del())烘贴。而是定義了當(dāng)對象被垃圾回收時的行為。 當(dāng)對象需要在銷毀時做一些處理的時候這個方法很有用撮胧,比如 socket 對象桨踪、文件對象。但是需要注意的是芹啥,當(dāng) Python 解釋器退出但對象仍然存活的時候锻离,del并不會 執(zhí)行铺峭。 所以養(yǎng)成一個手工清理的好習(xí)慣是很重要的,比如及時關(guān)閉連接汽纠。
`</pre>80. 如何知道一個 Python 對象的類型卫键?
答:可以通過 type 方法
81. Python 的傳參是傳值還是傳址?
答:Python 中的傳參即不是傳值也不是傳地址虱朵,傳的是對象的引用莉炉。
82. Python 中的元類 (metaclass) 使用舉例
答:可以使用元類實現(xiàn)一個單例模式,代碼如下
<pre>`class Singleton(type):
def init(self, *args, *kwargs):
print("in init")
self.__instance = None
super(Singleton, self).init(args, **kwargs)def __call__(self, *args, **kwargs): print("in __call__") if self.__instance is None: self.__instance = super(Singleton, self).__call__(*args, **kwargs) return self.__instance
class Foo(metaclass=Singleton):
pass # 在代碼執(zhí)行到這里的時候碴犬,元類中的new方法和init方法其實已經(jīng)被執(zhí)行了絮宁,而不是在 Foo 實例化的時候執(zhí)行。且僅會執(zhí)行一次服协。foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2)
`</pre>83. 簡述 any() 和 all() 方法
答:
any(x):判斷 x 對象是否為空對象绍昂,如果都為空、0偿荷、false窘游,則返回 false,如果不都為空遭顶、0张峰、false泪蔫,則返回 true棒旗。
all(x):如果 all(x) 參數(shù) x 對象的所有元素不為 0、''撩荣、False 或者 x 為空對象铣揉,則返回 True,否則返回 False餐曹。84. filter 方法求出列表所有奇數(shù)并構(gòu)造新列表逛拱,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
答
<pre>
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] print(list(filter(lambda x: x % 2 == 1, a)))
</pre>其實現(xiàn)在不推薦使用 filter,map 等方法了,一般列表生成式就可以搞定了台猴。
85. 什么是猴子補缎嗪稀?
答:
猴子補侗タ瘛(monkey patching):在運行時動態(tài)修改模塊曹步、類或函數(shù),通常是添加功能或修正缺陷休讳。猴子補丁在代碼運行時內(nèi)存中)發(fā)揮作用讲婚,不會修改源碼,因此只對當(dāng)前運行的程序?qū)嵗行Э∪帷R驗楹镒友a丁破壞了封裝筹麸,而且容易導(dǎo)致程序與補丁代碼的實現(xiàn)細(xì)節(jié)緊密耦合活合,所以被視為臨時的變通方案,不是集成代碼的推薦方式物赶。大概是下面這樣的一個效果<pre>`def post():
print("this is post")
print("想不到吧")class Http():
@classmethod
def get(self):
print("this is get")def main():
Http.get=post #動態(tài)的修改了 get 原因的功能白指,if name == 'main':
main()
Http.get()
`</pre>86. 在 Python 中是如何管理內(nèi)存的?
答:
垃圾回收:Python 不像 C++酵紫,Java 等語言一樣侵续,他們可以不用事先聲明變量類型而直接對變量進(jìn)行賦值。對 Python 語言來講憨闰,對象的類型和內(nèi)存都是在運行時確定的状蜗。這也是為什么我們稱 Python 語言為動態(tài)類型的原因(這里我們把動態(tài)類型可以簡單的歸結(jié)為對變量內(nèi)存地址的分配是在運行時自動判斷變量類型并對變量進(jìn)行賦值)。引用計數(shù):Python 采用了類似 Windows 內(nèi)核對象一樣的方式來對內(nèi)存進(jìn)行管理鹉动。每一個對象轧坎,都維護這一個對指向該對對象的引用的計數(shù)。當(dāng)變量被綁定在一個對象上的時候泽示,該變量的引用計數(shù)就是 1缸血,(還有另外一些情況也會導(dǎo)致變量引用計數(shù)的增加),系統(tǒng)會自動維護這些標(biāo)簽械筛,并定時掃描捎泻,當(dāng)某標(biāo)簽的引用計數(shù)變?yōu)?0 的時候,該對就會被回收埋哟。
內(nèi)存池機制 Python 的內(nèi)存機制以金字塔行笆豁,1、2 層主要有操作系統(tǒng)進(jìn)行操作
第 0 層是 C 中的 malloc赤赊,free 等內(nèi)存分配和釋放函數(shù)進(jìn)行操作
第 1 層和第 2 層是內(nèi)存池闯狱,有 Python 的接口函數(shù) PyMem_Malloc 函數(shù)實現(xiàn),當(dāng)對象小于 256K 時有該層直接分配內(nèi)存
第 3 層是最上層抛计,也就是我們對 Python 對象的直接操作
-
在 C 中如果頻繁的調(diào)用 malloc 與 free 時,是會產(chǎn)生性能問題的.再加上頻繁的分配與釋放小塊的內(nèi)存會產(chǎn)生內(nèi)存碎片哄孤。Python 在這里主要干的工作有:
* 如果請求分配的內(nèi)存在 1~256 字節(jié)之間就使用自己的內(nèi)存管理系統(tǒng),否則直接使用 malloc。
- 這里還是會調(diào)用 malloc 分配內(nèi)存吹截,但每次會分配一塊大小為 256k 的大塊內(nèi)存瘦陈。
-
經(jīng)由內(nèi)存池登記的內(nèi)存到最后還是會回收到內(nèi)存池,并不會調(diào)用 C 的 free 釋放掉以便下次使用波俄。對于簡單的 Python 對象晨逝,例如數(shù)值、字符串弟断,元組(tuple 不允許被更改)采用的是復(fù)制的方式(深拷貝?)咏花,也就是說當(dāng)將另一個變量 B 賦值給變量 A 時,雖然 A 和 B 的內(nèi)存空間仍然相同,但當(dāng) A 的值發(fā)生變化時昏翰,會重新給 A 分配空間苍匆,A 和 B 的地址變得不再相同。
87. 當(dāng)退出 Python 時是否釋放所有內(nèi)存分配棚菊?
答:不是的浸踩,循環(huán)引用其他對象或引用自全局命名空間的對象的模塊,在 Python 退出時并非完全釋放统求。
另外检碗,也不會釋放 c 庫保留的內(nèi)存部分
正則表達(dá)式
88. (1)使用正則表達(dá)式匹配出
<html><h1\>www.baidu.com</h1></html>
中的地址(2)a="張明 98 分",用 re.sub码邻,將 98 替換為 100答:
第一問答案<pre>`import re
source = "<html><h1>www.baidu.com</h1></html>"
pat = re.compile("<html><h1>(.*?)</h1></html>")
print(pat.findall(source)[0])
`</pre>第二問答案
<pre>
import re s = "張明 98 分" print(re.sub(r"\d+","100",s))
</pre>89. 正則表達(dá)式匹配中(.)和(.?)匹配區(qū)別折剃?
答:(.) 為貪婪模式極可能多的匹配內(nèi)容 ,(.?) 為非貪婪模式又叫懶惰模式,一般匹配到結(jié)果就好像屋,匹配字符的少為主怕犁,示例代碼如下
<pre>`import re
s = "<html><div>文本 1</div><div>文本 2</div></html>"
pat1 = re.compile(r"<div>(.*?)</div>")
print(pat1.findall(s))pat2 = re.compile(r"<div>(.*)</div>")
print(pat2.findall(s))
`</pre>輸出
<pre>
['文本 1', '文本 2'] ['文本 1</div><div>文本 2']
</pre>90. 寫一段匹配郵箱的正則表達(dá)式
答:關(guān)于郵箱的匹配這個還真的是一個永恒的話題。
電子郵件地址有統(tǒng)一的標(biāo)準(zhǔn)格式:用戶名@服務(wù)器域名己莺。用戶名表示郵件信箱奏甫、注冊名或信件接收者的用戶標(biāo)識,@符號后是你使用的郵件服務(wù)器的域名凌受。@可以讀成“at”阵子,也就是“在”的意思。整個電子郵件地址可理解為網(wǎng)絡(luò)中某臺服務(wù)器上的某個用戶的地址胜蛉。
用戶名挠进,可以自己選擇。由字母 a~z(不區(qū)分大小寫)腾么、數(shù)字 0~9奈梳、點、減號或下劃線組成解虱;只能以數(shù)字或字母開頭和結(jié)尾。
-
與你使用的網(wǎng)站有關(guān)漆撞,代表郵箱服務(wù)商殴泰。例如網(wǎng)易的有@163.com 新浪有@vip.sina.com 等。
網(wǎng)上看到了各種各樣的版本浮驳,都不確定用哪個悍汛,于是自己簡單的總結(jié)了一個。大家有更好的歡迎留言至会。
<pre>
r"^[a-zA-Z0-9]+[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
</pre>下面解釋上面的表達(dá)式
首先強調(diào)一點關(guān)于\w 的含義离咐,\w 匹配英文字母和俄語字母或數(shù)字或下劃線或漢字。
注意[]和[]的區(qū)別,[]表示字符集合宵蛀,[]表示已[]內(nèi)的任意字符集開始昆著,[]表示。
[a-zA-Z0-9]+:這里注意[]和[]的,第一個表示已什么開頭术陶,第二個[]的^表示不等于[]內(nèi)凑懂。所以這段表示以英文字母和數(shù)字開頭,后面緊跟的+梧宫,限定其個數(shù)>=1 個接谨。
[a-zA-Z0-9_.+-]+:表示匹配英文字母和數(shù)字開頭以及_.+-, 的任意一個字符,并限定其個數(shù)>=1 個塘匣。為了考慮@前面可能出現(xiàn).+-(但是不在開頭出現(xiàn))脓豪。
@就是郵箱必備符號了
@[a-zA-Z0-9-]+.:前面的不用說了,后面的.表示.轉(zhuǎn)義了,也是必備符號忌卤。
-
[ a-zA-Z0-9-.]+:$符表示以什么結(jié)束,這里表示以英文字和數(shù)字或 -. 1 個或多個結(jié)尾跑揉。
來個例子驗證一波:
<pre>
import re plt=re.compile(r"^[a-zA-Z0-9]+[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$") b=plt.findall('adas+fefe.we@qq.com.cn') print(b)
</pre>網(wǎng)上找了個驗證郵件地址的通用正則表達(dá)式(符合 RFC 5322 標(biāo)準(zhǔn))
<pre>
(?:[a-z0-9!#$%&'*+/=?^_
{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
</pre>其他內(nèi)容
91. 解釋一下 Python 中 pass 語句的作用?
答:pass 實際上就是一個占位符埠巨,在寫一個函數(shù)但是不確定里面寫啥的時候历谍,這個時候可以使用 pass。示例如下
<pre>
def foo(): pass
</pre>92. 簡述你對 input()函數(shù)的理解
答:在 Python3 中 input 函數(shù)可以接收用戶輸入的字符串辣垒。
然后根據(jù)程序的需要轉(zhuǎn)換成所需格式即可望侈。
93. Python 中的 is 和==
答:先說==它的作用是判斷兩個對象的值是否相同,然后說 is勋桶。is 表示的誰是誰脱衙,這也就意味著對象完全相等。我們知道一個對象有各自的內(nèi)存地址和對應(yīng)的值例驹,當(dāng)內(nèi)存地址和值都相同的時候使用 is 可以得到結(jié)果 True捐韩。另外需要注意的下面兩點特殊的情況。
這些變量很可能在許多程序中使用鹃锈。 通過池化這些對象荤胁,Python 可以防止對一致使用的對象進(jìn)行內(nèi)存分配調(diào)用。
<pre>
1.介于數(shù)字-5 和 256 之間的整數(shù) 2.字符串僅包含字母屎债、數(shù)字或下劃線
</pre>94. Python 中的作用域
答:
<pre>`Python 中仅政,一個變量的作用域總是由在代碼中被賦值的地方所決定
當(dāng) Python 遇到一個變量的話它會按照這的順序進(jìn)行搜索
本地作用域(Local)--->當(dāng)前作用域被嵌入的本地作用域(Enclosing locals)--->全局/模塊作用域(Global)--->內(nèi)置作用域(Built-in)
`</pre>95. 三元運算寫法和應(yīng)用場景?
答:Python 中的三元運算又稱三目運算盆驹,是對簡單的條件語句的簡寫圆丹。
是一種比較 Pythonic 的學(xué)法,形式為:val = 1 if 條件成立 else 2
代碼示例如下:<pre>`a = 2
b = 5普通寫法
if a > b:
val = True
else:
val = False改為三元運算符后
val = a if a > b else b
print(val) # 5
`</pre>96. 了解 enumerate 么躯喇?
答:enumerate 可以在迭代一個對象的時候辫封,同時獲取當(dāng)前對象的索引和值。
代碼示例如下<pre>`from string import ascii_lowercase
s = ascii_lowercase
for index, value in enumerate(s):
print(index, value)
`</pre>97. 列舉 5 個 Python 中的標(biāo)準(zhǔn)模塊
答:
pathlib:路徑操作模塊,比 os 模塊拼接方便倦微。
urllib:網(wǎng)絡(luò)請求模塊妻味,包括對 url 的結(jié)構(gòu)解析。
asyncio: Python 的異步庫璃诀,基于事件循環(huán)的協(xié)程模塊弧可。
re:正則表達(dá)式模塊。
itertools:提供了操作生成器的一些模塊劣欢。98. 如何在函數(shù)中設(shè)置一個全局變量
答:
<pre>
# 通過使用 global 對全局變量進(jìn)行修改棕诵。 n = 0 def foo(): global n n = 100 foo() print(n) x = 0
</pre>之前我在視頻教程中對這塊做了個講解,具體點擊下方鏈接
https://www.bilibili.com/video/av50865713