【问题标题】:Python Project Structure - multiple files and modulesPython 项目结构 - 多个文件和模块
【发布时间】:2020-04-25 03:48:01
【问题描述】:

我已经习惯了 PHP,其中一个全局变量将在整个项目中可用,并且包含/要求一个 PHP 文件几乎就像在那个地方“注入”它的代码行:整个事情都会被“看到”作为单个文件,所有变量都会被本能地访问。

Python 以不同的方式工作,我想了解一些好的做法,以便通过将大型项目拆分为文件来使其更易于管理...

假设我有一个名为 configs.py 的文件,类似于:

FRAME_DURATION = int(1000 / 25)
SCREEN_SIZE = 500

LIGHT_GREY  = (190,190,190)
RED = (255,0,0)
GREEN = (0,255,0)
YELLOW = (255,255,0)
#etc...

然后,在 Main.py 文件中,我可以执行以下操作:

import pygame
from configs import *

pygame.init()   
SCREEN = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE),1)
SCREEN.fill(LIGHT_GREY)

run = True
while run:
    pygame.time.delay(FRAME_DURATION )

    #HERE I'M SUPPOSED TO CHECK THE KEYBOARD AND MOUSE EVENTS

    pygame.display.update()

pygame.quit()

这很好,因为我们只处理变量。但是,如果我想将事件侦听器放入另一个单独的文件中,我会遇到一些“麻烦”。假设我想要一个包含我所有功能的文件。我将其命名为 actions.py,它包含以下函数:

def checkEvents():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                run = False
            if event.key == pygame.K_r:
                pass

如果我希望能够在 main.py 文件中调用 checkEvents() 函数,我会收到 NameError,因为它无法识别 actions.py 文件中的 pygame 模块。

我似乎无法让它工作:如果我在两个文件上都导入它(我知道这是最理想的),游戏会启动,但键和退出键什么都不做。我猜 checkEvents() 函数正在监听 pygame 的另一个实例?

无论如何,我想知道是否有办法使模块“全局可用”...在主文件中导入一次并在整个项目中使用它,包括在其他导入的自定义模块中?

最终的结果应该是这样的:

import pygame
from configs import *
import actions

pygame.init()   
SCREEN = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE),1)
SCREEN.fill(LIGHT_GREY)

run = True
while run:
    pygame.time.delay(FRAME_DURATION )

    actions.checkEvents()

    pygame.display.update()

pygame.quit()

【问题讨论】:

  • 您需要将初始化的 pygame 实例传递给 checkEvents(pygame) 或者创建一个单独的模块 - 例如game.py 包含 pygame 实例,然后将其导入 main.pyactions.py
  • 我尝试传递 pygame 和 run 变量但没有成功,我仍然需要通过任务管理器终止程序。还尝试将 'pygame.init()' 存储到一个变量中并将其传递给 checkEvents() 函数,但它会在 actions.py 文件中抛出一个 AttributeError ,说“'tuple'对象没有属性'event'”跨度>
  • 将初始化的 pygame 传递给 checkEvents() 的正确方法应该是什么?你能给我一个语法例子吗?另外,我不喜欢两次导入某些东西的想法...我在 main 中导入 game.py,在 actions.py 中也导入它,然后在 main 中导入 actions.py?如果对多个模块进行操作,这不会影响性能吗?还有,做维护好像没那么直观……
  • 你只需要import pygame in actions.py
  • 我试过了。 import pygame,然后,我打电话给actions.checkEvents(pygame) 我什至尝试actions.checkEvents(pygame, run) 看看它是否因为范围问题没有改变运行变量

标签: python scope architecture python-import python-module


【解决方案1】:

你只需要import pygame in actions.py

其他问题是run,你必须从checkEvents()返回

import pygame 

def checkEvents():
    run = True # local variable with default value before all tests

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False # set local variable

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                run = False # set local variable
            if event.key == pygame.K_r:
                pass

    return run # return local value to main code

然后你在main.py 中得到run

import pygame
from configs import *
import actions

pygame.init()   
SCREEN = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE),1)
SCREEN.fill(LIGHT_GREY)

run = True
while run:
    pygame.time.delay(FRAME_DURATION )

    run = actions.checkEvents() # get result from function and assign to `run`

    pygame.display.update()

pygame.quit()

【讨论】:

  • 好的,这解决了这个特定的问题,但必须有更好的方法......如果我想在 checkEvents() 中与SCREEN 交互,让我们说变暗或变亮它的填充颜色。我需要通过它然后再返回它吗?我们没有改变范围,我们传递变量然后返回它们......如果我的 checkEvents() 函数需要为每个按下的键更改不同的变量,这可能是一个问题......
  • 另外,两次导入模块不是次优的吗?当我让这个架构越来越复杂时,它会不会花费成倍的时间?
  • 你需要 pygame in actions.py 所以导入它 - 这是自然的方法 - 不要浪费时间“次优”和“指数”,因为你永远不会看到这个问题。
  • 如果你需要 SCREEN in checkEvents() 然后将其作为参数发送 - run = actions.checkEvents(SCREEN)def checkEvents(SCREEN): 而且你不必将其发回 - 它不是改变值的简单变量但是类实例会改变其属性的值。
  • 我明白了......所以,绝对没有办法在两个导入的模块之间全局访问变量或函数/方法?无论如何,我感谢您的帮助,非常感谢
猜你喜欢
  • 1970-01-01
  • 2014-03-08
  • 2012-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-18
  • 2021-12-30
相关资源
最近更新 更多