Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

about python recursive import in python3 when using type annotation

After spending another three hours, I thought I may got the solution.forward-references

if there isn't any better way to do this, I'll close this question later and post that solution

I'm doing reverse engineering on a program (and try to implement it using Python).

I got this problem

for example I have a class in ComponentOfCar.py, the code is as follows

__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

Another class like this(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;

But after doing so I came across this problem:

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'

The original program is written in a compiled language. Inside that the class inheritance is very complicated, and it has hundreds classes, Which makes me headache.

I want to make this process a bit clearer by using type annotations and seperate each class into individual files. But this would have to use recursive import.

After googleing for half day, I havn't find some solution, so I come here to seek help. Is Python cannot do this like compiled language, or I just make some mistake? I'm confused. How can I fix it.

Sorry about my broken English. And thanks for your time. :)

to be detailed

Here is the structure of the decompiled class declaration like this(it's c#, the whole file is about a hundred thousands of lines):

// 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);
}

Or my question is how to use python to implement this clearly.

Yes, in my thought the way to do this showed above, I know that it's wrong, but I have no idea about how to make it right. I shouldn't separate them? Or I can have them written in another way (to avoid rescursive import and) to do the same thing as in c#?

Please tell me a way to solve this, thank you very much.

After spending another three hours, I thought I may got the solution

forward-references , I'm checking this. And if there isn't any better way to do this, I'll close this question later and post that solution, it may fixes my code.

like image 295
返还击 Avatar asked Aug 23 '26 03:08

返还击


1 Answers

Hope this would help,

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)

Result:

->python car.py

bus red frontdoor
bus red reardoor
like image 113
Reck Avatar answered Aug 26 '26 13:08

Reck



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!