Python变量范围混淆

Python变量范围混淆,python,Python,我正在设置一个简单的游戏,从玩家类实例访问游戏类实例时遇到问题: class Player(): global game print game.board # NameError: name 'game' is not defined class Game(): def __init__(self): self.board = range(9) p = Player() if __name__ == "__main__": ga

我正在设置一个简单的游戏,从玩家类实例访问游戏类实例时遇到问题:

class Player():
    global game
    print game.board  # NameError: name 'game' is not defined


class Game():
    def __init__(self):
        self.board = range(9)

    p = Player()


if __name__ == "__main__":
    game = Game()

我相信这只是我的一个简单的修正/误解,但我还缺少什么?

更好的方法是使用DI(依赖注入),以便在初始化时将
游戏
对象“传递”给
玩家

class Player(object):
    def __init__(self, game):
        self.game = game  

    def print_player(self):
        print self.game.board


class Game(object):
    def __init__(self):
        self.board = range(9)


if __name__ == "__main__":
    game = Game()
    player = Player(game)
    player.print_player() # prints [0, 1, 2, 3, 4, 5, 6, 7, 8]
依赖于
globals()
是因为它依赖于执行顺序(就像在您的案例中),使代码可读性降低(您必须从一个地方跳到另一个地方,而不是“流利地”阅读),并且可能会带来副作用

坏习惯(即不要在家里做!):
以下代码(尽管这是一种不好的做法)将起作用,因为当您使用
globals()
时,减速顺序是有意义的:
game=game()
应该在class
Player
之前声明,以便在那里使用:

class Game():
    def __init__(self):
        self.board = range(9)

game = Game()

class Player():
    global game
    print game.board 

p = Player() # prints [0, 1, 2, 3, 4, 5, 6, 7, 8]

更好的方法是使用DI(依赖注入),以便在初始化时将
游戏
对象“传递”给
玩家

class Player(object):
    def __init__(self, game):
        self.game = game  

    def print_player(self):
        print self.game.board


class Game(object):
    def __init__(self):
        self.board = range(9)


if __name__ == "__main__":
    game = Game()
    player = Player(game)
    player.print_player() # prints [0, 1, 2, 3, 4, 5, 6, 7, 8]
依赖于
globals()
是因为它依赖于执行顺序(就像在您的案例中),使代码可读性降低(您必须从一个地方跳到另一个地方,而不是“流利地”阅读),并且可能会带来副作用

坏习惯(即不要在家里做!):
以下代码(尽管这是一种不好的做法)将起作用,因为当您使用
globals()
时,减速顺序是有意义的:
game=game()
应该在class
Player
之前声明,以便在那里使用:

class Game():
    def __init__(self):
        self.board = range(9)

game = Game()

class Player():
    global game
    print game.board 

p = Player() # prints [0, 1, 2, 3, 4, 5, 6, 7, 8]


解释器将首先尝试使class
Player
,然后使class
Game
,然后运行代码。因此,在执行
game=game()
之前,它将使class
Player
,因此此时没有变量
game
,并导致您的错误

解释器将首先尝试使class
玩家
,然后使class
游戏
,然后运行代码。因此,在执行
game=game()
之前,它将使class
Player
,因此此时没有变量
game
,并导致您的错误

@legostrmtropr否决票意味着“没有用的答案”。虽然它没有解释问题的根源,但它解释了如何通过编写更好的代码来避免问题。你认为这没用吗?我知道使用global是个坏主意,但这种行为仍然让我感到惊讶。这种将游戏实例传递给玩家的方法让我觉得很奇怪;我认为玩家是游戏的一部分,而不是游戏的一部分。不过,我确实明白你的意思,谢谢你的反馈。@调试DI一开始可能有点混乱,但当你习惯了它,它就变得自然了。它有它的优点,例如,它使您的代码更容易测试。@legostrmtropr否决票意味着“没有有用的答案”。虽然它没有解释问题的根源,但它解释了如何通过编写更好的代码来避免问题。你认为这没用吗?我知道使用global是个坏主意,但这种行为仍然让我感到惊讶。这种将游戏实例传递给玩家的方法让我觉得很奇怪;我认为玩家是游戏的一部分,而不是游戏的一部分。不过,我确实明白你的意思,谢谢你的反馈。@调试DI一开始可能有点混乱,但当你习惯了它,它就变得自然了。它有它的优点,例如,它使您的代码更容易测试。不知道为什么它被否决。。。通过添加我的加号1来更正;)@史蒂文·鲁姆巴斯基在我读到的时候,你和龙2说了完全一样的话。您表达的方式更清楚定义类和创建类实例之间的区别,但是你说的是同一件事。@Steven Rumbalski我说错误发生在类
Player
的创建过程中,而不是在该类的实例创建时。所以我的误解是解释器处理代码的顺序。我想它将从if name==“main”条件开始,但这不可能是正确的,因为我不能在Player类之前定义Game类并让代码工作。口译员肯定是从文件的顶端开始的。不知道为什么会被否决。。。通过添加我的加号1来更正;)@史蒂文·鲁姆巴斯基在我读到的时候,你和龙2说了完全一样的话。您表达的方式更清楚定义类和创建类实例之间的区别,但是你说的是同一件事。@Steven Rumbalski我说错误发生在类
Player
的创建过程中,而不是在该类的实例创建时。所以我的误解是解释器处理代码的顺序。我想它将从if name==“main”条件开始,但这不可能是正确的,因为我不能在Player类之前定义Game类并让代码工作。解释器肯定是从文件的顶部开始的。你不是“从玩家类实例访问游戏类实例”。你是从玩家类定义访问它,定义类时执行一次。如果在玩家的方法中定义了该代码,那么它就可以工作了。同样值得怀疑的是游戏类定义中对玩家
p
的类级引用。您可能需要将其移动到游戏的
\uuuu init\uuuu
方法。它不起作用,因为解释器创建
玩家时
游戏
不存在。您有一个难题,每个类都有一个对另一个的引用,但是因为Python按顺序创建对象,所以无论您如何重新排列定义,一个对象始终不存在。您需要重新考虑设计。@StevenRumbalski您是对的,game.board访问权限在玩家类定义中