You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多模块开发中window变量未定义NameError问题求助

问题分析:跨模块变量访问引发NameError

报错信息:

line 52, in main(), line 37, in main displayingTree(), line 23, in displayingTree i.display(window) NameError: name 'window' is not defined

开发的多模块Python程序中,displayingBug()看似可正常运行,但displayingTree()触发上述错误,逻辑上认为两者应行为一致。

代码片段

File 1(主模块)

# coding: utf-8

from variables import *
from bot_class import *
from tree_class import *
from movingBug import *
import pygame

pygame.init()

window = pygame.display.set_mode((gridWidth, gridHeight))
pygame.display.set_caption("Simulons la naissance d'une colonie")

def main():
    keepOn = True
    clock = pygame.time.Clock()
    areFirstBugs = False
    while keepOn:
        clock.tick(3)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                keepOn = False
        
        window.fill(backgroundColor)

        for x in range(0, gridWidth, cellSize):
            for y in range(0, gridHeight, cellSize):
                pygame.draw.rect(window, gridColor, (x, y, cellSize, cellSize), 1)
        
        if not areFirstBugs:
            firstBugsInit(areFirstBugs)
            areFirstBugs = True

        movingRedBugs()
        movingBlueBugs()
        displayingBug()
        displayingTree()


        pygame.display.update()
    pygame.quit()

def firstBugsInit(areFirstBugs):
    Bug(len(redBugList) + 1, red, 300, 10, 10, 8)

    Bug(len(blueBugList) + 1, blue, 300, 590, 590, 8)

    Tree(len(treeList) + 1, green, 60, 290, 290, 10)


if __name__ == "__main__":
    main()

File 2(tree_class.py)

from variables import *
from bot_class import *
from bots_grid import *
import pygame

class Tree():

    def __init__(self, number, color, frequency, xPos, yPos, size):
        self.number=number
        self.color=color
        self.frequency = frequency
        self.xPos=xPos
        self.yPos=yPos
        self.size=size
        treeList.append(self)
    
    def display(self, window):
        pygame.draw.rect(window, self.color, (self.xPos, self.yPos), self.size, self.size)


def displayingTree():
    for i in treeList:
        i.display(window)

File 3(bot_class.py)

from variables import *
from bots_grid import *
import threading
import pygame

class Bug():

    def __init__(self, number, color, maxAge, xPos, yPos, rayon): #maxAge est en seconde le temps qu'il reste au bug avant de mourir
        self.number=number
        self.color=color
        self.maxAge = maxAge
        self.xPos=xPos
        self.yPos=yPos
        self.rayon=rayon
        self.timer = threading.Timer(maxAge, self.destroy)
        allBugList.append(self)
        if color == red:
            redBugList.append(self)
        elif color == blue:
            blueBugList.append(self)
        self.planifyDeath()
    
    def display(self, window):
        pygame.draw.circle(window, self.color, (self.xPos, self.yPos), self.rayon)

    def planifyDeath(self):
        self.timer.start()

    def destroy(self):
        # Supprime le bug de la liste des bugs
        allBugList.remove(self)

        # Si le bug est bleu, le supprime également de la liste des bugs bleus
        if self.color == blue:
            blueBugList.remove(self)
            print('Bug '+ str(self.number) +' bleu est mort')

        # Si le bug est rouge, le supprime également de la liste des bugs rouges
        if self.color == red:
            redBugList.remove(self)
            print('Bug '+ str(self.number) +' rouge est mort')

        # Supprime le timer
        self.timer.cancel()

def displayingBug():
    for i in allBugList:
        i.display(window)

问题原因

  1. 模块命名空间独立性:每个Python模块拥有独立的全局命名空间。window变量定义在主模块(File1)的全局作用域中,但tree_class.py(File2)的命名空间中并未导入或定义该变量,因此displayingTree()函数尝试访问window时触发NameError。

  2. 关于displayingBug()看似正常的误区:实际上displayingBug()同样存在相同的问题,只是可能未触发报错(比如测试时allBugList为空,循环未执行到i.display(window))。Python函数的变量查找规则是在定义函数的模块命名空间中查找,而非调用时的模块,因此bot_class.py(File3)中的displayingBug()也无法正确访问主模块的window变量。

解决方案

最规范且无副作用的解决方式是将window作为参数传递给显示函数,具体步骤如下:

  1. 修改主模块(File1)的main()函数,调用显示函数时传入window:
# 替换原调用代码
displayingBug(window)
displayingTree(window)
  1. 修改tree_class.py(File2)中的displayingTree()函数,添加参数接收window:
def displayingTree(window):
    for i in treeList:
        i.display(window)
  1. 修改bot_class.py(File3)中的displayingBug()函数,添加参数接收window:
def displayingBug(window):
    for i in allBugList:
        i.display(window)

这种方式遵循了模块化设计原则,避免了全局变量共享带来的耦合问题,同时确保函数能正确获取所需的window对象。

内容的提问来源于stack exchange,提问作者archidoubi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 11:49:50