Fir*_*cer 17 python module circular-dependency
好的我有两个模块,每个模块都包含一个类,问题是它们的类互相引用.
让我们说例如我有一个房间模块和一个包含CRoom和CPerson的人员模块.
CRoom类包含有关房间的信息,以及房间中每个人的CPerson列表.
然而,CPerson类有时需要将CRoom类用于它的房间,例如找到门,或者看看房间里还有谁.
问题是两个模块互相导入我只是得到一个导入错误,其中第二次导入:(
在c ++中,我可以通过仅包含头来解决这个问题,因为在这两种情况下类都只有指向另一个类的指针,前向声明就足以满足标题,例如:
class CPerson;//forward declare
class CRoom
{
std::set<CPerson*> People;
...
Run Code Online (Sandbox Code Playgroud)
反正有没有在python中执行此操作,除了将两个类放在同一个模块或类似的东西?
编辑:添加了使用上面的类显示问题的python示例
错误:
回溯(最近一次调用最后一次):
文件"C:\ Projects\python\test\main.py",第1行,
从房间导入CRoom
文件"C:\ Projects\python\test\room.py",第1行,
来自人员导入CPerson
文件"C:\ Projects\python\test\person.py",第1行,
从房间导入 CRoom
ImportError:无法导入名称
CRoom room.py
from person import CPerson
class CRoom:
def __init__(Self):
Self.People = {}
Self.NextId = 0
def AddPerson(Self, FirstName, SecondName, Gender):
Id = Self.NextId
Self.NextId += 1#
Person = CPerson(FirstName,SecondName,Gender,Id)
Self.People[Id] = Person
return Person
def FindDoorAndLeave(Self, PersonId):
del Self.People[PeopleId]
Run Code Online (Sandbox Code Playgroud)
person.py
from room import CRoom
class CPerson:
def __init__(Self, Room, FirstName, SecondName, Gender, Id):
Self.Room = Room
Self.FirstName = FirstName
Self.SecondName = SecondName
Self.Gender = Gender
Self.Id = Id
def Leave(Self):
Self.Room.FindDoorAndLeave(Self.Id)
Run Code Online (Sandbox Code Playgroud)
Con*_*tin 20
无需导入CRoom
你不使用CRoomin person.py,所以不要导入它.由于动态绑定,Python不需要"在编译时查看所有类定义".
如果你确实不使用CRoom的person.py,然后换from room import CRoom到import room和使用模块合格形式room.CRoom.有关详细信息,请参阅Effbot的循环导入.
旁注:你可能有一个错误Self.NextId += 1.它增加NextId了实例,而不是NextId类.增加班级的反击使用CRoom.NextId += 1或Self.__class__.NextId += 1.
你真的需要在类定义时引用类吗?即.
class CRoom(object):
person = CPerson("a person")
Run Code Online (Sandbox Code Playgroud)
或者(更有可能),你是否只需要在你的类的方法中使用CPerson(反之亦然).例如:
class CRoom(object):
def getPerson(self): return CPerson("someone")
Run Code Online (Sandbox Code Playgroud)
如果是第二个,则没有问题 - 因为在调用方法而不是定义方法时,将导入模块.你唯一的问题是如何引用它.可能你正在做的事情如下:
from CRoom import CPerson # or even import *
Run Code Online (Sandbox Code Playgroud)
使用循环引用模块,您无法执行此操作,因为在一个模块导入另一个模块时,原始模块主体将不会执行完毕,因此命名空间将不完整.相反,使用合格的引用.即:
#croom.py
import cperson
class CRoom(object):
def getPerson(self): return cperson.CPerson("someone")
Run Code Online (Sandbox Code Playgroud)
在这里,python不需要在命名空间中查找属性,直到方法实际被调用,这时两个模块都应该完成初始化.