有__new__和属性的东西

时间:2013-05-03 16:22:19

标签: python

我尝试从一些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__?之间找到了一个讨论 根据评分最高的评论,如果一个人继承了strintunicodetuple这样的不可变类型,则应该只使用new。但我认为这是用于其他原因。更多我不明白为什么类cls应该有一个名字(为什么它应该有一些文件夹)以及为什么我可以调用

n= Node()
n.obs

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

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

1 个答案:

答案 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__时返回结果。