【问题标题】:Change class instance inside an instance method在实例方法中更改类实例
【发布时间】:2010-01-26 06:13:28
【问题描述】:

知道是否有办法使以下代码工作

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

【问题讨论】:

  • 为什么?您显然想要一个新实例,为什么不直接创建一个新实例并将其扔掉呢?请解释一下用例。

标签: python class instance hotswap


【解决方案1】:

self = Test(3) 正在重新绑定本地名称self,没有外部可观察到的影响。

分配self.__dict__(除非您正在谈论具有__slots__ 的实例或来自具有非平凡元类的类)通常是可以的,self.__init__(3) 重新初始化实例也是如此。不过,我更希望有一个特定的方法 self.restart(3),它知道它在一个已经初始化的实例上被调用,并且会做任何需要满足特定和不寻常的情况的事情。

【讨论】:

  • Django 的模型元类......很乱。如果尝试重新分配 self.__dict__ 会爆炸,我不会感到惊讶。
  • @Ignacio,使用“非平凡的元类”(或__slots__ 等),您可能希望使用getattr/setattr 的循环来代替。编写我提倡的 restart 方法的优点是,您可以隔离支持各种情况所需的调整(如果有的话),从普通对象到具有混乱元类的对象等等。
【解决方案2】:

没有,也没有。

话虽如此,您可以更改,但也不要这样做。

【讨论】:

    【解决方案3】:

    前面的代码可以工作,只是它不会做太多事情,因为它只是替换了 changeme() 范围内名为“self”的对象。 Python 名称不会锁定到值,它们总是相对于它们的作用域或命名空间。

    要做你想做的事,你需要访问班级之外的名字,你可以从里面分配给它:

    class Test:
      def changeme(self):
        global myclass
        myclass = Test(3)
    
    myclass = Test(2)
    myclass.changeme()
    print myclass # 3
    

    这基本上只是覆盖名称“myclass”以指向新实例。它不会像您想象的那样“覆盖”第一个实例。旧实例仍然存在,除非在其他地方引用,否则将被垃圾回收。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-24
      • 2014-01-22
      • 2012-10-22
      • 2013-11-12
      • 2014-11-21
      • 2022-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多