溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解Python猴子補丁

發布時間:2021-11-01 17:10:12 來源:億速云 閱讀:222 作者:iii 欄目:編程語言

這篇文章主要介紹“怎么理解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對象替代被測對象所依賴的對象的模塊。

怎么理解Python猴子補丁

題目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猴子補丁”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女