【问题标题】:Python: Best way to call methods from another class?Python:从另一个类调用方法的最佳方式?
【发布时间】:2011-06-16 07:00:58
【问题描述】:

我有以下代码:

class Player:
    def __init__(self, username, trip, model):
        self.username = username
        self.trip = trip
        self.hp = 100


    #### For player moving location/room ####
    def Move(self, dest):
        if dest == self.loc:
            return True

        # Check destination room is accessible from current room
        for room in aGame['rooms']:
            if room['ref'] == self.loc:
                for acsroom in room['acs']:
                    if acsroom == dest:
                        self.loc = dest
                        return True
        return False

aGame 是一个在此类之外定义的数组,因此此代码不起作用。 由于此类中可能有许多其他函数可能会使用 aGame 数组,我应该这样做:

class Player:
    def __init__(self, username, trip, model, aGame):
        self.username = username
        self.trip = trip
        self.hp = 100
        self.aGame = aGame            

    #### For player moving location/room ####
    def Move(self, dest):
        if dest == self.loc:
            return True

        # Check destination room is accessible from current room
        for room in self.aGame['rooms']:
            if room['ref'] == self.loc:
                for acsroom in room['acs']:
                    if acsroom == dest:
                        self.loc = dest
                        return True
        return False

或者这样做会更好:

class Player:
    def __init__(self, username, trip, model):
        self.username = username
        self.trip = trip
        self.hp = 100          

    #### For player moving location/room ####
    def Move(self, dest, aGame):
        if dest == self.loc:
            return True

        # Check destination room is accessible from current room
        for room in aGame['rooms']:
            if room['ref'] == self.loc:
                for acsroom in room['acs']:
                    if acsroom == dest:
                        self.loc = dest
                        return True
        return False

或者我应该让 aGame 成为一个全局变量(如果是,如何,注意这个类在不同的文件中)?

由于 aGame 是一个在所有地方都可以使用的数组,因此必须在每个类中复制它似乎是不正确的。 我可能有这个错误,我正在慢慢学习 OOP,所以感谢您的帮助。

【问题讨论】:

  • 您实际上并没有将aGame 字典复制到每个类中——参数是“通过引用”传递的。

标签: python oop class dictionary global


【解决方案1】:

在我看来,第一个选项是正确的,因为它没有充分的理由使用全局变量。所以选择是在第二个和第三个之间。

决定性的功能是您是否要对多个aGame 值使用相同的Player 实例。如果只有一个值,那么我要么将其传递给构造函数(您的选项 2),要么使用 gnibbler 将其设为类变量的想法。我可能倾向于将它传递给构造函数以便于测试。

如果您希望同一个 Player 实例可用于多个 aGame 值,那么选项 3 可能是实现这一目标的最简洁方法。

【讨论】:

  • 谢谢 :) 会有多个 Player 实例,但只有一个版本的 aGame。 aGame 是一个从文件加载值的字典 - 因此必须一直从文件中重新加载这些值将是低效的。我想我将不得不使用选项 2 将 aGame 设置为 self 类。并希望我最终不必在应用程序中出于任何原因更新 aGame dict。
  • @Tommo,只要您将同一个实例传递给所有实例,您对其所做的任何修改都将从每个实例中可见。 Python 不会复制字典,它只是创建对它的新引用。此外,如果您正在从文件中读取数据,您可能需要考虑使用 Walter Mundt 的想法和类方法来填充数组。
【解决方案2】:

每个实例的aGame 是否相同? 然后你可以像这样把它变成一个类属性

class Player:
    aGame={'rooms':...}
    ...

Class Player:
    ...

Player.aGame={'rooms':...}

在课堂内,您仍然可以通过self.aGame访问它

【讨论】:

    【解决方案3】:

    只有第一个选项有效。在第二个示例中,for room in self.aGame['rooms'] 将产生错误,因为没有任何地方 aGame 绑定到 self。如果它是for room in aGame['rooms'],它会起作用,但是你每次调用move() 时都必须不必要地传递aGame。

    您也可以将其设为全局变量,但最好让每个 Player 持有一个 aGame 实例。如果您需要更改 aGame 并拥有多个玩家,则应将其定义为全局变量。

    另外,只是吹毛求疵,但aGame 不是数组,而是字典。 Python 语言甚至没有数组(尽管一些扩展有)。

    【讨论】:

    • 对不起,我忘了删除“自我”。因为在第二个示例中,aGame 变量被传递到方法中。
    • 如果我将 aGame 添加到 Player 类中,那不就是复制当前 aGame 并将其应用到 Player 实例吗?那么如果 aGame 在类初始化后发生变化,那么 player1.aGame 会有所不同吗?
    • @Tommo,好吧,那么我的回答仍然有效。当每个Player 只能拥有一个实例时,为什么每次调用move() 时都要传递aGame?第一个解决方案更有意义,并且您需要的工作更少。如果你需要改变一个游戏并且有多个玩家,你应该将它定义为一个全局变量。
    【解决方案4】:

    我会在全局上使用一些细微的变化:

    # in game.py or whatever
    class Game(object):
        instance = {} # this is your aGame array
    
    # in player.py or whatever:
    from game import Game
    
    class Player(object):
        # ...
        def Move(self, dest):
            # ...
            for room in Game.instance['rooms']:
                # ...
    

    或者,您可以使 Game 成为一个适当的类,在初始化阶段将 Game.instance = Game(...) 分配给某个地方,并获得更多真正的单例模式。

    【讨论】:

    • 这种卷积有什么好处?
    • 好吧,我假设全局应该留在一个单独的模块中。在这种情况下,它消除了全局在导入时具有值的依赖性。如果没有容器类,播放器模块将不得不做from game import aGame。例如,如果初始化代码在加载播放器模块后分配给aGame 全局,则播放器模块的 aGame 值将不再正确。在这个版本中,这不是问题。其次,它使向拥有游戏范围状态的 Game 类的过渡更加明显,我认为这可能是一件好事。
    猜你喜欢
    • 2013-05-23
    • 2015-04-30
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多