【问题标题】:Python 3.5.2: Import a class that imports another class in subdirectoryPython 3.5.2:导入一个在子目录中导入另一个类的类
【发布时间】:2017-05-04 01:08:12
【问题描述】:

我是 stackoverflow 和 Python 的新手,很抱歉出现错误。

我在这个项目目录中有game.py

类子目录中有两个类,CardClass 和 CardDeckClass。

CardDeckClass 使用 CardClass。

/project/game.py
/project/classes/CardClass.py
/project/classes/CardDeckClass.py

我在将 CardDeckClass 导入 game.py 时遇到问题

到目前为止,我已经尝试过:

*CardClass.py*
class CardClass:
    ##functionality for CardClass

*CardDeckClass.py*
from random import shuffle
from CardClass import CardClass
class CardDeckClass:
    ##functionality for CardDeckClass

*game.py*
from classes.CardDeckClass import CardDeckClass

testDeck = CardDeckClass()
print("Amount of cards in deck: ", testDeck.getCardCount())

上面在 CardDeckClass.py 的第二行给了我一个错误:from CardClass import CardClass

ImportError: 没有名为“CardClass”的模块

关于如何解决此问题的任何提示或想法?谢谢!

【问题讨论】:

    标签: python class module python-import


    【解决方案1】:

    虽然 DYZ 的答案有效,但我认为它给了你非常糟糕的建议。如果您将 classes 文件夹添加到 Python 模块搜索路径,您现在将能够以两种不同的方式找到 CardClassCardDeckClass 模块。您可以直接在顶层按名称获取它们(例如import CardClass),或通过classes 包(使用import classes.CardClass)。

    这种歧义很糟糕,因为 Python 不会意识到两个不同的名称应该指代同一个东西。相反,您将获得所有内容的两个副本,这可能会非常令人困惑。例如,isinstance(CardClass.CardClass(), classes.CardClass.CardClass) 将是 False

    相反,您应该修复 CardDeckClass.py 中的导入以正确导入 CardClass。有两种方法可以做到这一点,而你想要的是风格问题(没有一个正确的选择)。您可以使用绝对导入,在模块名称之外命名包:

    from classes.CardClass import CardClass
    

    或者您也可以使用显式的相对导入

    from .CardClass import CardClass
    

    注意模块名称开头的点,它告诉 Python 开始在当前包中搜索。

    您可能没有意识到,将您的CardClass.pyCardDeckClass.py 文件放在一个文件夹中就是为它们创建了一个包。在较旧版本的 Python(Python 3.3 之前)中,您需要将名为 __init__.py 的文件添加到文件夹中,然后它才能作为包工作。这不再是必要的(由于有些模糊的原因,它被更改了,请参阅PEP 420 和它所指的 PEP)。仍然建议添加__init__.py 文件,因为您通常不需要您的包是“命名空间包”(如果您不知道命名空间包是什么,则不需要)。

    最后一个建议:您的模块命名方案表明您创建的每个模块中只有一个类。这在 Python 中通常是不好的风格。与 Java 等其他语言不同,Python 模块中包含许多类、函数和其他内容是很正常的。过多地拆分代码会使导入比需要的复杂得多。在这种情况下,CardClassCardDeckClass 模块几乎肯定应该组合在一起,因为它们处理密切相关的对象。将它们组合到您的 game.py 文件中可能最有意义,尽管单独的 cards 模块也可以。几乎可以肯定这里不需要包。

    【讨论】:

    • 感谢您花时间向像我这样的 python 新手解释概念和约定。只是想知道模块和类之间的区别是什么。模块是可以包含许多类和函数的文件吗?模块中通常包含什么?
    • 是的,你在一个文件中的任何内容都将在 Python 内部的一个模块中。这可以包括许多类(使用class 语句声明),以及顶级函数(使用def 定义)。您可以将任何类型的对象放在模块的顶层(但类和函数是最常见的)。如果您想了解更多有关 Python 模块的信息,Python Tutorial 可能是一个不错的选择。
    【解决方案2】:

    通常子目录classes 不在默认导入路径上。如果您希望从非标准子目录中导入您的类,则必须将其添加到路径中:

    import sys
    sys.path.append("./classes")
    

    【讨论】:

    • 感谢您的快速回答!这正是缺少的。
    • 我认为这个答案虽然可能有效,但实际上非常有害。对于初学者来说,弄乱模块搜索路径并不是一个好主意。了解包并修复相对导入是更好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2021-10-06
    相关资源
    最近更新 更多