Pythonic" 的方式重置对象的变量?
("变量"在这里指的是"名称",我不太确定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 个回答
我会创建一个叫做 default 的字典,里面放着所有默认值,然后在 __init__ 方法里用 __dict__.update(self.default) 把这些默认值更新到当前对象里。之后在某个时刻再用这个方法把所有的值恢复回来。
更一般来说,你可以使用 __setattr__ 这个钩子来记录每一个被改变的变量,之后可以用这些数据来重置它们。
我不太确定“pythonic”是什么意思,但为什么不在你的对象里创建一个 reset 方法呢?这个方法可以做你需要的所有重置工作。你可以在 __init__ 方法里调用这个 reset 方法,这样就不需要重复写数据了(也就是说,始终在一个地方(即 reset 方法)重新初始化数据)。
不太确定这样做是否够“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:添加了一个继承的测试