Вы можете обезьяна пропатчить библиотеку .
# a.py
import d
class A():
my_d = d.D()
# script.py
A.d.D = D_prime
def foo():
a_cls = a.A() # uses A.d.D is D'
Способ, которым a.py импортирует D, имеет значение
# a.py
from d import D
class A():
my_d = D()
# script.py
A.D = D_prime
def foo():
a_cls = a.A() # uses A.D is D'
Другие схемы импорта могут включать похожие шаблоны,Нечто подобное может быть очень трудно исправить.
def builder():
from d import D
return D()
Также может быть полезно посмотреть, как библиотека mock
делает это.Если это игрушка, вы могли бы использовать это напрямую.patch
в частности это интересно .
@patch('A.d.D', new=D_prime)
def my_func(...):
a = A() # a.d.D is D_prime
Исправление обезьян - это запах кода, в зависимости от юнит-теста в коде приложения это запах.Ничто из этого не является "изящным".Если вы являетесь автором библиотеки, пожалуйста, поддержите внедрение зависимостей.
Если вы храбры, вы можете вытащить некоторые из патч-декораторов во что-то, что не сфокусировано на мошенничестве.Поскольку этот шаблон существует в библиотеке unittest, его можно считать питоническим и «элегантным» с оговоркой выше.
Если вас интересует как это работает , вы модифицируететаблица символов для модуля a
.Подробнее см. глобальные и местные .