2011-04-21 62 views
21

我只是继承了一些让我感到不安的代码:有一个测试库,其中包含与我们网站上的网页相对应的类,并且每个网页类都有自动执行该页面功能的方法。Pythonic方式来解决循环导入语句?

有方法可以单击页面之间的链接,它将返回链接页面的类。这里有一个简单的例子:

文件homePageLib.py:

class HomePage(object): 
    def clickCalendarLink(self): 
     # Click page2 link which navigates browswer to page2 
     print "Click Calendar link" 
     # Then returns the page2 object 
     from calendarLib import CalendarPage 
     return CalendarPage() 

文件calendarLib.py:

class CalendarPage(object): 
    def clickHomePageLink(self): 
     # Click page1 link which navigates browswer to page1 
     print "Click Home Page link" 
     # Then return the page2 object 
     from homePageLib import HomePage 
     return HomePage() 

这就允许脚本文件,点击网页并获取对象作为回报来自该方法的值,这意味着脚本作者在他们在网站周围导航时不必实例化新页面。 (我觉得这是一个奇怪的设计,但我不能完全明白为什么,除此之外,有一种名为'clickSomeLink'的方法似乎很奇怪,并返回所得页面的对象。)

下面的脚本显示了脚本如何浏览该网站围绕:(我插print page展示如何在页面对象发生变化)

脚本文件:

from homePageLib import HomePage 

page = HomePage()  
print page 
page = page.clickCalendarLink() 
print page 
page = page.clickHomePageLink() 
print page 

产生以下输出:

<homePageLib.HomePage object at 0x00B57570> 
Click Calendar link 
<calendarLib.CalendarPage object at 0x00B576F0> 
Click Home Page link 
<homePageLib.HomePage object at 0x00B57570> 

因此,我特别感到最不自在的部分是最后结束的from ____ import ____。由于以下原因,这些攻击都不好:

  1. 我一直把它作为一个惯例,把所有导入语句放在文件的顶部。
  2. 由于页面可能存在多个链接,因此会在文件的多个位置产生相同的from foo import bar行代码。

的问题是,如果我们把这些import语句在页面的顶部,我们得到导入错误,因为(按照本例),首页进口CalendarPage反之亦然:

文件homePageLib。 PY

from calendarLib import CalendarPage 

class HomePage(object): 
    def clickCalendarLink(self): 
     # Click page2 link which navigates browswer to page2 
     print "Click Calendar link" 
     # Then returns the page2 object 

     return CalendarPage() 

文件calendarLib.py

from homePageLib import HomePage 

class CalendarPage(object): 
    def clickHomePageLink(self): 
     # Click page1 link which navigates browswer to page1 
     print "Click Home Page link" 
     # Then return the page2 object 
     return HomePage() 

这将导致以下错误:

>>> from homePageLib import HomePage 
Traceback (most recent call last): 
    File "c:\temp\script.py", line 1, in ? 
    #Script 
    File "c:\temp\homePageLib.py", line 2, in ? 
    from calendarLib import CalendarPage 
    File "c:\temp\calendarLib.py", line 2, in ? 
    from homePageLib import HomePage 
ImportError: cannot import name HomePage 

(关于如何更好的格式Python的输出秘诀吗?)

而不是延续这种风格,我想找到一个更好的办法。有没有Pythonic的方式来处理这样的循环依赖,并仍然在文件顶部保留import语句?

回答

46

解析这些构造通常涉及诸如Dependency Injection的技术。

据,然而,相当简单修复此错误:

在calendarLib.py:

import homePageLib 

class CalendarPage(object): 
    def clickHomePageLink(self): 
     [...] 
     return homePageLib.HomePage() 

在模块级别的代码在导入时被执行。使用from [...] import [...]语法要求模块完全初始化才能成功。

一个简单的import [...]没有,因为没有符号被访问,从而打破了依赖链。

+4

我明白了。为什么这是有效的? homePageLib仍然导入calendarPageLib,反之亦然。 – Nathan 2011-04-21 19:53:57

+0

@nathan:请看看这个了解更多信息。 http://stackoverflow.com/questions/710551/import-module-or-from-module-import – chuan 2016-10-10 18:34:03

-12

是的。重构将事物分解成更小,独立的部分。

+0

问题是关于如何正确地重构它以使这些部分独立。 – 2014-09-21 16:27:54

0

有关详细说明,请阅读Sebastian's answer。这种方法在PyCon

,提出了由大卫比兹利尝试定位在顶部的进口这样

try: 
    from homePageLib import HomePage 
except ImportError: 
    import sys 
    HomePage = sys.modules[__package__ + '.HomePage'] 

这将尝试导入您的HomePage,如果失败,将尝试从缓存加载