1

我尝试从一些 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)

我在Python 使用 __new__ 和 __init____init__的方法和方法之间找到了一个讨论? 根据评价最高的评论,只有在继承不可变类型(如 、 或 )时才应使用new 。但我认为这里是出于其他原因使用它。此外,我不明白为什么该类应该有一个名称(以及为什么它应该与某些文件夹有关)以及为什么我可以调用__new__strintunicodetuplecls

n= Node()
n.obs

就像函数 obs 将是一个属性函数,但它实际上不是..

我很困惑。如果你不是,我等不及你的回应。

4

1 回答 1

3

此类__new__用于实现单例模式。

__new__为类生成新实例,但在这种情况下,如果之前使用了相同的名称,它将返回现有实例。您不能使用 执行此操作__init__,因为它是在创建实例后调用的。请注意,何时调用cls._instances.has_key(name)is来创建类的新实例,然后将其初始化并返回。Falseself = object.__new__(cls)

为什么类检查./nodes/目录中的现有路径尚不清楚,这是一个特定于应用程序的检查,如果没有进一步的上下文,就不能轻易地进一步公开。

装饰器将@property函数替换为python 描述符。当从一个类中查找一个属性时,__get__如果该属性有一个,Python 将调用它的方法。Python 表达式由 Pythonn.obs翻译成type(n).obs.__get__(n, type(n))property对象调用包装函数并在调用时返回结果__get__

于 2013-05-03T16:28:52.403 回答