Pythonic方法解决循环导入语句?

Nat*_*han 33 python pageobjects

我只是继承了一些让我感到不安的代码:有一个测试库,其中包含与我们网站上的网页相对应的类,每个网页类都有自动化该页面功能的方法.

有一些方法可以单击页面之间的链接,返回链接页面的类.这是一个简化的例子:

文件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()
Run Code Online (Sandbox Code Playgroud)

文件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()
Run Code Online (Sandbox Code Playgroud)

然后,这允许脚本文件单击页面并将该对象作为该方法的返回值,这意味着脚本作者不必在浏览站点时保持实例化新页面.(我觉得这是一个奇怪的设计,但我不能完全理解为什么,除此之外,有一个名为'clickSomeLink'的方法并返回结果页面的对象似乎很奇怪.)

以下脚本说明了脚本如何在站点中导航:(我插入print page以显示页面对象如何更改)

脚本文件:

from homePageLib import HomePage

page = HomePage()    
print page
page = page.clickCalendarLink()
print page
page = page.clickHomePageLink()
print page
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

<homePageLib.HomePage object at 0x00B57570>
Click Calendar link
<calendarLib.CalendarPage object at 0x00B576F0>
Click Home Page link
<homePageLib.HomePage object at 0x00B57570>
Run Code Online (Sandbox Code Playgroud)

因此,我特别感到最不安的部分from ____ import ____是最终结束的线条.由于以下原因,这些让我感到害怕:

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

问题是,如果我们将这些import语句放在页面顶部,我们会得到导入错误,因为(根据此示例),HomePage导入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()
Run Code Online (Sandbox Code Playgroud)

文件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()
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误:

>>> 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
Run Code Online (Sandbox Code Playgroud)

(关于如何更好地格式化python输出的提示?)

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

ebo*_*ebo 63

解析这些结构通常涉及依赖注入等技术.

但是,修复此错误相当简单:

在calendarLib.py中:

import homePageLib

class CalendarPage(object):
    def clickHomePageLink(self):
        [...]
        return homePageLib.HomePage()
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我知道了.为什么这样有效?homePageLib仍然导入calendarPageLib,反之亦然. (4认同)
  • 这适用于所有循环导入问题吗?因为它没有解决我的问题。 (2认同)
  • 但是如果 `clickHomePageLink` 有返回值类型提示呢?这意味着返回值类型在外部 (2认同)

mih*_*hca 10

我有一个循环导入,因为我在类型提示中引用了一个类。这可以使用from __future__ import annotations(使用 Python 3.9.x 测试)来解决。

例子:

AClass.py

from BClass import BClass
class AClass():
    def __init__(self) -> None:
        self.bClass = BClass(self)
Run Code Online (Sandbox Code Playgroud)

BClass.py

from __future__ import annotations  # Without this, the type hint below would not work.
import AClass  # Note that `from AClass import AClass` would not work here.`
class BClass:
    def __init__(self, aClass: AClass.AClass) -> None:
        self.aClass = aClass
Run Code Online (Sandbox Code Playgroud)

  • 如果添加“from Typing import TYPE_CHECKING”,然后使用“if TYPE_CHECKING: from AClass import AClass”导入该类,则可以在类型提示中使用“AClass”而不是“AClass.AClass”。有关完整示例,请参阅 /sf/answers/4737161901/ (5认同)