Глобалы плохие именно по этой причине, как я уверен, вы знаете достаточно хорошо.
Я бы попытался переопределить A и B (возможно, путем их подкласса) в моем собственном модуле и со всеми ссылками на
my_global заменен введенной зависимостью от A и B, которую я здесь назову реестром.
class A(orig.A):
def __init__(self, registry):
self.registry = registry
self.registry.append(self)
# more updated methods
Если вы создаете все экземпляры A самостоятельно, вы в значительной степени готовы. Возможно, вы захотите создать фабрику, которая скрывает новый параметр init.
my_registry = []
def A_in_my_registry():
return A(my_registry)
Если внешний код создает для вас экземпляры orig.A, и вы предпочитаете иметь новые экземпляры A, вы должны надеяться, что внешний код можно настроить
с заводами. Если нет, производные от внешних классов и обновите их, чтобы вместо них использовать (недавно введенные) фабрики. .... И промыть повторить для создания этих обновленных классов. Я понимаю, что это может быть утомительно или почти невозможно в зависимости от сложности внешнего кода, но большинство стандартных библиотек довольно плоские.
-
Редактировать: Monkey patch std lib code.
Если вы не против того, чтобы обезьяны исправляли стандартные библиотеки, вы также можете попытаться изменить оригинальные классы, чтобы они работали
с уровнем перенаправления, который по умолчанию равен исходным глобальным переменным, но настраивается для каждого экземпляра:
import orig
class A(orig.A):
def __init__(self, registry=orig.my_globals):
self.registry = registry
self.registry.append(self)
# more updated methods
orig.A = A
Как и прежде, вам нужно будет контролировать создания A, которые должны использовать нестандартные глобалы,
но у вас не будет разных классов А, если вы достаточно рано исправите обезьяну.