4

除了举例之外,我不知道如何问这个问题。

假设我有一堂课:

class Foo():
    pass

我创建了一个实例:

foo = Foo()
    ...

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

foo = Foo()
    ...

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

4

7 回答 7

13

让我试着用图形来解释它。

当你这样做

foo = Foo()

第一次,您在内存中创建一个类型的对象(使用),同时创建一个指向该对象的变量:FooFoo()

在此处输入图像描述

当你执行

foo = Foo()

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

在此处输入图像描述

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

所以,在你的场景中,会发生什么:

  • 对第一个对象的引用被覆盖,但该对象将存在。如果另一个变量指向它,它不会被销毁。
  • 但是,如果没有其他变量指向它,则该对象将在将来的某个时间点被消除。
于 2012-08-20T21:48:38.537 回答
5

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

该变量foo被分配给一个新实例,该实例对前一个实例一无所知。它基本上与以下内容相同:

a = 1
a = 2

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

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

相关细节:单例模式

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

基本上, Foo.__new__classmethod 决定了当你做的时候你会得到什么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
于 2012-08-20T21:39:43.983 回答
2

第一个foo = Foo()

它创建一个新的实例对象并将其分配给foo,seefoo只是对返回的对象的引用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       
于 2012-08-20T21:41:51.000 回答
1

有几点需要注意。

  1. 名称“foo”是您的代码中定义的变量。在 Python 中,变量没有类型,除非你给它赋值。
  2. 当您说要为foo = Foo()变量分配foo类型对象的实例时Foo。通过调用不带任何参数Foo()的类的构造函数来创建此实例。Foo
  3. 每次调用Foo()都会创建一个新实例。因此,foo = Foo()在您的代码中重复将创建Foo该类的多个实例,并将它们分配给变量foo。变量指向的早期实例foo将不再具有引用并且可以被垃圾收集(假设您同时没有为这些实例分配任何其他引用)。

因此,您用来描述问题的词语

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

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

于 2012-08-20T21:47:34.337 回答
0
  1. Python中没有覆盖。
  2. 编写时Foo()会创建一个新实例(按顺序调用类方法__new__和实例方法)__init__
  3. 当没有指向类实例的指针时,Python 的垃圾收集器最终将删除该实例(并__del__在该实例上调用实例方法)
于 2012-08-20T21:39:54.133 回答
0

你最终绑定了一个新的 Foo 对象foo,你的旧Foo对象将失去一个引用。如果一个对象没有任何引用,那么它将在下一次垃圾回收中被回收。

于 2012-08-20T21:40:02.777 回答
0

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

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

于 2012-08-20T21:40:11.837 回答