在实例方法中改变类实例
有没有人知道怎么让下面的代码正常工作呢?
class Test(object):
def __init__(self, var):
self.var = var
def changeme(self):
self = Test(3)
t = Test(1)
assert t.var == 1
t.changeme()
assert t.var == 3
像下面这样的写法,使用在更复杂的对象上(比如Django模型),这样可以快速切换实例所指向的数据库条目,这样安全吗?
class Test(object):
def __init__(self, var):
self.var = var
def changeme(self):
new_instance = Test(3)
self.__dict__ = new_instance.__dict__
t = Test(1)
assert t.var == 1
t.changeme()
assert t.var == 3
3 个回答
2
之前的代码是可以工作的,但它的作用不大,因为它只是把名为 'self' 的对象替换掉了,这个替换只在 changeme() 这个函数的范围内有效。Python 中的名字并不是固定在某个值上的,它们总是和它们所在的范围或命名空间有关。
如果你想实现你想要的功能,你需要访问类外部的一个名字,然后可以在类内部对这个名字进行赋值:
class Test:
def changeme(self):
global myclass
myclass = Test(3)
myclass = Test(2)
myclass.changeme()
print myclass # 3
这基本上就是把名字 'myclass' 指向了一个新的实例。它并不会像你想的那样“覆盖”第一个实例。旧的实例仍然存在,除非在其他地方被引用,否则它会被垃圾回收。
2
不,可以说不是。
不过,确实可以更改类,但也不要这么做。
7
self = Test(3)
其实是在重新给本地的名字 self
赋值,但外面的人看不出来有什么变化。
给 self.__dict__
赋值(除非你在谈论有 __slots__
的实例,或者是一些复杂的类)通常是可以的,使用 self.__init__(3)
来重新初始化这个实例也是可以的。不过,我更喜欢有一个专门的方法 self.restart(3)
,这个方法知道它是在一个已经初始化过的实例上被调用的,并且会做一些特别的处理来应对这种特殊情况。