Time will tell.
1激挪、說說Python和其他語言的區(qū)別
Python屬于解釋型語言宛篇,當程序運行時,是一行一行的解釋段标,并運行,所以調(diào)式代碼很方便赛糟,開發(fā)效率高。
Python定位是任其自由發(fā)展、優(yōu)雅动知、明確、簡單丹皱,所以在每個領域都有建樹,所有它有著非常強大的第三方庫。
特點:
Python的類庫齊全并且使用簡潔阔墩,語法簡潔優(yōu)美耸彪,功能強大,標準庫與第三方庫都非常強大召川,而且應用領域也非常廣。可移植性峰搪,可擴展性凯旭,可嵌入性概耻。
缺點:
運行速度慢。
區(qū)別:
(1)與java相比罐呼,在很多方面念逞,Python比Java要簡單褪测,比如java中所有變量必須聲明才能使用炫隶,而Python不需要聲明,用少量的代碼構建出很多功能;(高效的高級數(shù)據(jù)結(jié)構)县好。
(2)與php相比妖混,python標準包直接提供了工具少漆,并且相對于PHP代碼更易于維護厅须。
(3)Python與c相比:Python 和 C Python這門語言是由C開發(fā)而來侧馅。
2危尿、Python有什么特點?
- 用少量的代碼構建出很多功能(高效的高級數(shù)據(jù)結(jié)構)
- Python 擁有最成熟的程序包資源庫之一
- Python完全支持面向?qū)ο?/li>
- Python 是跨平臺且開源的
- 動態(tài)類型
3馁痴、簡述解釋型和編譯型編程語言
- 解釋型:就是邊解釋邊執(zhí)行(Python谊娇,php)
- 編譯型:編譯后再執(zhí)行(c、java罗晕、c#)
4济欢、Python的解釋器種類及相關特點是什么赠堵?
CPython
-
當我們從Python官方網(wǎng)站下載并安裝好Python 3.6后,我們就直接獲得了一個官方版本的解釋器:CPython法褥。這個解釋器是用C語言開發(fā)的茫叭,所以叫CPython。在命令行下運行python就是啟動CPython解釋器半等。
CPython是使用最廣的Python解釋器揍愁。教程的所有代碼也都在CPython下執(zhí)行。
IPython
-
IPython是基于CPython之上的一個交互式解釋器杀饵,也就是說莽囤,IPython只是在交互方式上有所增強,但是執(zhí)行Python代碼的功能和CPython是完全一樣的切距。好比很多國產(chǎn)瀏覽器雖然外觀不同朽缎,但內(nèi)核其實都是調(diào)用了IE。
CPython用>>>作為提示符蔚舀,而IPython用In [序號]:作為提示符饵沧。
PyPy
-
PyPy是另一個Python解釋器,它的目標是執(zhí)行速度赌躺。PyPy采用JIT技術狼牺,對Python代碼進行動態(tài)編譯(注意不是解釋),所以可以顯著提高Python代碼的執(zhí)行速度礼患。
絕大部分Python代碼都可以在PyPy下運行是钥,但是PyPy和CPython有一些是不同的,這就導致相同的Python代碼在兩種解釋器下執(zhí)行可能會有不同的結(jié)果缅叠。如果你的代碼要放到PyPy下執(zhí)行悄泥,就需要了解PyPy和CPython的不同點。
Jython
- Jython是運行在Java平臺上的Python解釋器肤粱,可以直接把Python代碼編譯成Java字節(jié)碼執(zhí)行弹囚。
IronPython
- IronPython和Jython類似,只不過IronPython是運行在微軟.Net平臺上的Python解釋器领曼,可以直接把Python代碼編譯成.Net的字節(jié)碼鸥鹉。
Python的解釋器有很多,但使用最廣泛的還是CPython庶骄。如果要和Java或.Net平臺交互毁渗,最好的辦法不是用Jython或IronPython,而是通過網(wǎng)絡調(diào)用來交互单刁,確保各程序之間的獨灸异。
如果你對更多內(nèi)容、及Python實例練習題、面試題肺樟、自動化軟件測試感興趣的話可以加入我們175317069一起學習喔檐春。
5、位和字節(jié)的關系
位(bit)儡嘶,1字節(jié) = 8 位喇聊。數(shù)據(jù)存儲是以“字節(jié)”(Byte)為單位,數(shù)據(jù)傳輸是以大多是以“位”(又名“比特”)為單位蹦狂。
一個位就代表一個0或1(即一個二進制)誓篱,二進制是構成存儲器的最小單位,每8個位(bit凯楔,簡寫為b)組成一個字節(jié)(Byte窜骄,簡寫為B),字節(jié)是最小一級的信息單位摆屯。
6邻遏、b、B虐骑、KB准验、MB、GB的關系
b —> 位(bit)
B —> 字節(jié)(一個字節(jié)等于8位)
1B = 8 bit
1kb = 1024 B
1 MB = 1024 KB
1 GB = 1024 MB
7廷没、PE8規(guī)范
- 使用4個空格而不是tab鍵進行縮進
- 每行長度不能超過79
- 使用空行來間隔函數(shù)和類糊饱,以及函數(shù)內(nèi)部的大塊代碼
- 必要時候,在每一行下寫注釋
- 使用文檔注釋颠黎,寫出函數(shù)注釋
- 在操作符和逗號之后使用空格另锋,但是不要在括號內(nèi)部使用
- 命名類和函數(shù)的時候使用一致的方式,比如使用CamelCase來命名類狭归,使用lower_case_with_underscores來命名函數(shù)和方法
- 在類中總是使用self來作為默認
- 盡量不要使用魔法方法
- 默認使用UTF-8夭坪,甚至ASCII作為編碼方式
- 換行可以使用反斜杠,最好使用圓括號
- 不要在一句import中多個庫
8过椎、通過代碼實現(xiàn)如下轉(zhuǎn)換(進制之間轉(zhuǎn)換)
# 二進制轉(zhuǎn)換成十進制-->int
v = "0b1111011"
b = int(v,2)
print(b) # 123
# 十進制轉(zhuǎn)換成二進制--->bin
v2 = 18
print(bin(int(v2)))
# 0b10010
# 八進制轉(zhuǎn)換成十進制
v3 = "011"
print(int(v3))
# 11
# 十進制轉(zhuǎn)換成八進制:---> oct
v4 = 30
print(oct(int(v4)))
# 0o36
# 十六進制轉(zhuǎn)換成十進制:
v5 = "0x12"
print(int(v5,16))
# 18
# 十進制轉(zhuǎn)換成十六進制:---> hex
v6 = 87
print(hex(int(v6)))
# 0x57
9室梅、請編寫一個函數(shù)實現(xiàn)將IP地址轉(zhuǎn)換成一個整數(shù)
請編寫一個函數(shù)實現(xiàn)將IP地址轉(zhuǎn)換成一個整數(shù)。
如 10.3.9.12 轉(zhuǎn)換規(guī)則為:
10 00001010
3 00000011
9 00001001
12 00001100
再將以上二進制拼接起來計算十進制結(jié)果:00001010 00000011 00001001 00001100 = 疚宇?
def v1(addr):
# 取每個數(shù)
id = [int(x) for x in addr.split(".")]
print(id)
return sum(id[i] << [24, 16, 8, 0][i] for i in range(4))
print(v1("127.0.0.1"))
# [127, 0, 0, 1]
# 2130706433
10亡鼠、ascii、unicode灰嫉、utf-8、gbk的區(qū)別
python2內(nèi)容進行編碼(默認ascii),而python3對內(nèi)容進行編碼的默認為utf-8
ascii:最多只能用8位來表示(一個字節(jié))嗓奢,即:2**8 = 256讼撒,所以,ASCII碼最多只能表示 256 個符號。
unicode:萬國碼根盒,任何一個字符==兩個字節(jié)
utf-8:萬國碼的升級版 一個中文字符 == 三個字節(jié) 英文是一個字節(jié) 歐洲的是 2個字節(jié)
gbk:國內(nèi)版本 一個中文字符==2個字節(jié) 英文是一個字節(jié)
gbk 轉(zhuǎn) utf-8 需通過媒介 unicode
11钳幅、字節(jié)碼和機器碼的區(qū)別
機器碼,學名機器語言指令敢艰,有時也被稱為原生碼,是電腦的CPU可直接解讀的數(shù)據(jù)牡属。
字節(jié)碼是一種中間狀態(tài)(中間碼)的二進制代碼(文件)。需要直譯器轉(zhuǎn)譯后才能成為機器碼措伐。
字節(jié)碼是一種中間狀態(tài)(中間碼)的二進制代碼(文件)。需要直譯器轉(zhuǎn)譯后才能成為機器碼官硝。
如果你對更多內(nèi)容氢架、及Python實例練習題、面試題孙援、自動化軟件測試感興趣的話可以加入我們175317069一起學習喔。
12础淤、三元運算寫法和應用場景
應用場景:簡化if語句
# 關于三元運算
# 結(jié)果+ if + 條件 + else + 結(jié)果
result='gt' if 1>3 else 'lt'
print(result) # lt
# 理解:如果條件為真币砂,把if前面的值賦值給變量,否則把else后面的值賦值給變量。
lambda 表達式
temp = lambda x,y:x+y
print(temp(4,10)) # 14
可替代:
def foo(x,y):
return x+y
print(foo(4,10)) # 14
13拘鞋、Python3和Python2中的 int 和 long 的區(qū)別
在python3里,只有一種整數(shù)類型int,大多數(shù)情況下,和python2中的長整型類似宣旱。
14、xrange 和 range 的區(qū)別
都在循環(huán)時使用,xrange內(nèi)存性能更好燎字,xrange用法與range完全相同,range一個生成list對象,xrange是生成器妖异。
要生成很大的數(shù)字序列的時候,用xrange會比range性能優(yōu)很多,因為不需要一上來就開辟一塊很大的內(nèi)存空間。
在python2中:
range([start,] stop[, step]),根據(jù)start與stop指定的范圍以及step設定的步長误甚,生成一個序列
xrange用法與range完全相同,所不同的是生成的不是一個數(shù)組,而是一個生成器瞧筛。
在Python 3中:
- range() 是像 xrange() 那樣實現(xiàn)认轨,xrange()被拋棄恩急。
15纯续、文件操作時xreadlines和readlines的區(qū)別
readlines:返回一個列表
xreadlines:返回一個生成器
16茸歧、 lambda表達式格式以及應用場景是什么涤浇?
匿名函數(shù):為了解決那些功能很簡單的需求而設計的一句話函數(shù)
函數(shù)名 = lambda 參數(shù) :返回值
#參數(shù)可以有多個魔慷,用逗號隔開
#匿名函數(shù)不管邏輯多復雜只锭,只能寫一行,且邏輯執(zhí)行結(jié)束后的內(nèi)容就是返回值
#返回值和正常的函數(shù)一樣可以是任意數(shù)據(jù)類型
lambda 表達式
temp = lambda x,y:x+y
print(temp(4,10)) # 14
可替代:
def foo(x,y):
return x+y
print(foo(4,10)) # 14
17院尔、說說pass的作用
pass 是空語句蜻展,是為了保持程序結(jié)構的完整性。pass 不做任何事情邀摆,一般用做占位語句铺呵。
18、*arg 和 **kwarg 作用
*args代表位置參數(shù)隧熙,它會接收任意多個參數(shù)并把這些參數(shù)作為元祖?zhèn)鬟f給函數(shù)片挂。
**kwargs代表的關鍵字參數(shù),返回的是字典贞盯,位置參數(shù)一定要放在關鍵字前面音念。
19、 is和==的區(qū)別
a = 'lishi'
str1 = "li"
str2 = "shi"
str3 = str1 + str2
print("a == str3",a == str3)
print("a is str3",a is str3)
print("id(a)",id(a))
print("id(str3)",id(str3))
# a == str3 True == ---> 只需要內(nèi)容相等
# a is str3 False is ---> 只需要內(nèi)存地址相等
# id(a) 38565848
# id(str3) 39110280
is 比較的是兩個實例對象是不是完全相同躏敢,它們是不是同一個對象闷愤,占用的內(nèi)存地址是否相同。
== 比較的是兩個對象的內(nèi)容是否相等件余,即內(nèi)存地址可以不一樣讥脐,內(nèi)容一樣就可以了。默認會調(diào)用對象的__eq__()
方法啼器。
20旬渠、談談Python的深淺拷貝,以及實現(xiàn)方法和應用場景
淺拷貝只是增加了一個指針指向一個存在的地址端壳。
而深拷貝是增加一個指針并且開辟了新的內(nèi)存告丢,這個增加的指針指向這個新的內(nèi)存,采用淺拷貝的情況损谦,釋放內(nèi)存岖免,會釋放同一內(nèi)存岳颇,深拷貝就不會出現(xiàn)釋放同一內(nèi)存的錯誤。
一層的情況:
import copy
# 淺拷貝
li1 = [1, 2, 3]
li2 = li1.copy()
li1.append(4)
print(li1, li2) # [1, 2, 3, 4] [1, 2, 3]
# 深拷貝
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垃圾回收機制
引用計數(shù)
標記清除
分代回收
21话侧、Python的可變類型和不可變類型?
可變數(shù)據(jù)類型:列表闯参、字典掂摔、可變集合。
不可變數(shù)據(jù)類型:數(shù)字赢赊、字符串、元組级历、不可變集合释移。
22、 常用模塊都有那些寥殖?
re模塊玩讳,os模塊,json模塊嚼贡,time模塊熏纯,爬蟲里面的requests/beautifulsoup4(bs4)。
23粤策、re的match和search區(qū)別樟澜?
re.match 嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話叮盘,match()就返回none秩贰。
re.search 掃描整個字符串并返回第一個成功的匹配。
24柔吼、什么是正則的貪婪匹配毒费?
匹配一個字符串沒有節(jié)制,能匹配多少就去匹配多少愈魏,知道沒有匹配的為止觅玻。
25、def func(a,b=[]) 這種寫法有什么問題培漏?
def func(a,b = []):
b.append(1)
print(a,b)
func(a=2)
func(2)
func(2)
'''
2 [1]
2 [1, 1]
2 [1, 1, 1]
函數(shù)的默認參數(shù)是一個list 當?shù)谝淮螆?zhí)行的時候?qū)嵗艘粋€list
第二次執(zhí)行還是用第一次執(zhí)行的時候?qū)嵗牡刂反鎯?
所以三次執(zhí)行的結(jié)果就是 [1, 1, 1] 想每次執(zhí)行只輸出[1] 溪厘,默認參數(shù)應該設置為None
'''
26、如何實現(xiàn) “1,2,3” 變成 [‘1’,’2’,’3’]牌柄?
list("1,2,3".split(','))
27桩匪、如何實現(xiàn)[‘1’,’2’,’3’]變成[1,2,3]?
[int(x) for x in ['1','2','3']]
a = ['1','2','3']
b = [int(i) for i in a]
print(b)
# [1, 2, 3]
28友鼻、用代碼實現(xiàn)刪除列表中重復的值
list(set([1, 2, 3, 4, 45, 1, 2, 343, 2, 2]))
29傻昙、如何在函數(shù)中設置一個全局變量
python中的global語句是被用來聲明全局變量的闺骚。
x = 2
def func():
global x
x = 1
return x
func()
print(x) # 1
30、logging模塊的作用以及應用場景是什么妆档?
logging:模塊定義的函數(shù)和類為應用程序和庫的開發(fā)實現(xiàn)了一個靈活的事件日志系統(tǒng)僻爽。
作用:
- 可以了解程序運行情況,是否正常
- 在程序的出現(xiàn)故障快速定位出錯地方及故障分析
31贾惦、用代碼簡答實現(xiàn)stack
- Stack() 創(chuàng)建一個新的空棧
- push(item) 添加一個新的元素item到棧頂
- pop() 彈出棧頂元素
- peek() 返回棧頂元素
- is_empty() 判斷棧是否為空
- size() 返回棧的元素個數(shù)
# 實現(xiàn)一個棧stack,后進先出
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
# 判斷是否為空
return self.items == []
def push(self,item):
# 加入元素
self.items.append(item)
def pop(self):
# 彈出元素
return self.items.pop()
def peek(self):
# 返回棧頂元素
return self.items[len(self.items)-1]
def size(self):
# 返回棧的大小
return len(self.items)
if __name__ == "__main__":
stack = Stack()
stack.push("H")
stack.push("E")
stack.push("L")
print(stack.size()) # 3
print(stack.peek()) # L
print(stack.pop()) # L
print(stack.pop()) # E
print(stack.pop()) # H
32胸梆、常用字符串格式化哪幾種?
1.占位符%
%d 表示那個位置是整數(shù)须板;%f 表示浮點數(shù)碰镜;%s 表示字符串。
print('Hello,%s' % 'Python')
print('Hello,%d%s%.2f' % (666, 'Python', 9.99)) # 打酉肮濉:Hello,666Python10.00
2.format
print('{k} is {v}'.format(k='python', v='easy')) # 通過關鍵字
print('{0} is {1}'.format('python', 'easy')) # 通過關鍵字
33绪颖、簡述生成器、迭代器甜奄、可迭代對象以及應用場景
迭代器
- 含有iter和next方法 (包含next方法的可迭代對象就是迭代器)
生成器
- 包括含有yield這個關鍵字柠横,生成器也是迭代器,調(diào)動next把函數(shù)變成迭代器课兄。
應用場景:
range/xrange
py2: range(1000000) ,會立即創(chuàng)建牍氛,xrange(1000000)生成器
py3:range(10000000)生成器
可迭代對象
一個類內(nèi)部實現(xiàn)iter方法且返回一個迭代器。
應用場景:
- wtforms中對form對象進行循環(huán)時候烟阐,顯示form中包含的所有字段搬俊。
class LoginForm(Form):
name = simple.StringField(
label='用戶名',
validators=[
validators.DataRequired(message='用戶名不能為空.'),
validators.Length(min=6, max=18, message='用戶名長度必須大于%(min)d且小于%(max)d')
],
widget=widgets.TextInput(),
render_kw={'class': 'form-control'}
)
pwd = simple.PasswordField(
label='密碼',
validators=[
validators.DataRequired(message='密碼不能為空.'),
validators.Length(min=8, message='用戶名長度必須大于%(min)d'),
validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}",
message='密碼至少8個字符,至少1個大寫字母蜒茄,1個小寫字母悠抹,1個數(shù)字和1個特殊字符')
],
widget=widgets.PasswordInput(),
render_kw={'class': 'form-control'}
)
form = LoginForm()
for item in form:
print(item)
- 列表、字典扩淀、元組
-
裝飾器
裝飾器:
能夠在不修改原函數(shù)代碼的基礎上楔敌,在執(zhí)行前后進行定制操作,閉包函數(shù)的一種應用
場景:
- flask路由系統(tǒng)
- flask before_request
- csrf
- django內(nèi)置認證
- django緩存
# 手寫裝飾器驻谆;
import functools
def wrapper(func):
@functools.wraps(func) #不改變原函數(shù)屬性
def inner(*args, **kwargs):
執(zhí)行函數(shù)前
return func(*args, **kwargs)
執(zhí)行函數(shù)后
return inner
1. 執(zhí)行wapper函數(shù)卵凑,并將被裝飾的函數(shù)當做參數(shù)。 wapper(index)
2. 將第一步的返回值胜臊,重新賦值給 新index = wapper(老index)
@wrapper #index=wrapper(index)
def index(x):
return x+100
調(diào)用裝飾器其實是一個閉包函數(shù)勺卢,為其他函數(shù)添加附加功能,不修改被修改的源代碼和不修改被修飾的方式象对,裝飾器的返回值也是一個函數(shù)對象黑忱。
比如:插入日志、性能測試、事物處理甫煞、緩存菇曲、權限驗證等,有了裝飾器抚吠,就可以抽離出大量與函數(shù)功能本身無關的雷同代碼并繼續(xù)重用常潮。
34、用Python實現(xiàn)一個二分查找的函數(shù)
二分查找算法楷力。簡單的說喊式,就是將一個列表先排序好,比如按照從小到大的順序排列好萧朝,當給定一個數(shù)岔留。
比如3,查找3在列表中的位置時检柬,可以先找到列表中間的數(shù)li[middle]和3進行比較献联,當它比3小時,那么3一定是在列表的右邊厕吉,反之,則3在列表的左邊械念,比如它比3小头朱,則下次就可以只比較[middle+1, end]的數(shù),繼續(xù)使用二分法龄减,將它一分為二项钮,直到找到3這個數(shù)返回或者列表全部遍歷完成(3不在列表中) 。
優(yōu)點是效率高希停,時間復雜度為O(logN)烁巫; 缺點:數(shù)據(jù)要是有序的,順序存儲宠能。
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def search(someone, li):
l = -1
h = len(li)
while l + 1 != h:
m = int((l + h) / 2)
if li[m] < someone:
l = m
else:
h = m
p = h
if p >= len(li) or li[p] != someone:
print("元素不存在")
else:
str = "元素索引為%d" % p
print(str)
search(3, li) # 元素索引為2
35亚隙、談談你對閉包的理解
ef foo():
m=3
n=5
def bar():
a=4
return m+n+a
return bar
>>>bar = foo()
>>>bar()
12
bar在foo函數(shù)的代碼塊中定義。我們稱bar是foo的內(nèi)部函數(shù)违崇。 在bar的局部作用域中可以直接訪問foo局部作用域中定義的m阿弃、n變量。 簡單的說羞延,這種內(nèi)部函數(shù)可以使用外部函數(shù)變量的行為渣淳,就叫閉包。
36伴箩、如何用python刪除一個文件入愧?
import os
file = r'D:\test.txt'
if os.path.exists(file):
os.remove(file)
print('delete success')
else:
print('no such file:%s' % file)
37、談談你對面向?qū)ο蟮睦斫?/h2>
三大特性
面對對象是一種編程思想,以類的眼光來來看待事物的一種方式棺蛛。將有共同的屬性和方法的事物封裝到同一個類下面怔蚌。
繼承:
- 將多個類的共同屬性和方法封裝到一個父類下面,然后在用這些類來繼承這個類的屬性和方法
封裝:
-
將有共同的屬性和方法封裝到同一個類下面
第一層面:創(chuàng)建類和對象會分別創(chuàng)建二者的名稱空間鞠值,我們只能用類名.或者obj.的方式去訪問里面的名字媚创,這本身就是一種封裝。
第二層面:類中把某些屬性和方法隱藏起來(或者說定義成私有的)彤恶,只在類的內(nèi)部使用钞钙、外部無法訪問,或者留下少量接口(函數(shù))供外部訪問声离。
多態(tài):
- Python天生是支持多態(tài)的芒炼。指的是基類的同一個方法在不同的派生類中有著不同的功能。
38术徊、面向?qū)ο笊疃葍?yōu)先和廣度優(yōu)先是什么本刽?
Python的類可以繼承多個類,Python的類如果繼承了多個類赠涮,那么其尋找方法的方式有兩種:
- 當類是經(jīng)典類時子寓,多繼承情況下,會按照深度優(yōu)先方式查找 py3
- 當類是新式類時笋除,多繼承情況下斜友,會按照廣度優(yōu)先方式查找 py2
簡單點說就是:經(jīng)典類是縱向查找,新式類是橫向查找垃它。
經(jīng)典類和新式類的區(qū)別就是鲜屏,在聲明類的時候,新式類需要加上object關鍵字国拇。在python3中默認全是新式類洛史。
39、面向?qū)ο笾衧uper的作用
# 用于子類繼承基類的方法
class FooParent(object):
def __init__(self):
self.parent = 'I\'m the parent.'
print('Parent')
print('1111')
def bar(self, message):
print("%s from Parent" % message)
class FooChild(FooParent):
def __init__(self):
# super(FooChild,self) 首先找到 FooChild 的父類(就是類 FooParent)酱吝,然后把類B的對象 FooChild 轉(zhuǎn)換為類 FooParent 的對象
super(FooChild, self).__init__()
print('Child')
# def bar(self, message):
# # super(FooChild, self).bar(message)
# print('Child bar fuction')
# print(self.parent)
if __name__ == '__main__':
fooChild = FooChild()
fooChild.bar('HelloWorld')
40也殖、functools中的函數(shù)作用是什么?
# 用于修復裝飾器
import functools
def deco(func):
@functools.wraps(func) # 加在最內(nèi)層函數(shù)正上方
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@deco
def index():
'''哈哈哈哈'''
x = 10
print('from index')
print(index.__name__)
print(index.__doc__)
# 加@functools.wraps
# index
# 哈哈哈哈
# 不加@functools.wraps
# wrapper
# None
41务热、如何判斷是函數(shù)還是方法毕源?
看他的調(diào)用者是誰,如果是類陕习,就需要傳入一個參數(shù)self的值霎褐,這時他就是一個函數(shù)。
如果調(diào)用者是對象该镣,就不需要給self傳入?yún)?shù)值冻璃,這時他就是一個方法。
print(isinstance(obj.func, FunctionType)) # False
print(isinstance(obj.func, MethodType)) # True
class Foo(object):
def __init__(self):
self.name = 'lcg'
def func(self):
print(self.name)
obj = Foo()
print(obj.func) # <bound method Foo.func of <__main__.Foo object at 0x000001ABC0F15F98>>
print(Foo.func) # <function Foo.func at 0x000001ABC1F45BF8>
# ------------------------FunctionType, MethodType------------#
from types import FunctionType, MethodType
obj = Foo()
print(isinstance(obj.func, FunctionType)) # False
print(isinstance(obj.func, MethodType)) # True
print(isinstance(Foo.func, FunctionType)) # True
print(isinstance(Foo.func, MethodType)) # False
# ------------------------------------------------------------#
obj = Foo()
Foo.func(obj) # lcg
obj = Foo()
obj.func() # lcg
"""
注意:
方法,無需傳入self參數(shù)
函數(shù)省艳,必須手動傳入self參數(shù)
"""
42娘纷、靜態(tài)方法和類方法區(qū)別
盡管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明顯的區(qū)別跋炕。classmethod 必須有一個指向類對象的引用作為第一個參數(shù)赖晶,而 staticmethod 可以沒有任何參數(shù)。
例如:
class Num:
# 普通方法:能用Num調(diào)用而不能用實例化對象調(diào)用
def one():
print ('1')
# 實例方法:能用實例化對象調(diào)用而不能用Num調(diào)用
def two(self):
print ('2')
# 靜態(tài)方法:能用Num和實例化對象調(diào)用
@staticmethod
def three():
print ('3')
# 類方法:第一個參數(shù)cls長什么樣不重要辐烂,都是指Num類本身遏插,調(diào)用時將Num類作為對象隱式地傳入方法
@classmethod
def go(cls):
cls.three()
Num.one() #1
#Num.two() #TypeError: two() missing 1 required positional argument: 'self'
Num.three() #3
Num.go() #3
i=Num()
#i.one() #TypeError: one() takes 0 positional arguments but 1 was given
i.two() #2
i.three() #3
i.go() #3
43、什么是反射纠修?以及應用場景是什么胳嘲?
反射的核心本質(zhì)就是以字符串的形式去導入個模塊,利用字符串的形式去執(zhí)行函數(shù)扣草。
Django中的 CBV就是基于反射實現(xiàn)的了牛。
44、metaclass作用辰妙?以及應用場景鹰祸?
metaclass用來指定類是由誰創(chuàng)建的。
類的metaclass 默認是type密浑。我們也可以指定類的metaclass值蛙婴。在python3中:
class MyType(type):
def __call__(self, *args, **kwargs):
return 'MyType'
class Foo(object, metaclass=MyType):
def __init__(self):
return 'init'
def __new__(cls, *args, **kwargs):
return cls.__init__(cls)
def __call__(self, *args, **kwargs):
return 'call'
obj = Foo()
print(obj) # MyType
45、實現(xiàn)單例模式的方法
1:使用模塊
Python的模塊就是天然的單例模式肴掷。
因為模塊在第一次導入時敬锐,會生成 .pyc 文件背传,當?shù)诙螌霑r呆瞻,就會直接加載 .pyc 文件,而不會再次執(zhí)行模塊代碼径玖。
因此痴脾,我們只需把相關的函數(shù)和數(shù)據(jù)定義在一個模塊中,就可以獲得一個單例對象了梳星。
例如:
class V1(object):
def foo(self)
pass
V1 = V1()
將上面代碼保存在文件test.py,要使用時赞赖,直接在其他文件中導入此文件中的對象,這個對象既是單例模式的對象
如:from a import V1
2:使用裝飾器
def Singleton(cls):
_instance = {}
def _singleton(*args, **kargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kargs)
return _instance[cls]
return _singleton
@Singleton
class A(object):
a = 1
def __init__(self, x=0):
self.x = x
a1 = A(2)
a2 = A(3)
3:使用類
4:基于__new__方法實現(xiàn)
當我們實例化一個對象時冤灾,是先執(zhí)行了類的__new__方法
當:(我們沒寫時前域,默認調(diào)用object.__new__),實例化對象韵吨;然后再執(zhí)行類的__init__方法匿垄,對這個對象進行初始化,所有我們可以基于這個,實現(xiàn)單例模式
46椿疗、異常處理寫法以及如何主動跑出異常(應用場景)
# 觸發(fā)異常
def temp_convert(var):
try:
return int(var)
except ValueError as Argument:
print ("參數(shù)沒有包含數(shù)字%s"%Argument)
# 調(diào)用函數(shù)
temp_convert("xyz")
# 以10為基數(shù)的int()的無效文字:“xyz”
----------------------------------------------------------------------------
# raise語法
#raise [Exception [, args [, traceback]]]
# 語句中 Exception 是異常的類型漏峰,args 是自已提供的異常參數(shù)。
class Networkerror(RuntimeError):
def __init__(self, arg):
self.args = arg
try:
raise Networkerror("Bad hostname")
except Networkerror as e:
print(e.args)
47届榄、isinstance作用以及應用場景
isinstance(對象浅乔,類) 判斷這個對象是不是這個類或者這個類的子類的實例化
# # 判斷a 屬不屬于A這個類(可以判斷到祖宗類)
class A:
pass
class B(A):
pass
a = A()
b = B()
print(isinstance(b,A)) # ===> True 判斷到祖宗類
# 任何與object都是True,內(nèi)部都繼承object
class A:pass
a = A() # 實例化
print(isinstance(a,object)) # True
應用場景:rest framework 認證的流程
48、 什么是斷言铝条?應用場景是什么靖苇?
assert 是的作用?斷言
條件成立(布爾值為True)則繼續(xù)往下攻晒,否則跑出異常儒拂,一般用于:滿足某個條件之后,才能執(zhí)行指黎,否則應該跑出異常硼端。
寫API的時候,繼承GenericAPIView
class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
# You'll need to either set these attributes,
# or override `get_queryset()`/`get_serializer_class()`.
# If you are overriding a view method, it is important that you call
# `get_queryset()` instead of accessing the `queryset` property directly,
# as `queryset` will get evaluated only once, and those results are cached
# for all subsequent requests.
queryset = None
serializer_class = None
# If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
lookup_url_kwarg = None
# The filter backend classes to use for queryset filtering
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
# The style to use for queryset pagination.
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
def get_queryset(self):
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
queryset = self.queryset
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
return queryset
49给梅、簡述 OSI 七層協(xié)議
物理層:主要是基于電器特性發(fā)送高低電壓(電信號)假丧,高電壓對應數(shù)字1,低電壓對應數(shù)字0动羽。
數(shù)據(jù)鏈路層:定義了電信號的分組方式包帚。
網(wǎng)路層:引入一套新的地址用來區(qū)分不同的廣播域/子網(wǎng),這套地址即網(wǎng)絡地址运吓。
傳輸層:建立端口到端口的通信渴邦。
會話層:建立客戶端與服務端連接。
表示層:對來自應用層的命令和數(shù)據(jù)進行解釋拘哨,按照一定格式傳給會話層谋梭。如編碼、數(shù)據(jù)格式轉(zhuǎn)換倦青、加密解密瓮床、壓縮解壓 應用層:規(guī)定應用程序的數(shù)據(jù)格式。
50产镐、什么是C/S和B/S架構隘庄?
c/s架構,就是client(客戶端)與server(服務端)即:客戶端與服務端的架構癣亚。
b/s架構丑掺,就是brosver(瀏覽器端)與sever(服務端)即:瀏覽器端與服務端架構
優(yōu)點:統(tǒng)一了所有應用程序的入口、方便述雾、輕量級街州。
51蓬豁、簡述 三次握手、四次揮手的流程
三次握手:
-
第一次握手
客戶端先向服務端發(fā)起一次詢問建立連接的請求菇肃,并隨機生成一個值作為標識地粪。第二次握手
服務端向客戶端先回應第一個標識,再重新發(fā)一個確認標識琐谤。第三次握手
客戶端確認標識蟆技,建立連接,開始傳輸數(shù)據(jù)斗忌。
四次揮手:
-
第一次揮手
客戶端向服務端發(fā)起請求斷開連接的請求质礼。第二次揮手
服務端向客戶端確認請求。第三次揮手
服務端向客戶端發(fā)起斷開連接請求织阳。第四次揮手
客戶端向服務端確認斷開請求眶蕉。
52、TCP和UDP的區(qū)別唧躲?
TCP/UDP區(qū)別
- TCP協(xié)議是面向連接造挽,保證高可靠性傳輸層協(xié)議
- UDP:數(shù)據(jù)丟失,無秩序的傳輸層協(xié)議(qq基于udp協(xié)議)
53弄痹、為何基于tcp協(xié)議的通信比基于udp協(xié)議的通信更可靠饭入?
tcp:可靠,因為只要對方回了確認收到信息肛真,才發(fā)下一個谐丢,如果沒收到確認信息就重發(fā)。
UDP:不可靠蚓让,它是一直發(fā)數(shù)據(jù)乾忱,不需要對方回應。
流式協(xié)議: TCP協(xié)議历极,可靠傳輸窄瘟。
數(shù)據(jù)報協(xié)議: UDP協(xié)議,不可傳輸执解。
54寞肖、什么是socket纲酗?簡述基于tcp協(xié)議的套接字通信流程
Socket是應用層與TCP/IP協(xié)議族通信的中間軟件抽象層衰腌,它是一組接口。
在設計模式中觅赊,Socket其實就是一個門面模式右蕊,它把復雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對用戶來說吮螺,一組簡單的接口就是全部饶囚。
服務端:
創(chuàng)建socket對象帕翻,
綁定ip端口bind(),
設置最大鏈接數(shù)listen(),
accept()與客戶端的connect()創(chuàng)建雙向管道,等到聯(lián)接萝风,
send(), recv(), 收發(fā)數(shù)據(jù)
close()
客戶端:
創(chuàng)建socket對象嘀掸,
connect()與服務端accept()創(chuàng)建雙向管道 ,
send(),
recv(),
close()
55、什么是粘包规惰? socket 中造成粘包的原因是什什么睬塌? 哪些情況會發(fā)生粘包現(xiàn)象?
只有TCP有粘包現(xiàn)象歇万,UDP永遠不會粘包揩晴。
粘包:
在獲取數(shù)據(jù)時,出現(xiàn)數(shù)據(jù)的內(nèi)容不是本應該接收的數(shù)據(jù),如:對方第一次發(fā)送hello,第二次發(fā)送world,
我方接收時,應該收兩次,一次是hello,一次是world,但事實上是一次收到helloworld,一次收到空,這種現(xiàn)象叫粘包
原因:
粘包問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節(jié)的數(shù)據(jù)所造成的贪磺。
什么情況會發(fā)生:
發(fā)送端需要等緩沖區(qū)滿才發(fā)送出去硫兰,造成粘包(發(fā)送數(shù)據(jù)時間間隔很短,數(shù)據(jù)了很小寒锚,會合到一起劫映,產(chǎn)生粘包)
接收方不及時接收緩沖區(qū)的包,造成多個包接收(客戶端發(fā)送了一段數(shù)據(jù)刹前,服務端只收了一小部分苏研,服務端下次再收的時候還是從緩沖區(qū)拿上次遺留的數(shù)據(jù),產(chǎn)生粘包)
56腮郊、IO多路復的作用
socketserver摹蘑,多個客戶端連接,單線程下實現(xiàn)并發(fā)效果轧飞,就叫多路復用衅鹿。
與多進程和多線程技術相比,I/O多路復用技術的最大優(yōu)勢是系統(tǒng)開銷小过咬,系統(tǒng)不必創(chuàng)建進程/線程大渤,也不必維護這些進程/線程,從而大大減小了系統(tǒng)的開銷掸绞。
57泵三、什么是防火墻以及作用?
防火墻是一個分離器衔掸、一個限制器烫幕,也是一個分析器,有效地監(jiān)控了內(nèi)部網(wǎng)和Internet之間的任何活動敞映,保證了內(nèi)部網(wǎng)絡的安全较曼。
作用:
- 防火墻是網(wǎng)絡安全的屏障
- 可以強化網(wǎng)絡安全策略
- 對網(wǎng)絡存取和訪問進行監(jiān)控審計
- 防止內(nèi)部信息的外泄
- 除了安全作用,防火墻還支持具有Internet服務特性的企業(yè)內(nèi)部網(wǎng)絡技術體系V**(虛擬專用網(wǎng))
58振愿、簡述 進程捷犹、線程弛饭、協(xié)程的區(qū)別以及應用場景
線程是指進程內(nèi)的一個執(zhí)行單元,
# 進程
進程擁有自己獨立的堆和棧萍歉,既不共享堆侣颂,亦不共享棧,進程由操作系統(tǒng)調(diào)度枪孩。
# 線程
線程擁有自己獨立的棧和共享的堆横蜒,共享堆,不共享棧销凑,線程亦由操作系統(tǒng)調(diào)度
# 協(xié)程和線程
協(xié)程避免了無意義的調(diào)度丛晌,由此可以提高性能;但同時協(xié)程也失去了線程使用多CPU的能力
進程與線程的區(qū)別:
(1)地址空間:線程是進程內(nèi)的一個執(zhí)行單位斗幼,進程內(nèi)至少有一個線程澎蛛,他們共享進程的地址空間,而進程有自己獨立的地址空間
(2)資源擁有:進程是資源分配和擁有的單位蜕窿,同一個進程內(nèi)線程共享進程的資源
(3)線程是處理器調(diào)度的基本單位谋逻,但進程不是
(4)二者均可并發(fā)執(zhí)行
(5)每個獨立的線程有一個程序運行的入口
協(xié)程與線程:
(1)一個線程可以有多個協(xié)程,一個進程也可以單獨擁有多個協(xié)程桐经,這樣Python中則能使用多核CPU
(2)線程進程都是同步機制毁兆,而協(xié)程是異步
(3)協(xié)程能保留上一次調(diào)用時的狀態(tài)
59、GIL鎖是什么阴挣?
GIL本質(zhì)就是一把互斥鎖气堕,既然是互斥鎖,所有互斥鎖的本質(zhì)都一樣畔咧,都是將并發(fā)運行變成串行茎芭,以此來控制同一時間內(nèi)共享數(shù)據(jù)只能被一個任務所修改,進而保證數(shù)據(jù)安全誓沸。
GIL保護的是解釋器級的數(shù)據(jù)梅桩,保護用戶自己的數(shù)據(jù)則需要自己加鎖處理
總結(jié):
多線程用于IO密集型,如socket拜隧,爬蟲宿百,web。
多進程用于計算密集型洪添,如金融分析垦页。
- 每個cpython進程內(nèi)都有一個GIL
- GIL導致同一進程內(nèi)多個進程同一時間只能有一個運行
- 之所以有GIL,是因為Cpython的內(nèi)存管理不是線程安全的
- 對于計算密集型用多進程薇组,多IO密集型用多線程
60外臂、什么是并發(fā)和并行坐儿?
并發(fā):同一時刻只能處理一個任務律胀,但一個時段內(nèi)可以對多個任務進行交替處理(一個處理器同時處理多個任務)宋光。
并行:同一時刻可以處理多個任務(多個處理器或者是多核的處理器同時處理多個不同的任務)。
類比:并發(fā)是一個人同時吃三個饅頭炭菌,而并行是三個人同時吃三個饅頭罪佳。
61、解釋什么是異步非阻塞
非阻塞:不等待黑低。即:遇到IO阻塞不等待(setblooking=False),(可能會報錯->捕捉異常)
- sk=socket.socket()
- sk.setblooking(False)
異步:回調(diào)赘艳,當達到某個指定的狀態(tài)之后,自動調(diào)用特定函數(shù)克握。
異步體現(xiàn)在回調(diào)上蕾管,回調(diào)就是有消息返回時告知一聲兒進程進行處理。非阻塞就是不等待菩暗,不需要進程等待下去掰曾,繼續(xù)執(zhí)行其他操作,不管其他進程的狀態(tài)停团。
62旷坦、路由器和交換機的區(qū)別
1:交換機:是負責內(nèi)網(wǎng)里面的數(shù)據(jù)傳遞(arp協(xié)議)根據(jù)MAC地址尋址。
路由器:在網(wǎng)絡層佑稠,路由器根據(jù)路由表秒梅,尋找該ip的網(wǎng)段。
2:路由器可以處理TCP/IP協(xié)議舌胶。
3:路由器可以把一個IP分配給很多個主機使用捆蜀,這些主機對外只表現(xiàn)出一個IP。 交換機可以把很多主機連起來幔嫂,這些主機對外各有各的IP漱办。
4:交換機是做端口擴展的,也就是讓局域網(wǎng)可以連進來更多的電腦婉烟。路由器是用來做網(wǎng)絡連接娩井,也就是;連接不同的網(wǎng)絡似袁。
63洞辣、生產(chǎn)者消費者模型應用場景及優(yōu)勢
生產(chǎn)者與消費者模式是通過一個容器來解決生產(chǎn)者與消費者的強耦合關系,生產(chǎn)者與消費者之間不直接進行通訊昙衅,而是利用阻塞隊列來進行通訊扬霜,生產(chǎn)者生成數(shù)據(jù)后直接丟給阻塞隊列,消費者需要數(shù)據(jù)則從阻塞隊列獲取而涉。
實際應用中著瓶,生產(chǎn)者與消費者模式則主要解決生產(chǎn)者與消費者生產(chǎn)與消費的速率不一致的問題,達到平衡生產(chǎn)者與消費者的處理能力啼县,而阻塞隊列則相當于緩沖區(qū)材原。
應用場景:用戶提交訂單沸久,訂單進入引擎的阻塞隊列中,由專門的線程從阻塞隊列中獲取數(shù)據(jù)并處理
優(yōu)勢:
1余蟹、解耦
- 假設生產(chǎn)者和消費者分別是兩個類卷胯。如果讓生產(chǎn)者直接調(diào)用消費者的某個方法,那么生產(chǎn)者對于消費者就會產(chǎn)生依賴(也就是耦合)威酒。
將來如果消費者的代碼發(fā)生變化窑睁,可能會影響到生產(chǎn)者。而如果兩者都依賴于某個緩沖區(qū)葵孤,兩者之間不直接依賴担钮,耦合也就相應降低了。
2尤仍、支持并發(fā)
- 生產(chǎn)者直接調(diào)用消費者的某個方法裳朋,還有另一個弊端。由于函數(shù)調(diào)用是同步的(或者叫阻塞的)吓著,在消費者的方法沒有返回之前鲤嫡,生產(chǎn)者只能一直等著
而使用這個模型,生產(chǎn)者把制造出來的數(shù)據(jù)只需要放在緩沖區(qū)即可绑莺,不需要等待消費者來取
3:支持忙閑不均
- 緩沖區(qū)還有另一個好處暖眼。如果制造數(shù)據(jù)的速度時快時慢,緩沖區(qū)的好處就體現(xiàn)出來了纺裁。
當數(shù)據(jù)制造快的時候诫肠,消費者來不及處理,未處理的數(shù)據(jù)可以暫時存在緩沖區(qū)中欺缘。等生產(chǎn)者的制造速度慢下來栋豫,消費者再慢慢處理掉。
.
.
.
好啦谚殊,以上的資料就分享到這里了丧鸯,如果你對更多內(nèi)容、及Python實例練習題嫩絮、面試題丛肢、自動化軟件測試感興趣的話可以加入我們175317069一起學習喔。會有各項學習資源發(fā)放剿干,更有行業(yè)深潛多年的技術人分析講解蜂怎。期待你的加入!
歡迎【評論】置尔、【點贊】杠步、【關注】~
Time will tell.(時間會證明一切)