关于 python 使用类型注释时 python3 中的递归导入
about python recursive import in python3 when using type annotation
又花了三个小时,我想我可能找到答案了。forward-references
如果没有更好的方法,我稍后会关闭这个问题,post那个解决方案
我正在对一个程序进行逆向工程(并尝试使用 Python 实现它)。
我遇到了这个问题
例如
我在ComponentOfCar.py中有一个class,代码如下
__all__ = ("ComponentOfCar");
import Car;
#...#imports other needed packages
class ComponentOfCar(object):
def __init__(self, owner:Car.Car):
self.owner = owner;
self.type = "Default";
#....#create other attribute
另一个class像这样(Car.py):
__all__ = ("Car");
import ComponentOfCar;
#...#imports other needed packages
class Car(object):
__slots__ = ("m_lstComponents",....);
def __init__(self, data:FlatBuffersBinaryData):
self.m_lstComponents = list();
self.LoadFromData(data);
#....#create other attribute
def InstallComponen(self, component:ComponentOfCar.ComponentOfCar)->bool:
self.m_lstComponents.append(component);
return True;
但是这样做之后我遇到了这个问题:
Traceback (most recent call last):
File "Y:\Car.py", line 2, in <module>
import ComponentOfCar;
File "Y:\ComponentOfCar.py", line 2, in <module>
import Car;
File "Y:\Car.py", line 4, in <module>
class Car(object):
File "Y:\Car.py", line 10, in Car
def InstallComponen(self, component:ComponentOfCar.ComponentOfCar)->bool:
AttributeError: module 'ComponentOfCar' has no attribute 'ComponentOfCar'
原程序是用编译语言编写的。里面的class继承很复杂,有几百个class,让我很头疼。
我想通过使用类型注释并将每个 class 分成单独的文件来使这个过程更清晰一些。但这将不得不使用递归导入。
google了半天没找到解决办法,特来这里求助。是 Python 不能像编译语言那样做,还是我犯了一些错误?我很困惑。我该如何解决它。
抱歉我的英语不好。感谢您的宝贵时间。 :)
待详细
下面是反编译后的class声明的结构(是c#,整个文件大概有十万行):
// Namespace: GameNamespace
public class Car
{
// Fields
protected List`1<ComponentOfCar> m_lstComponents;
public int ObjectID;
// Methods
public void .ctor(Data data);
public void AddComponent(ComponentOfCar c);
}
// Namespace: GameNamespace
public abstract class ComponentOfCar
{
// Fields
protected Car m_owner;
// Properties
public Car Owner { get; }
// Methods
public Car get_Owner();
public void .ctor(Car owner);
}
或者我的问题是如何使用python来清楚地实现这一点。
是的,我的想法是上面显示的方法,我知道这是错误的,但我不知道如何改正。
我不应该把他们分开?或者我可以用另一种方式编写它们(以避免递归导入和)来做与 c# 中相同的事情?
请告诉我解决这个问题的方法,非常感谢。
又花了三个小时,我想我可能找到答案了
forward-references ,我正在检查这个。如果没有更好的方法来做到这一点,我稍后会关闭这个问题和 post 那个解决方案,它可能会修复我的代码。
希望这会有所帮助,
component.py
class Component:
def __init__(self, owner, data):
self.owner = owner
self.name = data['name']
car.py
from component import Component
class Car:
def __init__(self, data):
self.components = []
self.type = data['type']
self.color = data['color']
def add_car_components(self, data):
self.components.append(Component(self, data));
c = Car({'type': 'bus', 'color': 'red'})
c.add_car_components({'name': 'frontdoor'})
c.add_car_components({'name': 'reardoor'})
for component in c.components:
print(component.owner.type, component.owner.color, component.name)
结果:
->python car.py
bus red frontdoor
bus red reardoor
经过一番测试,我终于找到了解决方案。也许这不是最好的方法(修复递归导入),但它符合我最初的想法。
在这个 link.
中说
经过一番思考,我认为这可能被称为 forward-references,根据该文档 link 的广告。我将这两个 class 改写如下:
ComponentOfCar.py:
__all__ = ("ComponentOfCar");
import Car;
class ComponentOfCar(object):
__slots__=("owner","name");
def __init__(self, owner:'Car.Car',prop:dict={"name":"NoName"}):
self.owner = owner;
self.name = prop["name"];
if __name__=="__main__":
c=Car.Car({"type":"bus","color":"red"});
door1=ComponentOfCar(c,{"name":"frontdoor"});
door2=ComponentOfCar(c,{"name":"reardoor"});
c.InstallComponent(door1);
c.InstallComponent(door2);
print("We got the car",c);
for component in c.m_lstComponents:
print(component.name,component.owner);
comp1=c.m_lstComponents[0];#now we look at the first component
print("the component %s was installed on a %s %s"%(str(comp1),
comp1.owner.color,comp1.owner.type));
Car.py:
__all__ = ("Car");
import ComponentOfCar;
class Car(object):
__slots__ = ("m_lstComponents","type","color");
def __init__(self, data:dict):
self.m_lstComponents = list();
self.type=data["type"];
self.color=data["color"];
def InstallComponent(self, component:'ComponentOfCar.ComponentOfCar')->bool:
self.m_lstComponents.append(component);
return True;
if __name__=="__main__":
c=Car({"type":"bus","color":"red"});
door1=ComponentOfCar.ComponentOfCar(c,{"name":"frontdoor"});
door2=ComponentOfCar.ComponentOfCar(c,{"name":"reardoor"});
c.InstallComponent(door1);
c.InstallComponent(door2);
print("We got the car",c);
for component in c.m_lstComponents:
print(component.name,component.owner);
comp1=c.m_lstComponents[0];#now we look at the first component
print("the component %s was installed on a %s %s"%(str(comp1),comp1.owner.color,comp1.owner.type));
现在,我可以正确 运行 这段代码,并且得到如下输出:
We got the car <__main__.Car object at 0x0000015904C6AAC8>
frontdoor <__main__.Car object at 0x0000015904C6AAC8>
reardoor <__main__.Car object at 0x0000015904C6AAC8>
the component <ComponentOfCar.ComponentOfCar object at 0x0000015904C647F0> was installed on a red bus
现在我可以严格按照assemble代码写python代码了。我可以继续工作了。
如果有更好的方法满足我的需要,请指正。
谢谢大家。 :)
又花了三个小时,我想我可能找到答案了。forward-references
如果没有更好的方法,我稍后会关闭这个问题,post那个解决方案
我正在对一个程序进行逆向工程(并尝试使用 Python 实现它)。
我遇到了这个问题
例如 我在ComponentOfCar.py中有一个class,代码如下
__all__ = ("ComponentOfCar");
import Car;
#...#imports other needed packages
class ComponentOfCar(object):
def __init__(self, owner:Car.Car):
self.owner = owner;
self.type = "Default";
#....#create other attribute
另一个class像这样(Car.py):
__all__ = ("Car");
import ComponentOfCar;
#...#imports other needed packages
class Car(object):
__slots__ = ("m_lstComponents",....);
def __init__(self, data:FlatBuffersBinaryData):
self.m_lstComponents = list();
self.LoadFromData(data);
#....#create other attribute
def InstallComponen(self, component:ComponentOfCar.ComponentOfCar)->bool:
self.m_lstComponents.append(component);
return True;
但是这样做之后我遇到了这个问题:
Traceback (most recent call last):
File "Y:\Car.py", line 2, in <module>
import ComponentOfCar;
File "Y:\ComponentOfCar.py", line 2, in <module>
import Car;
File "Y:\Car.py", line 4, in <module>
class Car(object):
File "Y:\Car.py", line 10, in Car
def InstallComponen(self, component:ComponentOfCar.ComponentOfCar)->bool:
AttributeError: module 'ComponentOfCar' has no attribute 'ComponentOfCar'
原程序是用编译语言编写的。里面的class继承很复杂,有几百个class,让我很头疼。
我想通过使用类型注释并将每个 class 分成单独的文件来使这个过程更清晰一些。但这将不得不使用递归导入。
google了半天没找到解决办法,特来这里求助。是 Python 不能像编译语言那样做,还是我犯了一些错误?我很困惑。我该如何解决它。
抱歉我的英语不好。感谢您的宝贵时间。 :)
待详细
下面是反编译后的class声明的结构(是c#,整个文件大概有十万行):
// Namespace: GameNamespace
public class Car
{
// Fields
protected List`1<ComponentOfCar> m_lstComponents;
public int ObjectID;
// Methods
public void .ctor(Data data);
public void AddComponent(ComponentOfCar c);
}
// Namespace: GameNamespace
public abstract class ComponentOfCar
{
// Fields
protected Car m_owner;
// Properties
public Car Owner { get; }
// Methods
public Car get_Owner();
public void .ctor(Car owner);
}
或者我的问题是如何使用python来清楚地实现这一点。
是的,我的想法是上面显示的方法,我知道这是错误的,但我不知道如何改正。 我不应该把他们分开?或者我可以用另一种方式编写它们(以避免递归导入和)来做与 c# 中相同的事情?
请告诉我解决这个问题的方法,非常感谢。
又花了三个小时,我想我可能找到答案了
forward-references ,我正在检查这个。如果没有更好的方法来做到这一点,我稍后会关闭这个问题和 post 那个解决方案,它可能会修复我的代码。
希望这会有所帮助,
component.py
class Component:
def __init__(self, owner, data):
self.owner = owner
self.name = data['name']
car.py
from component import Component
class Car:
def __init__(self, data):
self.components = []
self.type = data['type']
self.color = data['color']
def add_car_components(self, data):
self.components.append(Component(self, data));
c = Car({'type': 'bus', 'color': 'red'})
c.add_car_components({'name': 'frontdoor'})
c.add_car_components({'name': 'reardoor'})
for component in c.components:
print(component.owner.type, component.owner.color, component.name)
结果:
->python car.py
bus red frontdoor
bus red reardoor
经过一番测试,我终于找到了解决方案。也许这不是最好的方法(修复递归导入),但它符合我最初的想法。 在这个 link.
中说经过一番思考,我认为这可能被称为 forward-references,根据该文档 link 的广告。我将这两个 class 改写如下:
ComponentOfCar.py:
__all__ = ("ComponentOfCar");
import Car;
class ComponentOfCar(object):
__slots__=("owner","name");
def __init__(self, owner:'Car.Car',prop:dict={"name":"NoName"}):
self.owner = owner;
self.name = prop["name"];
if __name__=="__main__":
c=Car.Car({"type":"bus","color":"red"});
door1=ComponentOfCar(c,{"name":"frontdoor"});
door2=ComponentOfCar(c,{"name":"reardoor"});
c.InstallComponent(door1);
c.InstallComponent(door2);
print("We got the car",c);
for component in c.m_lstComponents:
print(component.name,component.owner);
comp1=c.m_lstComponents[0];#now we look at the first component
print("the component %s was installed on a %s %s"%(str(comp1),
comp1.owner.color,comp1.owner.type));
Car.py:
__all__ = ("Car");
import ComponentOfCar;
class Car(object):
__slots__ = ("m_lstComponents","type","color");
def __init__(self, data:dict):
self.m_lstComponents = list();
self.type=data["type"];
self.color=data["color"];
def InstallComponent(self, component:'ComponentOfCar.ComponentOfCar')->bool:
self.m_lstComponents.append(component);
return True;
if __name__=="__main__":
c=Car({"type":"bus","color":"red"});
door1=ComponentOfCar.ComponentOfCar(c,{"name":"frontdoor"});
door2=ComponentOfCar.ComponentOfCar(c,{"name":"reardoor"});
c.InstallComponent(door1);
c.InstallComponent(door2);
print("We got the car",c);
for component in c.m_lstComponents:
print(component.name,component.owner);
comp1=c.m_lstComponents[0];#now we look at the first component
print("the component %s was installed on a %s %s"%(str(comp1),comp1.owner.color,comp1.owner.type));
现在,我可以正确 运行 这段代码,并且得到如下输出:
We got the car <__main__.Car object at 0x0000015904C6AAC8>
frontdoor <__main__.Car object at 0x0000015904C6AAC8>
reardoor <__main__.Car object at 0x0000015904C6AAC8>
the component <ComponentOfCar.ComponentOfCar object at 0x0000015904C647F0> was installed on a red bus
现在我可以严格按照assemble代码写python代码了。我可以继续工作了。
如果有更好的方法满足我的需要,请指正。
谢谢大家。 :)