Pythonic" 的方式重置对象的变量?

17 投票
10 回答
33663 浏览
提问于 2025-04-16 11:02

("变量"在这里指的是"名称",我不太确定pythonista们使用的定义)

我有一个对象和一些方法。这些方法都需要使用并且会改变对象的变量。那我该如何以最符合Python风格和面向对象编程(OOP)的方法,让这些方法使用对象的变量,同时又能保持它们的原始值供其他方法使用呢?

我每次调用一个方法时都应该复制这个对象吗?还是应该保存原始值,并在每次需要的时候用一个reset()方法来重置它们?或者还有更好的方法吗?

编辑:有人问我要伪代码。因为我更想理解这个概念,而不仅仅是解决我遇到的问题,所以我会尝试给一个例子:

class Player():
    games = 0
    points = 0
    fouls = 0
    rebounds = 0
    assists = 0
    turnovers = 0
    steals = 0

    def playCupGame(self):
        # simulates a game and then assigns values to the variables, accordingly
        self.points = K #just an example

    def playLeagueGame(self):
        # simulates a game and then assigns values to the variables, accordingly
        self.points = Z #just an example
        self.rebounds = W #example again

    def playTrainingGame(self):
        # simulates a game and then assigns values to the variables, accordingly
        self.points = X #just an example
        self.rebounds = Y #example again

上面是我为一个玩家对象(假设他是个篮球运动员)写的类。这个对象有三个不同的方法,都会给玩家的统计数据赋值。

假设这个队伍有两场联赛和一场杯赛。我需要进行以下调用:

p.playLeagueGame()
p.playLeagueGame()
p.playCupGame()

很明显,当进行第二次和第三次调用时,玩家之前改变的统计数据需要被重置。为此,我可以写一个reset方法,把所有变量都重置为0,或者每次调用时复制对象。或者做一些完全不同的事情。

这就是我的问题所在,什么方法在Python和OOP方面是最好的呢?

更新:我怀疑我把这个问题复杂化了,其实可以通过在函数中使用局部变量轻松解决。不过,如果我在一个函数里面有另一个函数,外层函数的局部变量可以在内层函数中使用吗?

相关问题:

10 个回答

3

我会创建一个叫做 default 的字典,里面放着所有默认值,然后在 __init__ 方法里用 __dict__.update(self.default) 把这些默认值更新到当前对象里。之后在某个时刻再用这个方法把所有的值恢复回来。

更一般来说,你可以使用 __setattr__ 这个钩子来记录每一个被改变的变量,之后可以用这些数据来重置它们。

7

我不太确定“pythonic”是什么意思,但为什么不在你的对象里创建一个 reset 方法呢?这个方法可以做你需要的所有重置工作。你可以在 __init__ 方法里调用这个 reset 方法,这样就不需要重复写数据了(也就是说,始终在一个地方(即 reset 方法)重新初始化数据)。

8

不太确定这样做是否够“Pythonic”,但你可以为__init__方法定义一个“可重置”的装饰器,这个装饰器会复制对象的__dict__(也就是对象的属性和它们的值),并添加一个reset()方法,这个方法可以把当前的__dict__切换回最初的那个。

编辑 - 这里有一个示例实现:

def resettable(f):
    import copy

    def __init_and_copy__(self, *args, **kwargs):
        f(self, *args)
        self.__original_dict__ = copy.deepcopy(self.__dict__)

        def reset(o = self):
            o.__dict__ = o.__original_dict__

        self.reset = reset

    return __init_and_copy__

class Point(object):
    @resettable
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return "%d %d" % (self.x, self.y)

class LabeledPoint(Point):
    @resettable
    def __init__(self, x, y, label):
        self.x = x
        self.y = y
        self.label = label

    def __str__(self):
        return "%d %d (%s)" % (self.x, self.y, self.label)

p = Point(1, 2)

print p # 1 2

p.x = 15
p.y = 25

print p # 15 25

p.reset()

print p # 1 2

p2 = LabeledPoint(1, 2, "Test")

print p2 # 1 2 (Test)

p2.x = 3
p2.label = "Test2"

print p2 # 3 2 (Test2)

p2.reset()

print p2 # 1 2 (Test)

编辑2:添加了一个继承的测试

撰写回答