我不知道除了例子之外我怎么问这个问题。
让我说我有一个班级:
class Foo():
pass
我创建了它的一个实例:
foo = Foo()
...
然后,作为我的程序的一部分,我重新创建具有相同名称的相同实例(重新启动游戏,但在另一个名为Bar的单独类中保持总分)。
foo = Foo()
...
(我不知道正确的术语)我没有编写任何代码来消除第一个实例。第一个实例是被删除还是被覆盖?它似乎适用于一个小程序。如果我多次这样做,我会遇到麻烦吗?
答案 0 :(得分:13)
让我试着以图形方式解释它。
当你这样做时
foo = Foo()
第一次,您在内存中创建了一个类型为Foo
的对象(Foo()
),同时创建了一个变量将指向此对象:
执行时
foo = Foo()
第二次,您正在创建另一个对象。同时,您正在使用相同的变量并将其指向新对象。当然,变量不再指向前一个对象:
现在,第一个对象会发生什么?好吧,如果你的程序中有没有其他变量指向它,它就没用了,因为你再也无法访问了它!在这种情况下,当解释器运行垃圾收集器时,对象将从内存中销毁/释放。垃圾收集器是一种算法,它将查找每个无法访问的对象并将其删除。垃圾收集器不会每次都运行,因此可能需要一段时间来销毁对象。
因此,在您的场景中,会发生什么:
答案 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)
需要注意的几点。
foo = Foo()
时,您要为变量foo
分配Foo
类型对象的实例。 Foo()
通过调用Foo
类的构造函数而不带任何参数来创建此实例。Foo()
都会创建一个新实例。因此,在代码中重复foo = Foo()
将创建Foo
类的多个实例,并将它们分配给变量foo
。 foo
变量指向的早期实例将不再具有引用,并且可以进行垃圾回收(假设您未同时为这些实例分配任何其他引用)。因此,您用来描述问题的词语
创建与现有名称相同的类的第二个实例 实例
其实不对。因为您没有创建“具有相同名称”的另一个实例。您正在创建另一个实例,并将其分配给“相同的变量”。
答案 4 :(得分:0)
Foo()
时,会创建一个新实例(类方法__new__
,实例方法__init__
将按顺序调用)__del__
)答案 5 :(得分:0)
您最终将新的Foo对象绑定到foo
,旧的Foo
对象将丢失引用。如果一个对象没有任何引用,那么它将在下一个垃圾收集中收集。
答案 6 :(得分:0)
第二个将覆盖第一个。 (它取代了模块的全局字典中的名称,其中存储了所有全局变量,函数和类。)
但是,您创建的foo = Foo()将继续使用创建时的原始实现,直到您创建一个新的foo = Foo()。