__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,unicodetuple。但我认为这是因为其他原因。进一步,我不明白为什么类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__时返回结果。

+0

谢谢你的回复。 所以使用'__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

+0

@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

+0

@Adam:Python类对象通常(在Python 3中,* always *),从'object'继承,而不是'cls'。 'cls'只是这个方法的本地名称。 – 2013-05-03 17:23:50