【问题标题】:Class cross referencing?类交叉引用?
【发布时间】:2023-03-03 15:56:01
【问题描述】:

我来自 C++ 背景,如果没有 Python 中的整个指针概念,我有点迷茫。或者至少还不清楚。 例如,我想在 Python 中使用 OOP 创建一个刻度线游戏。我有几个这样的课程:

class Game(object):
    def __init__(self, player1, player2):
        self.board = [['','',''],
                      ['','',''],
                      ['','','']]
        self.players = [player1, player2]

class Player(object):
    def __init__(self, game, marking):
        self.game = game
        self.marking = marking  # either 'X' or 'O'

很明显,游戏需要引用两个玩家,而玩家也是游戏的一部分,因此应该引用游戏。但是,上面的代码不起作用,因为如果不先创建游戏,我就无法创建玩家。但是要创建一个游戏,我需要两个玩家。 之后我可以通过执行以下操作来添加这些引用:player.game = some_game_reference 但这似乎不合 Python 且难以跟上。

完成此任务的最佳和最 Pythonic 方式是什么?

【问题讨论】:

  • objectplayer1有效的指针。它们不是值,就像在 C++ 中那样。
  • 为什么玩家需要了解游戏?游戏由一个棋盘和两个玩家组成。游戏知道轮到谁了以及棋盘的状态。玩家无需了解游戏。
  • 在 python 中你需要两个对象相互引用是非常罕见的。当您确实需要时,通常其中一个包含另一个,并且通常会在另一个上设置对自身的引用,最常见的是直接设置(此时对象已经紧密耦合)。
  • 如果您创建一个游戏列表,您可以查询每个游戏是否包含特定玩家。这样一个玩家甚至可以参与多场比赛,而不仅限于一场比赛。或者创建一个类Casino 来跟踪哪个玩家正在玩哪个游戏。
  • 老实说,您根本不应该在 Python 中考虑指针。它是一种比这更高级别的语言。没有实际的指针类型,但是“在底层”,您可以想到 Python 将指针传递给 Py_Object 结构。但老实说,您应该阅读 Ned Batchelder 的 Facts and Myths about Python names and values

标签: python c++ class inheritance


【解决方案1】:

你可以只让一个类或另一个更新它的参数。例如,先创建玩家,然后让游戏自行更新玩家:

class Game(object):
    def __init__(self, player1, player2):
        self.board = [['','',''],
                      ['','',''],
                      ['','','']]
        self.players = [player1, player2]
        player1.game = self
        player2.game = self
        player1.marking = 'X'
        player2.marking = 'O'  

# Neither game nor marking make sense to set initially, until
# the players are added to a game.
class Player(object):
    def __init__(self):
        pass

p1 = Player()
p2 = Player()

g = Game(p1, p2)

(您是否需要这种耦合,正如其他人指出的那样,是一个单独的设计问题。)

仅仅展示另一个方向也是可行的:

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

class Game(object):
    def __init__(self):
        self.board = [['','',''],
                      ['','',''],
                      ['','','']]

g = Game()
p1 = Player(g, 'X')
p2 = Player(g, 'O')

不过,希望您同意游戏为每个玩家分配一个标记更有意义。在这里,您可以尝试在游戏中添加超过 2 个玩家,或者添加两个 X 或两个 O 玩家。

【讨论】:

  • 这很有帮助,谢谢。我会看看是否发布了其他答案,但这似乎解决了我的问题。我不知道我可以将 self 分配给一个变量。你会说有更好的方法吗?上面的 cmets 指出,通常不需要这样的东西,但在我看来,这样我可以创建某种图形(数据结构),并且每个玩家可能有多个游戏。谢谢!
  • 这真的取决于你的应用程序的结构,但我同意你应该努力Player类不需要任何关于游戏的信息玩家参与其中。至于self,这个名字并没有什么特别之处;你可以使用任何你想要的名字,但self 是传统的。它只是指作为任何实例方法的(隐式)第一个参数传递的对象。任何方法调用obj.method(...) 等价于type(obj).method(obj, ...);参数self(或您使用的任何名称)绑定到obj
猜你喜欢
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 2011-03-03
  • 2013-11-11
  • 1970-01-01
相关资源
最近更新 更多