我正在使用pygame为游戏制作一个小框架,我希望在其上实现基本代码以快速启动新项目。这将是一个模块,谁使用谁应该只创建一个文件夹与子文件夹的精灵类,地图,级别等。 我的问题是,我的框架模块应该如何加载这些客户端模块?我正在考虑设计它,以便开发人员可以将目录的名称传递给主对象,例如:
game = Game()
game.scenarios = 'scenarios'
然后游戏会将'scenario'附加到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'?
注意:这不是网络应用
答案 0 :(得分:4)
我不会考虑让图书馆从我当前的路径或模块中导入好东西。相反,我只希望从两个地方导入一个库:
从全局模块空间绝对导入,就像使用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()
类来实现某个界面,以提供sprites
,maps
等。原因是:精灵和地图通常保存在单独的文件中:您绝对不想做的事情是查看scenarios
的{{1}}属性并开始猜测其文件。而是实现一个为其提供统一接口的方法。
__file__
您的特定于用户的方案将从中派生出来,并可选择重载加载方法
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
关键字arg的情况下使用(即对于方形默认地图和一些彩色默认值纹理)
scenarios=