__new__和属性
我尝试从某些OpenSource GitHub项目中了解以下代码。有一个课程没有__init__
,但有一个__new__
方法。该代码给出:__new__和属性
class Node(object):
#pylint: disable=W0404
#Singleton-Pattern
_instances = dict()
def __new__(cls, name=None):
""" Instanciates a node from a file, and (name=None) creates a new node
Caution: Filenames are always given relative to the root-dir
When no name is given, a new node is created. """
if(name!=None and cls._instances.has_key(name)):
return(cls._instances[name])
if(name==None): # a new node, lets find a name
for i in itertools.count(0):
name = "node%.4d"%i
if(cls._instances.has_key(name)): continue# new nodes might not been saved, yet
if(path.exists("./nodes/"+name)): continue
break
self = object.__new__(cls)
cls._instances[name] = self
#actuall init-code
from ZIBMolPy.pool import Pool #avoids circular imports
self._pool = Pool() #Pool is a singleton
self._name = name
self._tmp = Store() #for thing that need to be stored temporarly
self._obs = Store()
self.parent = None
if(path.exists(self.dir)):
self.reload()
#self.pool.append(self) #register with pool
return(self)
#---------------------------------------------------------------------------
@property
def obs(self):
return(self._obs)
我发现一个讨论beween的__init__
方法和Python's use of __new__ and __init__? 的__new__
方法根据收视率最高的评论,如果一个人继承一个不可变的类型像str
一个只应使用新的, int
,unicode
或tuple
。但我认为这是因为其他原因。进一步,我不明白为什么类cls
应该有一个名字(以及为什么它应该有一些文件夹任何待办事项),为什么我可以叫
n= Node()
n.obs
的功能等OBS将是一个性质的功能,但它其实不是..
我很困惑。如果你不是,我不能等待你的回应。
本课使用__new__
来实现单例模式。
__new__
产生一个类的新实例,但在这种情况下,如果之前使用了相同的名称,它将返回一个现有的实例。你不能用__init__
来做到这一点,因为在已经创建实例之后,这被称为。请注意,当cls._instances.has_key(name)
为False
时,将调用self = object.__new__(cls)
来创建该类的新实例,然后将其初始化并返回。
为什么类在./nodes/
目录中检查现有路径不清楚,这是一个特定于应用程序的检查,如果没有进一步的上下文,不容易再暴露。
@property
修饰器用python descriptor代替函数。从类中查找属性时,如果属性有一个属性,则Python将其称为__get__
方法。 Python表达式n.obs
被Python翻译为type(n).obs.__get__(n, type(n))
。 A property
对象调用封装的函数,并在调用__get__
时返回结果。
谢谢你的回复。 所以使用'__new__'的唯一原因是因为有时候我想要一个已经被创建好的对象?这只是在'if(name!= None和cls._instances.has_key(name))'的情况下。我应该如何用name!= None调用'__new__'函数?我的意思是超时我创建了一个节点对象,我称之为'node = Node()',然后默认'name = None'。我还认为cls是一个静态的全局类对象。因此,如果我向全局类cls添加一个名称,因为每个对象都包含该名称,因为每个对象都是cls的子类 - 是否正确? – Adam 2013-05-03 17:18:58
@Adam:参见['__new__'](http://docs.python.org/2/reference/datamodel.html#object.__new__)文档; 'cls'是对'__new__'方法传入的类对象的引用(就像'self'传入引用当前实例的方法一样)。 Node()为你创建一个新名字,如果你不通过('name = None'),理论上这个项目可以在需要的时候传入一个明确的'name'。在这种情况下,'cls'会引用'Node'类或'Node'的任何子类。 – 2013-05-03 17:22:59
@Adam:Python类对象通常(在Python 3中,* always *),从'object'继承,而不是'cls'。 'cls'只是这个方法的本地名称。 – 2013-05-03 17:23:50