繁体   English   中英

我是否应该始终使用最pythonic的方式导入模块?

[英]Should I always use the most pythonic way to import modules?

我正在为pygame开发一个小型游戏框架,在该框架上我希望实现基本代码以快速启动新项目。 这将是一个模块,无论谁使用,都应仅创建一个带有子文件夹的子文件夹,用于存放精灵类,地图,关卡等。我的问题是,我的框架模块应如何加载这些客户端模块? 我正在考虑对其进行设计,以便开发人员可以将目录名称传递给主对象,例如:

game = Game()
game.scenarios = 'scenarios'

然后游戏会将“场景”追加到sys.path并使用__import__() 我已经测试了而且可以用 但是后来我研究了一下,看是否在python中已经有一些自动加载器,所以我可以避免重写它,而我发现了这个问题Python模块自动加载器? 基本上,不建议在python中使用自动加载器,因为“显式优于隐式”和“可读性”。

这样,我认为,我应该强迫我的模块的用户手动导入他/她的每个模块,并将它们传递给游戏实例,例如:

import framework.Game
import scenarios
#many other imports
game = Game()
game.scenarios = scenarios
#so many other game.whatever = whatever

但这对我来说并不好,不那么舒服。 看,我曾经使用过php,我喜欢它与自动加载器一起工作的方式。 因此,第一个示例可能会崩溃或出现麻烦,还是不是“ pythonic”?

注意: 这不是Web应用程序

我不会考虑让库从我当前的路径或模块好的样式中导入内容。 相反,我只希望库从两个地方导入:

  1. 从全局模块空间绝对导入,就像您使用pip安装的东西一样。 如果库执行此操作,则还必须在其install_requires=[]列表中找到该库。

  2. 从自身内部的相对进口。 如今,这些已明确从中导入.

     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()类,该类实现某个接口以提供spritesmaps等。原因是:Sprites和Maps通常存储在单独的文件中: 您绝对不想做的是查看scenarios__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模块,该模块在不使用scenarios=关键字arg的情况scenarios=使用(例如,用于方形默认贴图和一些彩色默认纹理)

from . import contrib

class Game()
    def __init__(self, ..., scenarios=None, ...):
        if scenarios is None:
            scenarios = contrib.scenarios
        self.scenarios = scenarios

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM