В первом фрагменте вы заставляете bar.do_something_expensive
обращаться к функциональному объекту, к которому a_package.baz.do_something_expensive
относится в данный момент. Чтобы действительно «обезьянить», вам нужно изменить саму функцию (вы меняете только то, к чему относятся имена); это возможно, но вы на самом деле не хотите этого делать.
Пытаясь изменить поведение a_function
, вы сделали две вещи:
В первой попытке вы делаете do_something_exbly глобальным именем в вашем модуле. Однако вы вызываете a_function
, который не ищет в вашем модуле разрешения имен, поэтому он по-прежнему ссылается на ту же функцию.
Во втором примере вы меняете то, к чему относится a_package.baz.do_something_expensive
, но bar.do_something_expensive
магически не привязано к нему. Это имя по-прежнему относится к объекту функции, который он посмотрел при инициализации.
Самый простой, но далеко не идеальный подход - это изменить bar.py
на
import a_package.baz
def a_function():
print a_package.baz.do_something_expensive()
Правильное решение, вероятно, одно из двух:
- Переопределите
a_function
, чтобы взять функцию в качестве аргумента и вызвать ее, вместо того, чтобы пытаться проникнуть внутрь и изменить функцию, на которую она жестко запрограммирована, или
- Сохранить функцию, которая будет использоваться в экземпляре класса; это то, как мы делаем изменяемое состояние в Python.
Использование глобальных переменных (это то, что означает изменение материала на уровне модулей по сравнению с другими модулями) - это плохая вещь , которая приводит к не поддерживаемому, сбивающему с толку, не тестируемому и не масштабируемому коду, поток которого трудно отследить.