Python 3.5.2:导入一个 class,在子目录中导入另一个 class

Python 3.5.2: Import a class that imports another class in subdirectory

我是 Whosebug 的新手,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'

的模块

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

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

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

虽然 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 文件仍然被推荐,因为你通常不需要你的包是一个 "namespace package"(如果你不知道什么是命名空间包,你不需要一个)。

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