Declaring a class and subclass in two different fi

2019-09-18 09:54发布

I have two files, one declaring a superclass which involves a method involving a subclass, and the other defining the subclass.

File1:

from file2 import subclass

class superclass:
    def __init__(self):
        "Stuff"

    def method(self):
        temp = subclass()
        "Stuff"

File2:

from file1 import superclass

class subclass(superclass):
    def __init__(self):
        "Stuff"

When I run file1's code I get an error inside file2 that superclass is not defined. This is because I import file2 before defining the superclass.

However if I import file2 after defining superclass I get an error in file1 saying the subclass is not defined. This is because I use a subclass instance in the method.

One solution to this problem is to have both superclass and subclass declarations in a single file, but I am wondering if there is a way to have them declared in different files.

3条回答
劳资没心,怎么记你
2楼-- · 2019-09-18 10:17

You can include the following line into your file2:

if superclass in locals(): print pass
else: 'Please define superclass'

Like this:

File2:

from file1 import superclass

class subclass(superclass):
    if superclass in locals(): pass
    else: print 'Please define superclass'
    def __init__(self):
        "Stuff"

Now try to run the file1 NOT file2. It will prompt 'Please define superclass'. But the subclass has been registered. Once you run something like:

x = superclass()

The subclass becomes workable.

查看更多
姐就是有狂的资本
3楼-- · 2019-09-18 10:21

Get temp from a method and override that method in the subclass.

class superclass:
    def get_temp(self):
        return 'a superclass temp'

    def method(self):
        temp = self.get_temp()
        print(type(self).__name__, repr(temp))

class subclass(superclass):
    def get_temp(self):
        return 'a subclass temp'


superclass().method()
subclass().method()

Output:

superclass 'a superclass temp'
subclass 'a subclass temp'

If you need method() to be different in subclass or perhaps do some work before or after superclass.method(), use the super keyword.

查看更多
不美不萌又怎样
4楼-- · 2019-09-18 10:37

The problem is easy to understand if you look at how Python loads modules:

  1. You run python file2.py.
  2. Python loads file2.py and starts to execute it.
  3. Python parses from file1 import superclass.
  4. Python loads file1.py and starts to execute it.
  5. Python parses from file2 import subclass.
  6. As file2 is already loaded, Python tries to access file2.subclass.
  7. Python didn't yet parse the class statement, so subclass doesn't exist yet. This causes the ImportError.

Python can handle circular dependencies as long the classes are already parsed when the second import happens. There are two ways to get that:

1) import file2 in the method itself.

class superclass:
    def __init__(self):
        "Stuff"

    def method(self):
        from file2 import subclass
        temp = subclass()
        "Stuff"

This causes the import to happen when method is called for the first time and not while importing/loading file1. The downside is that there is some runtime overhead every time method is called and that you must make sure that method() is only called after the import of file1 was completed.

2) import file2 at the end of file1 without using from import.

class superclass:
    def __init__(self):
        "Stuff"

    def method(self):
        temp = file1.subclass()
        "Stuff"

import file2

This way the circular import of file2 happens when superclass already exists in the namespace of file1. At that time the namespace of file2 is incomplete (file2.subclass doesn't exist yet, so from file2 import subclass would fail) but as long as method is never called before the imports succeeded, it works. The downside is that you need to keep track of which import statements need to be at the bottom of the file and which need to be at the top. Any error will cause ImportErrors that can be hard to track if your module hierarchy gets more complex.

That said, you should really rework your class hierarchy. Circular imports are (as I explained above) very fragile and should generally be avoided.

查看更多
登录 后发表回答