Я намагаюся зрозуміти, що таке патч мавп чи патч мавпи?
Це щось на зразок методів / операторів, які перевантажують чи делегують?
Чи має щось спільне з цими речами?
Я намагаюся зрозуміти, що таке патч мавп чи патч мавпи?
Це щось на зразок методів / операторів, які перевантажують чи делегують?
Чи має щось спільне з цими речами?
Відповіді:
Ні, це не так, як жодна з цих речей. Це просто динамічна заміна атрибутів під час виконання.
Наприклад, розглянемо клас, який має метод get_data
. Цей метод здійснює зовнішній пошук (наприклад, у базі даних або веб-API), а також інші методи у класі називають його. Однак при тесті на одиницю ви не хочете залежати від зовнішнього джерела даних - тому ви динамічно замінюєте get_data
метод заглушкою, яка повертає деякі фіксовані дані.
Оскільки класи Python є змінними, а методи - це лише атрибути класу, ви можете робити це скільки завгодно - і, фактично, ви можете навіть замінити класи та функції в модулі точно так само.
Але, як зазначив коментатор , будьте обережні під час маніпулювання мавпами:
Якщо нічого іншого, крім вашої логіки тестової логіки get_data
, також дзвінки замінять замість оригіналу, замість оригіналу - що може бути добре чи погано. Тільки остерігайся.
Якщо існує якась змінна або атрибут, яка також вказує на get_data
функцію до моменту її заміни, цей псевдонім не змінить свого значення і продовжить вказувати на оригінал get_data
. (Чому? Python просто перев'язує ім'я get_data
у вашому класі на якийсь інший функціональний об'єкт; інші прив’язки до імен взагалі не впливають.)
pointing to the original get_data function
? Ви маєте на увазі, коли ви зберігаєте функцію всередині змінної, якщо хтось змінить цю функцію, змінна продовжить вказувати на стару?
get_data
ви прив'язуєте ім'я get_data
до функції макету. Якщо якесь інше ім’я деінде в програмі пов'язане з функцією, яка раніше була відома як - get_data
, для цього іншого імені нічого не зміниться.
MonkeyPatch - це фрагмент коду Python, який розширює або змінює інший код під час виконання (як правило, при запуску).
Простий приклад виглядає так:
from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
return "ook ook eee eee eee!"
SomeClass.speak = speak
Джерело: Сторінка MonkeyPatch на вікі Zope.
Що таке патч мавп?
Простіше кажучи, виправлення мавп вносить зміни в модуль або клас під час роботи програми.
У документації на Pandas є приклад виправлення мавп:
import pandas as pd
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
Щоб розбити це, спочатку імпортуємо наш модуль:
import pandas as pd
Далі ми створюємо визначення методу, яке існує незв'язане та вільне поза межами будь-яких визначень класу (оскільки розмежування є досить безглуздим між функцією та беззв'язаним методом, Python 3 відміняє метод незв'язаного):
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
Далі ми просто приєднуємо цей метод до класу, на якому ми хочемо ним скористатися:
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
Тоді ми можемо використовувати метод на екземплярі класу та видалити метод, коли ми закінчимо:
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
Якщо ви використовуєте керування іменами (атрибути з префіксацією з подвійним підкресленням, яке змінює ім'я, і яке я не рекомендую), вам доведеться виконувати ім'я вручну, якщо ви це зробите. Оскільки я не рекомендую керувати іменами, я не демонструю це тут.
Як ми можемо використовувати ці знання, наприклад, при тестуванні?
Скажімо, нам потрібно моделювати виклик пошуку даних до зовнішнього джерела даних, що призводить до помилки, оскільки ми хочемо забезпечити правильну поведінку в такому випадку. Ми можемо мавпами виправити структуру даних, щоб забезпечити таку поведінку. (Отже, використовуючи аналогічну назву методу, яку запропонував Даніель Роузмен :)
import datasource
def get_data(self):
'''monkey patch datasource.Structure with this to simulate error'''
raise datasource.DataRetrievalError
datasource.Structure.get_data = get_data
І коли ми перевіримо його на поведінку, яка спирається на цей метод, викликаючи помилку, якщо правильно виконано, ми отримаємо цю поведінку в результатах тесту.
Виконання вищесказаного змінить Structure
об'єкт протягом життя процесу, тому ви хочете використовувати установки та терени у своїх тестах, щоб уникнути цього, наприклад:
def setUp(self):
# retain a pointer to the actual real method:
self.real_get_data = datasource.Structure.get_data
# monkey patch it:
datasource.Structure.get_data = get_data
def tearDown(self):
# give the real method back to the Structure object:
datasource.Structure.get_data = self.real_get_data
(Хоча в наведеному вище порядку, ймовірно , було б краще ідеї використовувати mock
бібліотеку для виправлення коду. mock
«S patch
декоратора буде менше помилок , ніж робити вище, що потребують більше рядків коди і , отже , більше можливостей для впровадження помилок . Я ще не переглянув код, mock
але, думаю, він використовує аналогічний спосіб виправлення мавп.)
За даними Вікіпедії :
У Python термін мавповий патч стосується лише динамічних модифікацій класу чи модуля під час виконання, мотивованих наміром виправити наявний сторонній код як вирішення помилки чи функції, яка не відповідає вашим бажанням.
По-перше: виправлення мавп - це зла злом (на мою думку).
Він часто використовується для заміни методу на рівні модуля або класу на власну реалізацію.
Найпоширенішою справою є додавання вирішення помилки в модулі або класі, коли ви не можете замінити вихідний код. У цьому випадку ви замінюєте "неправильний" код за допомогою патчу мавпи на реалізацію всередині власного модуля / пакета.
Виправлення мавп можна робити лише в динамічних мовах, з яких пітон є хорошим прикладом. Зміна методу під час виконання замість оновлення визначення об'єкта є одним із прикладів; аналогічно, додавання атрибутів (будь то методи чи змінні) під час виконання вважається виправленням мавпи. Це часто робиться під час роботи з модулями, для яких у вас немає джерела, так що визначення об'єктів неможливо легко змінити.
Це вважається поганим, оскільки означає, що визначення об'єкта не повністю або точно описує, як він насправді веде себе.
Патч мавп - це повторне відкриття існуючих класів або методів у класі під час виконання та зміна поведінки, яку слід використовувати обережно, або використовувати її потрібно лише тоді, коли вам це справді потрібно.
Оскільки Python - це динамічна мова програмування, класи є змінними, тому ви можете їх знову відкрити, змінити або навіть замінити.
Що таке лачання мавп? Виправлення мавп - це техніка, яка використовується для динамічного оновлення поведінки фрагмента коду під час виконання.
Навіщо використовувати виправлення мавп? Це дозволяє нам змінювати або розширювати поведінку бібліотек, модулів, класів або методів під час виконання без фактичної зміни вихідного коду
Висновок Виправлення мавп - це класна техніка, і тепер ми навчилися робити це в Python. Однак, як ми обговорювали, у нього є свої недоліки, і їх слід обережно використовувати.
Для отримання додаткової інформації зверніться до [1]: https://medium.com/@nagillavenkatesh1234/monkey-patching-in-python-explained-with-examples-25eed0aea505
Monkey patching is a technique to add, modify, or suppress the default behavior of a piece of code at runtime without changing its original source code.