2014-10-30 44 views
1

說我有一個模塊看起來像這樣:Python和循環進口再次

circlejerking/ 
├── bar.py 
├── foo.py 
└── __init__.py 

bar.py:

from .foo import Foo 

class Bar(Foo): 
    pass 

foo.py:

from .bar import Bar 

class Foo(object): 
    my_bar = Bar() 

__init__.py:

from .foo import Foo 
from .bar import Bar 

__all__ = [ 
    'Foo', 
    'Bar' 
] 

使用該模塊因循環導入而失敗。

In [1]: from circlejerking import Foo 
--------------------------------------------------------------------------- 
ImportError Traceback (most recent call last) 
<ipython-input-1-2258014c7099> in <module>() 
----> 1 from circlejerking import Foo 

/home/me/circlejerking/__init__.py in <module>() 
----> 1 from .foo import Foo 
2 from .bar import Bar 
3 
4 __all__ = [ 
5 'Foo', 

/home/me/circlejerking/foo.py in <module>() 
----> 1 from .bar import Bar 
2 
3 class Foo(object): 
4 my_bar = Bar() 

/home/me/circlejerking/bar.py in <module>() 
----> 1 from .foo import Foo 
2 
3 class Bar(Foo): 
4 pass 

ImportError: cannot import name Foo 

我明白的問題,我知道,那蟒蛇相關的圓形進口問題已討論多次,但我似乎無法得到這個工作。 兩個轉到答案SO有針對此問題是:

  1. 重新設計你的代碼,你持有它錯或
  2. 導入其他模塊只在你需要它。

我相當肯定,我的設計是好的,是的,我相信這兩個班其實不是一回事。

在其他地方導入其他類不是一個選項,因爲我需要它們在正確的位置。

任何想法?

+0

也許將所有導入移動到'__init__'?這樣你的進口訂單就一勞永逸地解決了 – inspectorG4dget 2014-10-30 18:08:54

+0

這應該是'Bar Bar(Foo)'類嗎?現在你根本沒有任何叫「酒吧」的東西。另外,你爲什麼「需要」這種方式? – BrenBarn 2014-10-30 18:09:21

+0

您的問題比循環進口更糟糕;你的類實際上有循環*引用*,即使它們都在同一個文件中定義,它也不能在Python中解析。看[這個問題](http://stackoverflow.com/questions/3270045/python-circular-references)。你確定你需要'my_bar'作爲類屬性而不是實例屬性嗎? – BrenBarn 2014-10-30 18:13:08

回答

0

一般來說,你可以用注射方式解決這個問題:

該模塊是細如-是:

from .foo import Foo 
class Bar(Foo): 
    pass 

那麼你其他的模塊就成爲:

class Foo(object): 
    bar = None 

    @classmethod 
    def set_bar(cls, bar): 
     cls.bar = bar 

這是再向上到任何使用Foo來確保set_bar在使用之前被適當地調用。