如果我使用包含现有实例的相同变量来定义类的第二个实例会发生什么?

时间:2012-08-20 21:35:07

标签: python class variables instantiation

我不知道除了例子之外我怎么问这个问题。

让我说我有一个班级:

class Foo():
    pass

我创建了它的一个实例:

foo = Foo()
    ...

然后,作为我的程序的一部分,我重新创建具有相同名称的相同实例(重新启动游戏,但在另一个名为Bar的单独类中保持总分)。

foo = Foo()
    ...

(我不知道正确的术语)我没有编写任何代码来消除第一个实例。第一个实例是被删除还是被覆盖?它似乎适用于一个小程序。如果我多次这样做,我会遇到麻烦吗?

7 个答案:

答案 0 :(得分:13)

让我试着以图形方式解释它。

当你这样做时

foo = Foo()

第一次,您在内存中创建了一个类型为Foo对象Foo()),同时创建了一个变量将指向此对象:

enter image description here

执行时

foo = Foo()

第二次,您正在创建另一个对象。同时,您正在使用相同的变量并将其指向新对象。当然,变量不再指向前一个对象:

enter image description here

现在,第一个对象会发生什么?好吧,如果你的程序中有没有其他变量指向它,它就没用了,因为你再也无法访问了它!在这种情况下,当解释器运行垃圾收集器时,对象将从内存中销毁/释放。垃圾收集器是一种算法,它将查找每个无法访问的对象并将其删除。垃圾收集器不会每次都运行,因此可能需要一段时间来销毁对象。

因此,在您的场景中,会发生什么:

  • 第一个对象的引用将被覆盖,但该对象将存在。如果另一个变量指向它,它将不会被销毁。
  • 但是,如果没有其他变量指向它,将来某个时候将删除该对象。

答案 1 :(得分:5)

基本(可能是足够的)答案:

变量foo被分配给一个新实例,它不知道前一个实例。 它基本上与以下相同:

a = 1
a = 2

在某些时候(可能迟早),foo的旧实例将被垃圾收集(除非你仍然在其他地方引用它)。

理解这一点的简单方法是foo名称只是指向实际对象的指针。如果foo指向新对象,则foo指向新对象,句点。

相关细节:单身人士模式

有一些设计模式(我会想到singleton),这可能会改变这种行为。

基本上,Foo.__new__类方法决定了你Foo()时会得到什么。

可以构建此方法,以便它始终返回您创建的第一个实例,但这是非常偏离主题的。

以下是一个示例实现:

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

答案 2 :(得分:2)

第一foo = Foo()

它会创建一个新的实例对象并将其分配给foo,请参阅foo只是对Foo()

返回的对象的引用

第二foo = Foo()

它创建一个新的实例对象并将其分配给foo,并且前一个实例对象Foo()被垃圾收集,因为没有指向它的变量。

示例:

>>> class Foo:
...   pass
... 
>>> 
>>> foo=Foo()  
>>> id(foo)   #foo points to an object with id 3077166220L
3077166220L
>>> foo=Foo()  #now foo points to some other object and the object with id 3077166220L is garbage collected
>>> id(foo)
3077166252L  
>>> 
>>> 
>>> temp=foo      #now both foo and temp point to same object i.e 3077166252L  
>>> foo=Foo()     #assign foo to a new object
>>> id(temp)      #temp still points 3077166252L ,so it's not garbage collected   
3077166252L 
>>> id(foo)       #it points to a new object   
3077166092L       

答案 3 :(得分:1)

需要注意的几点。

  1. 名称'foo'是代码中定义的变量。在Python中,在为变量赋值之前,变量没有类型。
  2. 当您说foo = Foo()时,您要为变量foo分配Foo类型对象的实例。 Foo()通过调用Foo类的构造函数而不带任何参数来创建此实例。
  3. 每次调用Foo()都会创建一个新实例。因此,在代码中重复foo = Foo()将创建Foo类的多个实例,并将它们分配给变量foofoo变量指向的早期实例将不再具有引用,并且可以进行垃圾回收(假设您未同时为这些实例分配任何其他引用)。
  4. 因此,您用来描述问题的词语

      

    创建与现有名称相同的类的第二个实例   实例

    其实不对。因为您没有创建“具有相同名称”的另一个实例。您正在创建另一个实例,并将其分配给“相同的变量”。

答案 4 :(得分:0)

  1. Python中没有覆盖。
  2. 当您编写Foo()时,会创建一个新实例(类方法__new__,实例方法__init__将按顺序调用)
  3. 当没有指向类实例的指针时,Python的垃圾收集器最终将删除该实例(并在该实例上调用实例方法__del__

答案 5 :(得分:0)

您最终将新的Foo对象绑定到foo,旧的Foo对象将丢失引用。如果一个对象没有任何引用,那么它将在下一个垃圾收集中收集。

答案 6 :(得分:0)

第二个将覆盖第一个。 (它取代了模块的全局字典中的名称,其中存储了所有全局变量,函数和类。)

但是,您创建的foo = Foo()将继续使用创建时的原始实现,直到您创建一个新的foo = Foo()。