這篇文章主要介紹“怎么理解Python猴子補丁”,在日常操作中,相信很多人在怎么理解Python猴子補丁問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解Python猴子補丁”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
題目:談談你對“猴子補丁”(monkey patching)的理解。
“猴子補丁”是動態類型語言的一個特性,代碼運行時在不修改源代碼的前提下改變代碼中的方法、屬性、函數等以達到熱補?。╤ot patch)的效果。很多系統的安全補丁也是通過猴子補丁的方式來實現的,但實際開發中應該避免對猴子補丁的使用,以免造成代碼行為不一致的問題。
在使用gevent庫的時候,我們會在代碼開頭的地方執行gevent.monkey.patch_all(),這行代碼的作用是把標準庫中的socket模塊給替換掉,這樣我們在使用socket的時候,不用修改任何代碼就可以實現對代碼的協程化,達到提升性能的目的,這就是對猴子補丁的應用。
另外,如果希望用ujson三方庫替換掉標準庫中的json,也可以使用猴子補丁的方式,代碼如下所示。
import json, ujson
json.__name__ =
'ujson'
json.dumps = ujson.dumps
json.loads = ujson.loads
單元測試中的Mock技術也是對猴子補丁的應用,Python中的unittest.mock模塊就是解決單元測試中用Mock對象替代被測對象所依賴的對象的模塊。
題目32:閱讀下面的代碼說出運行結果。
class A:
def who(self):
print('A', end='')
class B(A):
def who(self):
super(B, self).who()
print('B', end='')
class C(A):
def who(self):
super(C, self).who()
print('C', end='')
class D(B, C):
def who(self):
super(D, self).who()
print('D', end='')
item = D()
item.who()
點評:這道題考查到了兩個知識點。知識點一:Python中的MRO(方法解析順序)。在沒有多重繼承的情況下,向對象發出一個消息,如果對象沒有對應的方法,那么向上(父類)搜索的順序是非常清晰的。如果向上追溯到object類(所有類的父類)都沒有找到對應的方法,那么將會引發AttributeError異常。但是有多重繼承尤其是出現菱形繼承(鉆石繼承)的時候,向上追溯到底應該找到那個方法就得確定MRO。Python 3中的類以及Python 2中的新式類使用C3算法來確定MRO,它是一種類似于廣度優先搜索的方法;Python 2中的舊式類(經典類)使用深度優先搜索來確定MRO。在搞不清楚MRO的情況下,可以使用類的mro方法或__mro__屬性來獲得類的MRO列表。知識點二:super()函數的使用。在使用super函數時,可以通過super(類型, 對象)來指定對哪個對象以哪個類為起點向上搜索父類方法。所以上面B類代碼中的super(B, self).who()表示以B類為起點,向上搜索self(D類對象)的who方法,所以會找到C類中的who方法,因為D類對象的MRO列表是D --> B --> C --> A --> object。
ACBD
題目33:編寫一個函數實現對逆波蘭表達式求值,不能使用Python的內置函數。
點評:逆波蘭表達式也稱為“后綴表達式”,相較于平常我們使用的“中綴表達式”,逆波蘭表達式不需要括號來確定運算的優先級,例如5 * (2 + 3)對應的逆波蘭表達式是5 2 3 + *。逆波蘭表達式求值需要借助棧結構,掃描表達式遇到運算數就入棧,遇到運算符就出棧兩個元素做運算,將運算結果入棧。表達式掃描結束后,棧中只有一個數,這個數就是最終的運算結果,直接出棧即可。
import operator
class Stack:
"""棧(FILO)"""
def __init__(self):
self.elems = []
def push(self, elem):
"""入棧"""
self.elems.append(elem)
def pop(self):
"""出棧"""
return self.elems.pop()
@property
def is_empty(self):
"""檢查棧是否為空"""
return len(self.elems) ==
0def eval_suffix(expr):
"""逆波蘭表達式求值"""
operators = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv
}
stack = Stack()
for item
in expr.split():
if item.isdigit():
stack.push(float(item))
else:
num2 = stack.pop()
num1 = stack.pop()
stack.push(operators[item](num1, num2))
return stack.pop()
題目34:Python中如何實現字符串替換操作?
Python中實現字符串替換大致有兩類方法:字符串的replace方法和正則表達式的sub方法。
方法一:使用字符串的replace方法。
message =
'hello, world!'
print(message.replace('o',
'O').replace('l',
'L').replace('he',
'HE'))
方法二:使用正則表達式的sub方法。
import re
message =
'hello, world!'
pattern = re.compile('[aeiou]')
print(pattern.sub('#', message))
擴展:還有一個面試題,列表中保存了一系列的文件名,如filenames = ['a9.txt', 'a12.txt', 'a8.txt', 'b2.txt', 'b19.txt','a3.txt'],對這些文件名進行排序,要求按照字面表和數字大小進行排序,簡單的說就是a9.txt會排在a12.txt的前面,b2.txt會排在b19.txt的前面。大家可以思考下這個問題如何解決。
題目35:如何剖析Python代碼的執行性能?
剖析代碼性能可以使用Python標準庫中的cProfile和pstats模塊,cProfile的run函數可以執行代碼并收集統計信息,創建出Stats對象并打印簡單的剖析報告。Stats是pstats模塊中的類,它是一個統計對象。當然,也可以使用三方工具line_profiler和memory_profiler來剖析每一行代碼耗費的時間和內存,這兩個三方工具都會用非常友好的方式輸出剖析結構。如果使用PyCharm,可以利用“Run”菜單的“Profile”菜單項對代碼進行性能分析,PyCharm中可以用統計表格(Statistics)或者調用圖(Call Graph)的方式來顯示性能剖析的結果。
下面是使用cProfile剖析代碼性能的例子。
example.py
import cProfile
def is_prime(num):
for factor
in range(2, int(num **
0.5) +
1):
if num % factor ==
0:
return False
return True
class
PrimeIter:
def __init__(self, total):
self.counter =
0
self.current =
1
self.total = total
def __iter__(self):
return self
def __next__(self):
if self.counter <
self.total:
self.current +=
1
while not is_prime(self.current):
self.current +=
1
self.counter +=
1
return self.current
raise StopIteration()
cProfile.run('list(PrimeIter(10000))')
如果使用line_profiler三方工具,可以直接剖析is_prime函數每行代碼的性能,需要給is_prime函數添加一個profiler裝飾器,代碼如下所示。
@profiler
def is_prime(num):
for factor in range(2, int(num ** 0.5) + 1):
if num % factor == 0:
return False
return True
安裝line_profiler。
pip install line_profiler
使用line_profiler。
kernprof -lv example.py
運行結果如下所示。
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1
@profile
2 def is_prime(num):
3 86624
48420.0
0.6 50.5 for factor
in range(2, int(num **
0.5) +
1):
4 85624
44000.0
0.5 45.9 if num % factor ==
0:
5 6918
3080.0
0.4
3.2 return False
6 1000 430.0
0.4
0.4 return True
到此,關于“怎么理解Python猴子補丁”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。