python循环引用的处理
假设同一文件夹下存在三个文件:a.py, b.py 和run.py
a和b中定义A,B,C类,run.py执行调用
a中定义类A和C,b中定义类B,其中B是A的子类,C是B的子类,
因此b.py中需要import A,a.py中需要import B,造成循环引用
文件内容分别如下(报错版):
a.py
from b import B
class A:
name = 'A'
def print_self(self):
print(self.name)
class C(B):
name = 'C'
c = C()
c.print_self()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
b.py
from a import A
class B(A):
name = 'B'
- 1
- 2
- 3
- 4
- 5
run.py
from a import A, B, C
test_A = A()
test_B = B()
test_C = C()
test_A.print_self()
test_B.print_self()
test_C.print_self()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
运行run.py,运行结果:
结果说明:
run.py中执行from a import A, B, C时,由于a.py中的B是从b.py中import过来的,
会到b.py中执行代码,遇到第一行from a import A,又回到a.py中执行from b import B,造成无限循环,编译器报错。
那怎么处理呢?
注意到B继承自A,C继承自B,我们可以在需要使用到B时再import B,也即把a.py修改如下(正确运行版):
class A:
name = 'A'
def print_self(self):
print(self.name)
from b import B
class C(B):
name = 'C'
c = C()
c.print_self()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
运行结果:
1.第一个”C”由A.py中c.print_self()输出
2.”A”由run.py中test_A.print_self()输出
3.”B”由run.py中test_B.print_self()输出
4.第二个“C”由run.py中test_C.print_self()输出
执行顺序:
1.from a import A, B, C时,会把a.py中的代码执行一遍
2.首先声明class A
3.执行到第8行from b import B,到b.py中,执行from a import A,由于A已经被声明,在这里返回一个A的引用,给B作父类(这是由于python编译器把每个模块都视为单例,已经import的模块便不再import,只是在b.py中建立一个A类的引用,供B类的声明与初始化)。
4.回到a.py中声明C,初始化c,执行c.print_self(),输出第一个”C”
5.a.py走完一遍,A,B,C均已声明,from a import A, B, C返回A,B,C三个类的引用
6.run.py继续往下执行,完成三个类的初始化与方法调用,依次输出“A”,“B”,“C”
以上为能解释现象的执行顺序,仅供参考,是否正确,需要到python源码中找解答
———————————update———————————
上述方案能执行,但理解上是不正确的,因为直接执行a.py也报错: