目錄
Python進階
元類
42.Python中類方法、類執行個體方法、靜态方法有何差別?
43.周遊一個object的所有屬性,并print每一個屬性名?
44.寫一個類,并讓它盡可能多的支援操作符?
45.介紹Cython,Pypy Cpython Numba各有什麼缺點
46.請描述抽象類和接口類的差別和聯系
47.Python中如何動态擷取和設定對象的屬性?
記憶體管理與垃圾回收機制
48.哪些操作會導緻Python記憶體溢出,怎麼處理?
49.關于Python記憶體管理,下列說法錯誤的是 B
50.Python的記憶體管理機制及調優手段?
51.記憶體洩露是什麼?如何避免?
函數
52.python常見的清單推導式?
53.簡述read、readline、readlines的差別?
54.什麼是Hash(散列函數)?
55.python函數重載機制?
56.寫一個函數找出一個整數數組中,第二大的數
57.手寫一個判斷時間的裝飾器
58.使用Python内置的filter()方法來過濾?
59.編寫函數的4個原則
60.函數調用參數的傳遞方式是值傳遞還是引用傳遞?
61.如何在function裡面設定一個全局變量
62.對預設參數的了解 ?
63.Mysql怎麼限制IP通路?
64.帶參數的裝飾器?
65.為什麼函數名字可以當做參數用?
66.Python中pass語句的作用是什麼?
67.有這樣一段代碼,print c會輸出什麼,為什麼?
68.交換兩個變量的值?
69.map函數和reduce函數?
70.回調函數,如何通信的?
71.Python主要的内置資料類型都有哪些? print dir( ‘a ’) 的輸出?
72.map(lambda x:xx,[y for y in range(3)])的輸出?
73.hasattr() getattr() setattr() 函數使用詳解?
74.一句話解決階乘函數?
75.什麼是lambda函數? 有什麼好處?
76.遞歸函數停止的條件?
77.下面這段代碼的輸出結果将是什麼?請解釋。
78.什麼是lambda函數?它有什麼好處?寫一個匿名函數求兩個數的和
設計模式
79.對設計模式的了解,簡述你了解的設計模式?
80.請手寫一個單例
81.單例模式的應用場景有那些?
82.用一行代碼生成[1,4,9,16,25,36,49,64,81,100]
83.對裝飾器的了解,并寫出一個計時器記錄方法執行性能的裝飾器?
84.解釋以下什麼是閉包?
85.函數裝飾器有什麼作用?
86.生成器,疊代器的差別?
87.X是什麼類型?
88.請用一行代碼 實作将1-N 的整數清單以3為機關分組
89.Python中yield的用法?
面向對象
90.Python中的可變對象和不可變對象?
91.Python的魔法方法
92.面向對象中怎麼實作隻讀屬性?
93.談談你對面向對象的了解?
正規表達式
94.請寫出一段代碼用正則比對出ip?
95.a = “abbbccc”,用正則比對為abccc,不管有多少b,就出現一次?
96.Python字元串查找和替換?
97.用Python比對HTML g tag的時候,<.> 和 <.*?> 有什麼差別
98.正規表達式貪婪與非貪婪模式的差別?
99.寫出開頭比對字母和下劃線,末尾是數字的正規表達式?
100.正規表達式操作
101.請比對出變量A 中的json字元串。
102.怎麼過濾評論中的表情?
103.簡述Python裡面search和match的差別
104.請寫出比對ip的Python正規表達式
105.Python裡match與search的差別?
系統程式設計
106.程序總結
107.談談你對多程序,多線程,以及協程的了解,項目是否用?
108.Python異常使用場景有那些?
109.多線程共同操作同一個資料互斥鎖同步?
110.什麼是多線程競争?
111.請介紹一下Python的線程同步?
112.解釋以下什麼是鎖,有哪幾種鎖?
113.什麼是死鎖?
114.多線程互動通路資料,如果通路到了就不通路了?
115.什麼是線程安全,什麼是互斥鎖?
116.說說下面幾個概念:同步,異步,阻塞,非阻塞?
117.什麼是僵屍程序和孤兒程序?怎麼避免僵屍程序?
118.python中程序與線程的使用場景?
119.線程是并發還是并行,程序是并發還是并行?
120.并行(parallel)和并發(concurrency)?
121.IO密集型和CPU密集型差別?
122.python asyncio的原理?
網絡程式設計
123.怎麼實作強行關閉用戶端和伺服器之間的連接配接?
124.簡述TCP和UDP的差別以及優缺點?
125.簡述浏覽器通過WSGI請求動态資源的過程?
126.描述用浏覽器通路www.baidu.com的過程
127.Post和Get請求的差別?
128.cookie 和session 的差別?
129.列出你知道的HTTP協定的狀态碼,說出表示什麼意思?
130.請簡單說一下三次握手和四次揮手?
131.說一下什麼是tcp的2MSL?
132.為什麼用戶端在TIME-WAIT狀态必須等待2MSL的時間?
133.說說HTTP和HTTPS差別?
134.談一下HTTP協定以及協定頭部中表示資料類型的字段?
135.HTTP請求方法都有什麼?
136.使用Socket套接字需要傳入哪些參數 ?
137.HTTP常見請求頭?
138.七層模型?
139.url的形式?
Python進階
元類
42.Python中類方法、類執行個體方法、靜态方法有何差別?
類方法: 是類對象的方法,在定義時需要在上方使用 @classmethod 進行裝飾,形參為cls,表示類對象,類對象和執行個體對象都可調用
類執行個體方法: 是類執行個體化對象的方法,隻有執行個體對象可以調用,形參為self,指代對象本身;
靜态方法: 是一個任意函數,在其上方使用 @staticmethod 進行裝飾,可以用對象直接調用,靜态方法實際上跟該類沒有太大關系
43.周遊一個object的所有屬性,并print每一個屬性名?
class Car:
def __init__(self,name,loss): # loss [價格,油耗,公裡數]
self.name = name
self.loss = loss
def getName(self):
return self.name
def getPrice(self):
# 擷取汽車價格
return self.loss[0]
def getLoss(self):
# 擷取汽車損耗值
return self.loss[1] * self.loss[2]
Bmw = Car("寶馬",[60,9,500]) # 執行個體化一個寶馬車對象
print(getattr(Bmw,"name")) # 使用getattr()傳入對象名字,屬性值。
print(dir(Bmw)) # 獲Bmw所有的屬性和方法
44.寫一個類,并讓它盡可能多的支援操作符?
class Array:
__list = []
def __init__(self):
print "constructor"
def __del__(self):
print "destruct"
def __str__(self):
return "this self-defined array class"
def __getitem__(self,key):
return self.__list[key]
def __len__(self):
return len(self.__list)
def Add(self,value):
self.__list.append(value)
def Remove(self,index):
del self.__list[index]
def DisplayItems(self):
print "show all items---"
for item in self.__list:
print item
45.介紹Cython,Pypy Cpython Numba各有什麼缺點
Cython
46.請描述抽象類和接口類的差別和聯系
1.抽象類: 規定了一系列的方法,并規定了必須由繼承類實作的方法。由于有抽象方法的存在,是以抽象類不能執行個體化。可以将抽象類了解為毛坯房,門窗,牆面的樣式由你自己來定,是以抽象類與作為基類的普通類的差別在于限制性更強
2.接口類:與抽象類很相似,表現在接口中定義的方法,必須由引用類實作,但他與抽象類的根本差別在于用途:與不同個體間溝通的規則,你要進宿舍需要有鑰匙,這個鑰匙就是你與宿舍的接口,你的舍友也有這個接口,是以他也能進入宿舍,你用手機通話,那麼手機就是你與他人交流的接口
3.差別和關聯:
1.接口是抽象類的變體,接口中所有的方法都是抽象的,而抽象類中可以有非抽象方法,抽象類是聲明方法的存在而不去實作它的類
2.接口可以繼承,抽象類不行
3.接口定義方法,沒有實作的代碼,而抽象類可以實作部分方法
4.接口中基本資料類型為static而抽象類不是
47.Python中如何動态擷取和設定對象的屬性?
if hasattr(Parent, 'x'):
print(getattr(Parent, 'x'))
setattr(Parent, 'x',3)
print(getattr(Parent,'x'))
記憶體管理與垃圾回收機制
48.哪些操作會導緻Python記憶體溢出,怎麼處理?
49.關于Python記憶體管理,下列說法錯誤的是 B
A,變量不必事先聲明 B,變量無須先建立和指派而直接使用
C,變量無須指定類型 D,可以使用del釋放資源
50.Python的記憶體管理機制及調優手段?
記憶體管理機制: 引用計數、垃圾回收、記憶體池
引用計數:引用計數是一種非常高效的記憶體管理手段,當一個Python對象被引用時其引用計數增加1,
當其不再被一個變量引用時則計數減1,當引用計數等于0時對象被删除。弱引用不會增加引用計數
垃圾回收:
1.引用計數
引用計數也是一種垃圾收集機制,而且也是一種最直覺、最簡單的垃圾收集技術。當Python的某個對象的引用計數降為0時,說明沒有任何引用指向該對象,該對象就成為要被回收的垃圾了。比如某個建立對象,它被配置設定給某個引用,對象的引用計數變為1,如果引用被删除,對象的引用計數為0,那麼該對象就可以被垃圾回收。不過如果出現循環引用的話,引用計數機制就不再起有效的作用了。
2.标記清除
https://foofish.net/python-gc.html
調優手段
1.手動垃圾回收
2.調高垃圾回收門檻值
3.避免循環引用
51.記憶體洩露是什麼?如何避免?
記憶體洩漏指由于疏忽或錯誤造成程式未能釋放已經不再使用的記憶體。記憶體洩漏并非指記憶體在實體上的消失,而是應用程式配置設定某段記憶體後,由于設計錯誤,導緻在釋放該段記憶體之前就失去了對該段記憶體的控制,進而造成了記憶體的浪費。
有
__del__()
函數的對象間的循環引用是導緻記憶體洩露的主兇。不使用一個對象時使用: del object 來删除一個對象的引用計數就可以有效防止記憶體洩露問題。
通過Python擴充子產品gc 來檢視不能回收的對象的詳細資訊。
可以通過 sys.getrefcount(obj) 來擷取對象的引用計數,并根據傳回值是否為0來判斷是否記憶體洩露
函數
52.python常見的清單推導式?
[表達式 for 變量 in 清單] 或者 [表達式 for 變量 in 清單 if 條件]
53.簡述read、readline、readlines的差別?
read 讀取整個檔案
readline 讀取下一行
readlines 讀取整個檔案到一個疊代器以供我們周遊
54.什麼是Hash(散列函數)?
散列函數(英語:Hash function)又稱雜湊演算法、哈希函數,是一種從任何一種資料中建立小的數字“指紋”的方法。散列函數把消息或資料壓縮成摘要,使得資料量變小,将資料的格式固定下來。該函數将資料打亂混合,重新建立一個叫做散列值(hash values,hash codes,hash sums,或hashes)的指紋。散列值通常用一個短的随機字母和數字組成的字元串來代表
55.python函數重載機制?
函數重載主要是為了解決兩個問題。 1。可變參數類型。 2。可變參數個數。
另外,一個基本的設計原則是,僅僅當兩個函數除了參數類型和參數個數不同以外,其功能是完全相同的,此時才使用函數重載,如果兩個函數的功能其實不同,那麼不應當使用重載,而應當使用一個名字不同的函數。
好吧,那麼對于情況 1 ,函數功能相同,但是參數類型不同,python 如何處理?答案是根本不需要處理,因為 python 可以接受任何類型的參數,如果函數的功能相同,那麼不同的參數類型在 python 中很可能是相同的代碼,沒有必要做成兩個不同函數。
那麼對于情況 2 ,函數功能相同,但參數個數不同,python 如何處理?大家知道,答案就是預設參數。對那些缺少的參數設定為預設參數即可解決問題。因為你假設函數功能相同,那麼那些缺少的參數終歸是需要用的。
好了,鑒于情況 1 跟 情況 2 都有了解決方案,python 自然就不需要函數重載了。
56.寫一個函數找出一個整數數組中,第二大的數
57.手寫一個判斷時間的裝飾器
import datetime
class TimeException(Exception):
def __init__(self, exception_info):
super().__init__()
self.info = exception_info
def __str__(self):
return self.info
def timecheck(func):
def wrapper(*args, **kwargs):
if datetime.datetime.now().year == 2019:
func(*args, **kwargs)
else:
raise TimeException("函數已過時")
return wrapper
@timecheck
def test(name):
print("Hello {}, 2019 Happy".format(name))
if __name__ == "__main__":
test("backbp")
58.使用Python内置的filter()方法來過濾?
list(filter(lambda x: x % 2 == 0, range(10)))
59.編寫函數的4個原則
1.函數設計要盡量短小
2.函數聲明要做到合理、簡單、易于使用
3.函數參數設計應該考慮向下相容
4.一個函數隻做一件事情,盡量保證函數語句粒度的一緻性
60.函數調用參數的傳遞方式是值傳遞還是引用傳遞?
Python的參數傳遞有:位置參數、預設參數、可變參數、關鍵字參數。
函數的傳值到底是值傳遞還是引用傳遞、要分情況:
不可變參數用值傳遞:像整數和字元串這樣的不可變對象,是通過拷貝進行傳遞的,因為你無論如何都不可能在原處改變不可變對象。
可變參數是引用傳遞:比如像清單,字典這樣的對象是通過引用傳遞、和C語言裡面的用指針傳遞數組很相似,可變對象能在函數内部改變。
61.如何在function裡面設定一個全局變量
globals() # 傳回包含目前作用餘全局變量的字典。
global 變量 設定使用全局變量
62.對預設參數的了解 ?
預設參數指在調用函數的時候沒有傳入參數的情況下,調用預設的參數,在調用函數的同時指派時,所傳入的參數會替代預設參數。
*args是不定長參數,它可以表示輸入參數是不确定的,可以是任意多個。
**kwargs是關鍵字參數,指派的時候是以鍵值對的方式,參數可以是任意多對在定義函數的時候
不确定會有多少參數會傳入時,就可以使用兩個參數
63.Mysql怎麼限制IP通路?
64.帶參數的裝飾器?
帶定長參數的裝飾器
def new_func(func):
def wrappedfun(username, passwd):
if username == 'root' and passwd == '123456789':
print('通過認證')
print('開始執行附加功能')
return func()
else:
print('使用者名或密碼錯誤')
return
return wrappedfun
@new_func
def origin():
print('開始執行函數')
origin('root','123456789')
帶不定長參數的裝飾器
def new_func(func):
def wrappedfun(*parts):
if parts:
counts = len(parts)
print('本系統包含 ', end='')
for part in parts:
print(part, ' ',end='')
print('等', counts, '部分')
return func()
else:
print('使用者名或密碼錯誤')
return func()
return wrappedfun
65.為什麼函數名字可以當做參數用?
Python中一切皆對象,函數名是函數在記憶體中的空間,也是一個對象
66.Python中pass語句的作用是什麼?
在編寫代碼時隻寫架構思路,具體實作還未編寫就可以用pass進行占位,是程式不報錯,不會進行任何操作。
67.有這樣一段代碼,print c會輸出什麼,為什麼?
a = 10
b = 20
c = [a]
a = 15
答:10對于字元串,數字,傳遞是相應的值
68.交換兩個變量的值?
a, b = b, a
69.map函數和reduce函數?
map(lambda x: x * x, [1, 2, 3, 4]) # 使用 lambda
# [1, 4, 9, 16]
reduce(lambda x, y: x * y, [1, 2, 3, 4]) # 相當于 ((1 * 2) * 3) * 4
# 24
70.回調函數,如何通信的?
回調函數是把函數的指針(位址)作為參數傳遞給另一個函數,将整個函數當作一個對象,指派給調用的函數。
71.Python主要的内置資料類型都有哪些? print dir( ‘a ’) 的輸出?
内建類型:布爾類型,數字,字元串,清單,元組,字典,集合
輸出字元串'a'的内建方法
72.map(lambda x:xx,[y for y in range(3)])的輸出?
[0, 1, 4]
73.hasattr() getattr() setattr() 函數使用詳解?
hasattr(object,name)函數:
判斷一個對象裡面是否有name屬性或者name方法,傳回bool值,有name屬性(方法)傳回True,否則傳回False。
class function_demo(object):
name = 'demo'
def run(self):
return "hello function"
functiondemo = function_demo()
res = hasattr(functiondemo, "name") # 判斷對象是否有name屬性,True
res = hasattr(functiondemo, "run") # 判斷對象是否有run方法,True
res = hasattr(functiondemo, "age") # 判斷對象是否有age屬性,False
print(res)
getattr(object, name[,default])函數:
擷取對象object的屬性或者方法,如果存在則列印出來,如果不存在,列印預設值,預設值可選。注意:如果傳回的是對象的方法,則列印結果是:方法的記憶體位址,如果需要運作這個方法,可以在後面添加括号().
functiondemo = function_demo()
getattr(functiondemo, "name")# 擷取name屬性,存在就列印出來 --- demo
getattr(functiondemo, "run") # 擷取run 方法,存在列印出方法的記憶體位址
getattr(functiondemo, "age") # 擷取不存在的屬性,報錯
getattr(functiondemo, "age", 18)# 擷取不存在的屬性,傳回一個預設值
setattr(object, name, values)函數:
給對象的屬性指派,若屬性不存在,先建立再指派
class function_demo(object):
name = "demo"
def run(self):
return "hello function"
functiondemo = function_demo()
res = hasattr(functiondemo, "age") # 判斷age屬性是否存在,False
print(res)
setattr(functiondemo, "age", 18) # 對age屬性進行指派,無傳回值
res1 = hasattr(functiondemo, "age") # 再次判斷屬性是否存在,True
綜合使用
class function_demo(object):
name = "demo"
def run(self):
return "hello function"
functiondemo = function_demo()
res = hasattr(functiondemo, "addr") # 先判斷是否存在
if res:
addr = getattr(functiondemo, "addr")
print(addr)
else:
addr = getattr(functiondemo, "addr", setattr(functiondemo, "addr", "北京首都"))
print(addr)
74.一句話解決階乘函數?
reduce(lambda x,y : x*y,range(1,n+1))
75.什麼是lambda函數? 有什麼好處?
lambda 函數是一個可以接收任意多個參數(包括可選參數)并且傳回單個表達式值的函數
1.lambda函數比較輕便,即用即仍,很适合需要完成一項功能,但是此功能隻在此一處使用,連名字都很随意的情況下
2.匿名函數,一般用來給filter,map這樣的函數式程式設計服務
3.作為回調函數,傳遞給某些應用,比如消息處理
76.遞歸函數停止的條件?
遞歸的終止條件一般定義在遞歸函數内部,在遞歸調用前要做一個條件判斷,根據判斷的結果選擇是繼續調用自身,還是return,,傳回終止遞歸。
終止的條件:判斷遞歸的次數是否達到某一限定值
2.判斷運算的結果是否達到某個範圍等,根據設計的目的來選擇
77.下面這段代碼的輸出結果将是什麼?請解釋。
def multipliers():
return [lambda x: i *x for i in range(4)]
print([m(2) for m in multipliers()])
上面代碼的輸出結果是[6,6,6,6],不是我們想的[0,2,4,6]
你如何修改上面的multipliers的定義産生想要的結果?
上述問題産生的原因是python閉包的延遲綁定。這意味着内部函數被調用時,參數的值在閉包内進行查找。是以,當任何由multipliers()傳回的函數被調用時,i的值将在附近的範圍進行查找。那時,不管傳回的函數是否被調用,for循環已經完成,i被賦予了最終的值3.
def multipliers():
for i in range(4):
yield lambda x: i *x
def multipliers():
return [lambda x,i = i: i*x for i in range(4)]
78.什麼是lambda函數?它有什麼好處?寫一個匿名函數求兩個數的和
lambda函數是匿名函數,使用lambda函數能建立小型匿名函數,這種函數得名于省略了用def聲明函數的标準步驟
設計模式
79.對設計模式的了解,簡述你了解的設計模式?
設計模式是經過總結,優化的,對我們經常會碰到的一些程式設計問題的可重用解決方案。一個設計模式并不像一個類或一個庫那樣能夠直接作用于我們的代碼,反之,設計模式更為進階,它是一種必須在特定情形下實作的一種方法模闆。 常見的是工廠模式和單例模式
80.請手寫一個單例
#python2
class A(object):
__instance = None
def __new__(cls,*args,**kwargs):
if cls.__instance is None:
cls.__instance = objecet.__new__(cls)
return cls.__instance
else:
return cls.__instance
81.單例模式的應用場景有那些?
單例模式應用的場景一般發現在以下條件下: 資源共享的情況下,避免由于資源操作時導緻的性能或損耗等,如日志檔案,應用配置。 控制資源的情況下,友善資源之間的互相通信。如線程池等,1,網站的計數器 2,應用配置 3.多線程池 4資料庫配置 資料庫連接配接池 5.應用程式的日志應用...
82.用一行代碼生成[1,4,9,16,25,36,49,64,81,100]
print([x*x for x in range(1, 11)])
83.對裝飾器的了解,并寫出一個計時器記錄方法執行性能的裝飾器?
裝飾器本質上是一個callable object ,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的傳回值也是一個函數對象。
import time
from functools import wraps
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.clock()
ret = func(*args, **kwargs)
end = time.clock()
print('used:',end-start)
return ret
return wrapper
@timeit
def foo():
print('in foo()'foo())
84.解釋以下什麼是閉包?
在函數内部再定義一個函數,并且這個函數用到了外邊函數的變量,那麼将這個函數以及用到的一些變量稱之為閉包。
85.函數裝飾器有什麼作用?
裝飾器本質上是一個callable object,它可以在讓其他函數在不需要做任何代碼的變動的前提下增加額外的功能。裝飾器的傳回值也是一個函數的對象,它經常用于有切面需求的場景。比如:插入日志,性能測試,事務處理,緩存。權限的校驗等場景,有了裝飾器就可以抽離出大量的與函數功能本身無關的雷同代碼并發并繼續使用。 詳細參考:https://manjusaka.itscoder.com/2018/02/23/something-about-decorator/
86.生成器,疊代器的差別?
疊代器是遵循疊代協定的對象。使用者可以使用 iter() 以從任何序列得到疊代器(如 list, tuple, dictionary, set 等)。另一個方法則是建立一個另一種形式的疊代器 —— generator 。要擷取下一個元素,則使用成員函數 next()(Python 2)或函數 next() function (Python 3) 。當沒有元素時,則引發 StopIteration 此例外。若要實作自己的疊代器,則隻要實作 next()(Python 2)或
__next__
()( Python 3)
生成器(Generator),隻是在需要傳回資料的時候使用yield語句。每次next()被調用時,生成器會傳回它脫離的位置(它記憶語句最後一次執行的位置和所有的資料值)
差別: 生成器能做到疊代器能做的所有事,而且因為自動建立iter()和next()方法,生成器顯得特别簡潔,而且生成器也是高效的,使用生成器表達式取代清單解析可以同時節省記憶體。除了建立和儲存程式狀态的自動方法,當發生器終結時,還會自動抛出StopIteration異常。
官方介紹:https://docs.python.org/3/tutorial/classes.html#iterators
87.X是什麼類型?
X= (i for i in range(10))
X是 generator類型
88.請用一行代碼 實作将1-N 的整數清單以3為機關分組
N =100
print ([[x for x in range(1,100)] [i:i+3] for i in range(0,100,3)])
89.Python中yield的用法?
yield就是儲存目前程式執行狀态。你用for循環的時候,每次取一個元素的時候就會計算一次。用yield的函數叫generator,和iterator一樣,它的好處是不用一次計算所有元素,而是用一次算一次,可以節省很多空間,generator每次計算需要上一次計算結果,是以用yield,否則一return,上次計算結果就沒了
面向對象
90.Python中的可變對象和不可變對象?
不可變對象,該對象所指向的記憶體中的值不能被改變。當改變某個變量時候,由于其所指的值不能被改變,相當于把原來的值複制一份後再改變,這會開辟一個新的位址,變量再指向這個新的位址。
可變對象,該對象所指向的記憶體中的值可以被改變。變量(準确的說是引用)改變後,實際上其所指的值直接發生改變,并沒有發生複制行為,也沒有開辟出新的位址,通俗點說就是原地改變。
Pyhton中,數值類型(int 和float),字元串str、元祖tuple都是不可變類型。而清單list、字典dict、集合set是可變類型
91.Python的魔法方法
魔法方法就是可以給你的類增加魔力的特殊方法,如果你的對象實作(重載)了這些方法中的某一個,那麼這個方法就會在特殊的情況下被Python所調用,你可以定義自己想要的行為,而這一切都是自動發生的,它們經常是兩個下劃線包圍來命名的(比如
__init___
,
__len__
),Python的魔法方法是非常強大的是以了解其使用方法也變得尤為重要!
__init__
構造器,當一個執行個體被建立的時候初始化的方法,但是它并不是執行個體化調用的第一個方法。
__new__
才是執行個體化對象調用的第一個方法,它隻取下cls參數,并把其他參數傳給
__init___
.
___new__
很少使用,但是也有它适合的場景,尤其是當類繼承自一個像元祖或者字元串這樣不經常改變的類型的時候。
__call__
讓一個類的執行個體像函數一樣被調用
__getitem__
定義擷取容器中指定元素的行為,相當于self[key]
__getattr__
定義當使用者試圖通路一個不存在屬性的時候的行為。
__setattr__
定義當一個屬性被設定的時候的行為
__getattribute___
定義當一個屬性被通路的時候的行為
92.面向對象中怎麼實作隻讀屬性?
将對象私有化,通過共有方法提供一個讀取資料的接口
class person:
def __init__(self, x):
self.__age = 10
def age(self):
return self.__age
t = person(22)
# t.__age =100
print(t.age())
最好的方法
class MyCls(object):
__weight = 50
@property
def weight(self):
return self.__weight
93.談談你對面向對象的了解?
面向對象是相當于面向過程而言的,面向過程語言是一種基于功能分析的,以算法為中心的程式設計方法,而面向對象是一種基于結構分析的,以資料為中心的程式設計思想。在面向對象語言中有一個很重要的東西,叫做類。面向對象有三大特性:封裝、繼承、多态。
正規表達式
94.請寫出一段代碼用正則比對出ip?
95.a = “abbbccc”,用正則比對為abccc,不管有多少b,就出現一次?
96.Python字元串查找和替換?
97.用Python比對HTML g tag的時候,<.> 和 <.*?> 有什麼差別
98.正規表達式貪婪與非貪婪模式的差別?
99.寫出開頭比對字母和下劃線,末尾是數字的正規表達式?
100.正規表達式操作
101.請比對出變量A 中的json字元串。
102.怎麼過濾評論中的表情?
103.簡述Python裡面search和match的差別
104.請寫出比對ip的Python正規表達式
105.Python裡match與search的差別?
系統程式設計
106.程序總結
程序:程式運作在作業系統上的一個執行個體,就稱之為程序。程序需要相應的系統資源:記憶體、時間片、pid。 建立程序: 首先要導入multiprocessing中的Process: 建立一個Process對象; 建立Process對象時,可以傳遞參數;
p = Process(target=XXX,args=(tuple,),kwargs={key:value})
target = XXX 指定的任務函數,不用加(),
args=(tuple,)kwargs={key:value}給任務函數傳遞的參數
使用start()啟動程序 結束程序 給子程序指定函數傳遞參數Demo
import os
from mulitprocessing import Process
import time
def pro_func(name,age,**kwargs):
for i in range(5):
print("子程序正在運作中,name=%s,age=%d,pid=%d"%(name,age,os.getpid()))
print(kwargs)
time.sleep(0.2)
if __name__ =="__main__":
#建立Process對象
p = Process(target=pro_func,args=('小明',18),kwargs={'m':20})
#啟動程序
p.start()
time.sleep(1)
#1秒鐘之後,立刻結束子程序
p.terminate()
p.join()
注意:程序間不共享全局變量
程序之間的通信-Queue
在初始化Queue()對象時(例如q=Queue(),若在括号中沒有指定最大可接受的消息數量,獲數量為負值時,那麼就代表可接受的消息數量沒有上限一直到記憶體盡頭)
Queue.qsize():傳回目前隊列包含的消息數量
Queue.empty():如果隊列為空,傳回True,反之False
Queue.full():如果隊列滿了,傳回True,反之False
Queue.get([block[,timeout]]):擷取隊列中的一條消息,然後将其從隊列中移除,
block預設值為True。
如果block使用預設值,且沒有設定timeout(機關秒),消息隊列如果為空,此時程式将被阻塞(停在讀中狀态),直到消息隊列讀到消息為止,如果設定了timeout,則會等待timeout秒,若還沒讀取到任何消息,則抛出“Queue.Empty"異常:
Queue.get_nowait()相當于Queue.get(False)
Queue.put(item,[block[,timeout]]):将item消息寫入隊列,block預設值為True; 如果block使用預設值,且沒有設定timeout(機關秒),消息隊列如果已經沒有空間可寫入,此時程式将被阻塞(停在寫入狀态),直到從消息隊列騰出空間為止,如果設定了timeout,則會等待timeout秒,若還沒空間,則抛出”Queue.Full"異常 如果block值為False,消息隊列如果沒有空間可寫入,則會立刻抛出"Queue.Full"異常; Queue.put_nowait(item):相當Queue.put(item,False)
程序間通信Demo:
from multiprocessing import Process.Queue
import os,time,random
#寫資料程序執行的代碼:
def write(q):
for value in ['A','B','C']:
print("Put %s to queue...",%value)
q.put(value)
time.sleep(random.random())
#讀資料程序執行的代碼
def read(q):
while True:
if not q.empty():
value = q.get(True)
print("Get %s from queue.",%value)
time.sleep(random.random())
else:
break
if __name__=='__main__':
#父程序建立Queue,并傳給各個子程序
q = Queue()
pw = Process(target=write,args=(q,))
pr = Process(target=read,args=(q,))
#啟動子程序pw ,寫入:
pw.start()
#等待pw結束
pw.join()
#啟動子程序pr,讀取:
pr.start()
pr.join()
#pr 程序裡是死循環,無法等待其結束,隻能強行終止:
print('')
print('所有資料都寫入并且讀完')
程序池Pool
#coding:utf-8
from multiprocessing import Pool
import os,time,random
def worker(msg):
t_start = time.time()
print("%s 開始執行,程序号為%d"%(msg,os.getpid()))
# random.random()随機生成0-1之間的浮點數
time.sleep(random.random()*2)
t_stop = time.time()
print(msg,"執行完畢,耗時%0.2f”%(t_stop-t_start))
po = Pool(3)#定義一個程序池,最大程序數3
for i in range(0,10):
po.apply_async(worker,(i,))
print("---start----")
po.close()
po.join()
print("----end----")
程序池中使用Queue
如果要使用Pool建立程序,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue(),否則會得到如下的錯誤資訊:
RuntimeError: Queue objects should only be shared between processs through inheritance
from multiprocessing import Manager,Pool
import os,time,random
def reader(q):
print("reader 啟動(%s),父程序為(%s)"%(os.getpid(),os.getpid()))
for i in range(q.qsize()):
print("reader 從Queue擷取到消息:%s"%q.get(True))
def writer(q):
print("writer 啟動(%s),父程序為(%s)"%(os.getpid(),os.getpid()))
for i ini "itcast":
q.put(i)
if __name__ == "__main__":
print("(%s)start"%os.getpid())
q = Manager().Queue()#使用Manager中的Queue
po = Pool()
po.apply_async(wrtier,(q,))
time.sleep(1)
po.apply_async(reader,(q,))
po.close()
po.join()
print("(%s)End"%os.getpid())
107.談談你對多程序,多線程,以及協程的了解,項目是否用?
這個問題被問的概念相當之大, 程序:一個運作的程式(代碼)就是一個程序,沒有運作的代碼叫程式,程序是系統資源配置設定的最小機關,程序擁有自己獨立的記憶體空間,所有程序間資料不共享,開銷大。
線程: cpu排程執行的最小機關,也叫執行路徑,不能獨立存在,依賴程序存在,一個程序至少有一個線程,叫主線程,而多個線程共享記憶體(資料共享,共享全局變量),進而極大地提高了程式的運作效率。
協程: 是一種使用者态的輕量級線程,協程的排程完全由使用者控制。協程擁有自己的寄存器上下文和棧。協程排程時,将寄存器上下文和棧儲存到其他地方,在切回來的時候,恢複先前儲存的寄存器上下文和棧,直接操中棧則基本沒有核心切換的開銷,可以不加鎖的通路全局變量,是以上下文的切換非常快。
108.Python異常使用場景有那些?
異步的使用場景:
1、 不涉及共享資源,獲對共享資源隻讀,即非互斥操作
2、 沒有時序上的嚴格關系
3、 不需要原子操作,或可以通過其他方式控制原子性
4、 常用于IO操作等耗時操作,因為比較影響客戶體驗和使用性能
5、 不影響主線程邏輯
109.多線程共同操作同一個資料互斥鎖同步?
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire(1):
num +=1
msg = self.name + 'set num to ' +str(num)
print msg
mutex.release()
num = 0
mutex = threading.Lock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__=="__main__":
test()
110.什麼是多線程競争?
線程是非獨立的,同一個程序裡線程是資料共享的,當各個線程通路資料資源時會出現競争狀态即:資料幾乎同步會被多個線程占用,造成資料混亂,即所謂的線程不安全
那麼怎麼解決多線程競争問題?---鎖
鎖的好處: 確定了某段關鍵代碼(共享資料資源)隻能由一個線程從頭到尾完整地執行能解決多線程資源競争下的原子操作問題。
鎖的壞處: 阻止了多線程并發執行,包含鎖的某段代碼實際上隻能以單線程模式執行,效率就大大地下降了
鎖的緻命問題: 死鎖
111.請介紹一下Python的線程同步?
一、 setDaemon(False) 當一個程序啟動之後,會預設産生一個主線程,因為線程是程式執行的最小機關,當設定多線程時,主線程會建立多個子線程,在Python中,預設情況下就是setDaemon(False),主線程執行完自己的任務以後,就退出了,此時子線程會繼續執行自己的任務,直到自己的任務結束。
例子
import threading
import time
def thread():
time.sleep(2)
print('---子線程結束---')
def main():
t1 = threading.Thread(target=thread)
t1.start()
print('---主線程--結束')
if __name__ =='__main__':
main()
#執行結果
---主線程--結束
---子線程結束---
二、 setDaemon(True) 當我們使用setDaemon(True)時,這是子線程為守護線程,主線程一旦執行結束,則全部子線程被強制終止
例子
import threading
import time
def thread():
time.sleep(2)
print(’---子線程結束---')
def main():
t1 = threading.Thread(target=thread)
t1.setDaemon(True)#設定子線程守護主線程
t1.start()
print('---主線程結束---')
if __name__ =='__main__':
main()
#執行結果
---主線程結束--- #隻有主線程結束,子線程來不及執行就被強制結束
三、 join(線程同步) join 所完成的工作就是線程同步,即主線程任務結束以後,進入堵塞狀态,一直等待所有的子線程結束以後,主線程再終止。
當設定守護線程時,含義是主線程對于子線程等待timeout的時間将會殺死該子線程,最後退出程式,是以說,如果有10個子線程,全部的等待時間就是每個timeout的累加和,簡單的來說,就是給每個子線程一個timeou的時間,讓他去執行,時間一到,不管任務有沒有完成,直接殺死。
沒有設定守護線程時,主線程将會等待timeout的累加和這樣的一段時間,時間一到,主線程結束,但是并沒有殺死子線程,子線程依然可以繼續執行,直到子線程全部結束,程式退出。
例子
import threading
import time
def thread():
time.sleep(2)
print('---子線程結束---')
def main():
t1 = threading.Thread(target=thread)
t1.setDaemon(True)
t1.start()
t1.join(timeout=1)#1 線程同步,主線程堵塞1s 然後主線程結束,子線程繼續執行
#2 如果不設定timeout參數就等子線程結束主線程再結束
#3 如果設定了setDaemon=True和timeout=1主線程等待1s後會強制殺死子線程,然後主線程結束
print('---主線程結束---')
if __name__=='__main___':
main()
112.解釋以下什麼是鎖,有哪幾種鎖?
鎖(Lock)是python提供的對線程控制的對象。有互斥鎖,可重入鎖,死鎖。
113.什麼是死鎖?
若幹子線程在系統資源競争時,都在等待對方對某部分資源解除占用狀态,結果是誰也不願先解鎖,互相幹等着,程式無法執行下去,這就是死鎖。
GIL鎖 全局解釋器鎖
作用: 限制多線程同時執行,保證同一時間隻有一個線程執行,是以cython裡的多線程其實是僞多線程!
是以python裡常常使用協程技術來代替多線程,協程是一種更輕量級的線程。
程序和線程的切換時由系統決定,而協程由我們程式員自己決定,而子產品gevent下切換是遇到了耗時操作時才會切換
三者的關系:程序裡有線程,線程裡有協程。
114.多線程互動通路資料,如果通路到了就不通路了?
怎麼避免重讀?
建立一個已通路資料清單,用于存儲已經通路過的資料,并加上互斥鎖,在多線程通路資料的時候先檢視資料是否在已通路的清單中,若已存在就直接跳過。
115.什麼是線程安全,什麼是互斥鎖?
每個對象都對應于一個可稱為’互斥鎖‘的标記,這個标記用來保證在任一時刻,隻能有一個線程通路該對象。
同一程序中的多線程之間是共享系統資源的,多個線程同時對一個對象進行操作,一個線程操作尚未結束,另一線程已經對其進行操作,導緻最終結果出現錯誤,此時需要對被操作對象添加互斥鎖,保證每個線程對該對象的操作都得到正确的結果。
116.說說下面幾個概念:同步,異步,阻塞,非阻塞?
同步: 多個任務之間有先後順序執行,一個執行完下個才能執行。
異步: 多個任務之間沒有先後順序,可以同時執行,有時候一個任務可能要在必要的時候擷取另一個同時執行的任務的結果,這個就叫回調!
阻塞: 如果卡住了調用者,調用者不能繼續往下執行,就是說調用者阻塞了。
非阻塞: 如果不會卡住,可以繼續執行,就是說非阻塞的。
同步異步相對于多任務而言,阻塞非阻塞相對于代碼執行而言。
117.什麼是僵屍程序和孤兒程序?怎麼避免僵屍程序?
孤兒程序: 父程序退出,子程序還在運作的這些子程序都是孤兒程序,孤兒程序将被init 程序(程序号為1)所收養,并由init 程序對他們完成狀态收集工作。
僵屍程序: 程序使用fork 建立子程序,如果子程序退出,而父程序并沒有調用wait 獲waitpid 擷取子程序的狀态資訊,那麼子程序的程序描述符仍然儲存在系統中的這些程序是僵屍程序。
避免僵屍程序的方法:
1.fork 兩次用孫子程序去完成子程序的任務
2.用wait()函數使父程序阻塞
3.使用信号量,在signal handler 中調用waitpid,這樣父程序不用阻塞
118.python中程序與線程的使用場景?
多程序适合在CPU密集操作(cpu操作指令比較多,如位多的的浮點運算)。
多線程适合在IO密性型操作(讀寫資料操作比多的的,比如爬蟲)
119.線程是并發還是并行,程序是并發還是并行?
線程是并發,程序是并行;
程序之間互相獨立,是系統配置設定資源的最小機關,同一個線程中的所有線程共享資源。
120.并行(parallel)和并發(concurrency)?
并行: 同一時刻多個任務同時在運作
不會在同一時刻同時運作,存在交替執行的情況。
實作并行的庫有: multiprocessing
實作并發的庫有: threading
程式需要執行較多的讀寫、請求和回複任務的需要大量的IO操作,IO密集型操作使用并發更好。
CPU運算量大的程式,使用并行會更好
121.IO密集型和CPU密集型差別?
IO密集型: 系統運作,大部分的狀況是CPU在等 I/O(硬碟/記憶體)的讀/寫