请看一下缩小后的代码:
from abc import ABC, abstractmethod
class AbstractProduct(ProductFactory, ABC):
@abstractmethod
def some_method(self):
''' Is abstract method '''
class Product1(AbstractProduct):
def some_method(self):
print('I am a Product1!')
class Product2(AbstractProduct):
def some_method(self):
print('I am a Product2!')
class ProductFactory:
knowed_types = {
0: Product1,
1: Product2
}
@classmethod
def create_product(cls, type_id:int):
if type_id in cls.knowed_types:
return cls.knowed_types[type_id]()
该代码不起作用,因为这些类循环相互引用。如何在不破坏当前代码逻辑的情况下打破循环依赖?该片段仅用于演示目的。我不需要专门用这段代码来解决问题。我想知道一般情况下,Python是否有内置的方法来消除这样的循环依赖?例如,在 Django 中,您可以将类名括在引号中以推迟依赖关系解析。在 C++ 中,您可以在文件的开头声明函数签名,然后声明其实现。纯Python中有类似的机制吗?
tl;dr两种主要方式:
在今天的问题中,出于某种原因,作者没有提到他昨天提到的细微差别 - 他希望方法
create_product不仅在类中ProductFactory,而且在类中AbstractProduct(“可用性和代码可维护性之间的权衡”),为此,他尝试进行继承,从而获得了循环依赖。在昨天的(现已删除)问题中,我已经提出通过用类中的简单代理方法替换完全不合逻辑的继承来解决循环依赖
AbstractProduct,但由于某种原因,问题的作者对此并不满意,他断然拒绝解释为什么。ProductFactorycreate_productAbstractProduct对 Python 不太熟悉的人可能会有一个问题:为什么这会起作用,即使在我修改的代码中
ProductFactory它是在类声明之前提到的ProductFactory?事实上,Python(像许多其他脚本语言一样)不会检查函数体中代码的正确性 - 您可以在其中编写任何内容,只要语法正确即可。Python 只会在调用函数时立即开始查找变量ProductFactory- 并且在调用函数时,类ProductFactory已经创建,因此一切正常,并且循环依赖已成功克服。隔离函数和方法内的依赖关系是处理循环依赖关系的一种方法。如果该类
ProductFactory在另一个文件中,那么您import也可以在方法中编写此类;幸运的是,Python 允许您随时随地进行导入 - 类似地,导入只会在调用函数时发生。为了多样化,我还将添加一个“就像在 Django 中一样”的方法 - 使用带有对象名称的字符串而不是这些对象本身。这个想法是不立即使用依赖项,而是稍后使用该行中写入的标识符查找它。在下面的示例中
knowed_types,我对其进行了更改,以便它存储类的名称,并且该方法create_product通过全局变量中的指定名称搜索这些类。根据具体情况,您可以使用字典等代替全局变量(但随后您需要编写填充此类字典的代码 - 在 Django 中,元类会执行此操作)。(如果对象位于不同的文件中,则可以在同一行中写入模块的路径,使用 importlib.import_module 函数导入它,然后使用 提取所需的对象
getattr,但这在下面的示例中没有使用。)请记住,总体投票统计数据并不总是反映答案的质量:投票支持开设俄语 StackOverflow
我通过使用元类解决了这个问题
type