Ошибка исправления Python — monkey, почему?

#python-3.x #metaprogramming #python-import #monkeypatching #python-internals

#python-3.x #метапрограммирование #python-импорт #monkeypatching #python-внутренности

Вопрос:

Я хочу запустить исправление f(*args, **kwargs) из установленного модуля. Я использую идею декоратора в своем собственном коде, но другие методы из установленного модуля не вызывают f корректно.

Вот пример:

 import numpy as np

def log(func):
    def wrapper(*args, **kwargs):
        print('logging')
        return func(*args, **kwargs)
    return wrapper

if __name__ == "__main__":
    a1 = np.asarray([0, 1, 2])
    print(f'a1={a1}')

    a2 = np.array([0, 1, 2])
    print(f'a2={a2}')

    np.array = log(np.array)

    a3 = np.asarray([0, 1, 2])
    print(f'a3={a3}')

    a4 = np.array([0, 1, 2])
    print(f'a4={a4}')
 

Вывод:

 a1=[0 1 2]
a2=[0 1 2]
a3=[0 1 2]
logging
a4=[0 1 2]
 

Я бы хотел, чтобы результат был:

 a1=[0 1 2]
a2=[0 1 2]
logging
a3=[0 1 2]
logging
a4=[0 1 2]
 

поскольку asarray вызовы array в исходном коде.

Мои вопросы: 1. Почему ошибка исправления обезьяны? 2. Как это исправить?

Комментарии:

1. … что вы украшаете своим log декоратором?

2. @hiroprotagonist np.array методы, я думаю, моя терминология неверна.

Ответ №1:

np.array = log(np.array) Вы меняете, к какой функции относится «общедоступное» имя np.array .

Но np.asarray определяется в numpy.core.numeric модуле, который имеет свое собственное «частное» имя для ссылки на эту функцию. На это не влияет исправление общедоступного имени.

Вам нужно будет исправить личное имя:

 np.core.numeric.array = log(np.array)
 

Комментарии:

1. Таким образом, я должен исправить как общедоступное имя ( np.array = log(np.array) ), так и личное имя ( np.core.numeric.array = log(np.array) ), а также любое другое личное имя, которое вызывает np.arrray . Возможно ли, чтобы я исправил только один раз?

2. Я не думаю, что это возможно. Однако, исправляя np.core.numeric.array , вы уже покрываете множество функций.