我正在使用 pygame 制作一个小型游戏框架,我希望在其上实现基本代码以快速启动新项目。这将是一个模块,无论谁使用,都应该只创建一个文件夹,其中包含 Sprite 类、 map 、关卡等的子文件夹。 我的问题是,我的框架模块应该如何加载这些客户端模块?我正在考虑设计它,以便开发人员可以将目录名称传递给主对象,例如:
game = Game()
game.scenarios = 'scenarios'
然后游戏会将“场景”附加到 sys.path 并使用 __import__()
。 我已经测试过并且有效。
但是后来我多研究了一下,看看python中是否已经有一些自动加载器,所以我可以避免重写它,我发现了这个问题Python modules autoloader?
基本上,不建议在 python 中使用自动加载器,因为“显式优于隐式”和“可读性很重要”。
那样的话,我想,我应该强制我的模块的用户手动导入他/她的每个模块,并将它们传递给游戏实例,例如:
import framework.Game
import scenarios
#many other imports
game = Game()
game.scenarios = scenarios
#so many other game.whatever = whatever
但这对我来说不太好,不太舒服。看,我习惯于使用 php,我喜欢它与自动加载器一起工作的方式。 所以,第一个例子有一定的崩溃或麻烦的可能性,或者它不是'pythonic'?
注意:这不是网络应用程序
最佳答案
我不会考虑让库从我当前的路径或模块好的样式中导入东西。相反,我只希望从两个地方导入一个库:
从全局模块空间绝对导入,例如您使用
pip
安装的东西。如果库执行此操作,则还必须在其install_requires=[]
列表中找到该库从自身内部的相对导入。现在这些都是从
明确导入的。
:from . import bla from .bla import blubb
这意味着传递一个对象或模块本地到我的当前范围必须总是显式地发生:
from . import scenarios
import framework
scenarios.sprites # attribute exists
game = framework.Game(scenarios=scenarios)
这允许你做一些事情,比如模拟 scenarios
模块:
import types
import framework
# a SimpleNamespace looks like a module, as they both have attributes
scenarios = types.SimpleNamespace(sprites='a', textures='b')
scenarios.sprites # attribute exists
game = framework.Game(scenarios=scenarios)
你也可以实现一个framework.utils.Scenario()
类,它实现了某个接口(interface)来提供sprites
、maps
等。原因是: Sprite 和 map 通常保存在单独的文件中:你绝对不想做的是查看场景
的__file__
属性并开始猜测它的文件。而是实现一个为其提供统一接口(interface)的方法。
class Scenario():
def __init__(self):
...
def sprites(self):
# optionally load files from some default location
# If no such things as a default location exists, throw a NotImplemented error
...
您的用户特定场景将从中派生并可选择重载加载方法
import framework.utils
class Scenario(framework.utils.Scenario):
def __init__(self):
...
def sprites(self):
# this method *must* load files from location
# accessing __file__ is OK here
...
您还可以让 framework
发布它自己的 framework.contrib.scenarios
模块,在没有 scenarios=
关键字的情况下使用使用了 arg(即用于方形默认贴图和一些彩色默认纹理)
from . import contrib
class Game()
def __init__(self, ..., scenarios=None, ...):
if scenarios is None:
scenarios = contrib.scenarios
self.scenarios = scenarios
关于python - 我应该始终使用最 pythonic 的方式来导入模块吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49730635/