当我尝试将现有函数作为成员函数合并到类中时,就会出现此问题。我有类似的设置:
课程:
base(object)
primitive(base)
square(primitive)
union(primitive)
我有一个名为union
的函数,用户可以调用该函数返回一个union
基本对象。
obj1 = square()
obj2 = square()
obj3 = union(obj1, obj2) #this is the union function which returns a union primitive
我希望用户也能够做到这一点
obj3 = obj1.union(obj2)
这就是问题所在。 primitive
类需要导入union
函数,后者又导入union
类,后者又导入primitive
类,并且遇到循环依赖项错误。是否有一种聪明的方法来重构代码或更改导入语句以使其工作?
编辑:
为清楚起见,这是代码的结构方式:
operations / union.py (功能)
from objects import union as _union #the union class
def union(obj1, obj2): #the union function
#CODE
return _union(args)
objects / union.py (该类)
from objects import primitive
class union(primitive):
#CODE
objects / primitive.py
from operations import union #the function
class primitive(base):
#CODE
def union(self, obj2):
return union(self, obj2)
有一个名为union
的类,该类包含有关联合输入对象的信息。用户不会与此交互。然后是用户可以调用的union
函数,该函数返回一个union
对象。我希望primitive
类包含一个名为union
的成员函数,该成员函数使用我已经编写的union
函数。问题是union
函数返回一个union
类的primitive
对象。这会导致循环依赖性问题。我可以删除union
成员函数,但用户不能这样做
obj3 = obj1.union(obj2)
答案 0 :(得分:1)
听起来好像您通过在单独的模块/文件中定义primitive
和square
给自己造成了很多麻烦。如果您在同一模块中定义它们,我怀疑您会遇到麻烦。例如,以下可以正常工作:
class Primitive:
pass
class Square(Primitive):
def union(self, other):
return Union(self, other)
class Union(Primitive):
def __init__(self, *members):
self.members = members
obj1 = Square()
obj2 = Square()
obj3 = obj1.union(obj2)
print(type(obj3))
print(obj3.members)
但是,如果您坚持将类放在不同的文件中,则可以执行以下操作:
primitive.py:
class Primitive:
pass
square.py:
from .primitive import Primitive
class Square(Primitive):
def union(self, other):
from .union import Union
return Union(self, other)
union.py:
from .primitive import Primitive
class Union(Primitive):
def __init__(self, *members):
self.members = members
test.py:
from .square import Square
obj1 = Square()
obj2 = Square()
obj3 = obj1.union(obj2)
print(type(obj3))
print(obj3.members)
关键是要在from .union import Union
方法内移动union()
语句,直到需要时才调用它。
这是关于Python循环导入的good resource。
答案 1 :(得分:1)
如果您在模块级别不依赖任何导入,则可以将导入放置在文件的末尾。对于union
,需要Primitive
在模块范围内定义一个类,因此请按原样保留union.py
:
from objects.primitive import Primitive
class Union(Primitive):
@classmethod
def union(cls, a, b):
return Union(a, b)
但是primitive
仅需要一种方法中的Union
,而无需在模块范围内创建任何内容,因此,您所需要的只是使导入的模块在调用该方法时就已经存在。这意味着您可以执行以下操作:
class Primitive(Base):
#CODE
def union(self, obj2):
return union.Union.union(self, obj2)
from objects import union
您需要将导入放在末尾的原因是为了确保无论哪个模块首先导入,该导入都能正常工作。如果导入objects.union
,它将正确导入objects.primitive
,然后再到达模块主体。如果首先导入objects.primitive
,它将尝试导入objects.union
,这需要Primitive
类已经存在。因此,导入到类主体之后。
我建议将union
中的@classmethod
设为Union
的{{1}},以便您可以正确地将其用作备用构造函数。另外,使用CamelCase中编写类名的Python约定可以使命名更容易混淆。