我尝试从一些OpenSource GitHub项目中了解以下代码。有一个没有__init__
但使用__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)
我在__init__
方法和__new__
方法Python's use of __new__ and __init__?之间找到了一个讨论
根据评分最高的评论,如果一个人继承了str
,int
,unicode
或tuple
这样的不可变类型,则应该只使用new。但我认为这是用于其他原因。更多我不明白为什么类cls
应该有一个名字(为什么它应该有一些文件夹)以及为什么我可以调用
n= Node()
n.obs
像函数obs一样是属性函数,但它实际上不是..
我很困惑。如果你没有,我等不及你的回应。
答案 0 :(得分:3)
此类使用__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))
。 property
对象调用包装函数,并在调用__get__
时返回结果。