4

我有一个 python 类层次结构,我想在运行时扩展它。此外,这个层次结构中的每个类都有一个静态属性“dict”,我想在每个子类中覆盖它。简单地说,它看起来像这样:

'dict' 是受保护的(公共但带有前导下划线)成员

class A(object):
    _dict = {}

    @classmethod
    def getdict(cls):
        return cls._dict

    @classmethod
    def setval(cls, name, val):
        cls._dict[name] = val

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '_dict' : {} })

B = A.addchild('B')
A.setval(1, 5)

print A.getdict()
# prints: {1: 5}
# like expected

print B.getdict()
# prints: {}
# like expected

这就像预期的那样工作。现在的问题是:如果我将属性声明为私有,为什么它不再起作用:

现在,“dict”成为私人成员也是如此

class C(object):
    __dict = {}

    @classmethod
    def getdict(cls):
        return cls.__dict

    @classmethod
    def setval(cls, name, val):
        cls.__dict[name] = val

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '__dict' : {} })

D = C.addchild('D')
C.setval(1, 5)

print C.getdict()
# prints: {1: 5}
# like expected

print D.getdict()
# prints: {1: 5}
# why!?

突然D, , 的子类C在 'dict' 中的值与其超类相同!?

谁能这么好心向我解释一下,这是什么原因?提前致谢!

4

3 回答 3

3

phild,如您所知,当您在属性名称前加上双下划线__时,python 解释器会自动将属性名称从(修改)更改为__attributeto _CLS__attribute,其中 CLS 是类名。

然而,当你说

return type(name, (cls, ), { '__dict' : {} })

字典中的键{ '__dict' : {} }不会被破坏。__dict保持原样。

因此 D 以D._C__dictand结束D.__dict

(Pdb) dir(D)
['_C__dict', '__class__', '__delattr__', '__dict', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'addchild', 'getdict', 'setval']

D._C__dict指C的类属性。所以当你跑

C.setval(1, 5)

你也在D._C__dict改变C._C__dict。他们是一样的。

于 2009-11-24T19:12:33.517 回答
2

这是有关“私有”属性的文档中的一章。我评论了你的类定义以使其更清楚:

class C(object):
    __dict = {} # This creates C.__dict__['_C__dict']

    @classmethod
    def getdict(cls):
        return cls.__dict # Uses cls.__dict__['_C__dict'] 

    @classmethod
    def setval(cls, name, val):
        cls.__dict[name] = val # Uses cls.__dict__['_C__dict'] 

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '__dict' : {} }) # Creates child.__dict__['__dict']

即所有孩子都有自己的__dict属性,但只使用基类中的一个。

于 2009-11-24T18:57:21.533 回答
1

“受保护”和“私有”的 Java 或 C++ 概念不适用。命名约定 Python 做了一点,但不是你想象的那样。

__name进行一些名称修改,由于名称被遮蔽,因此难以访问。

您的_dict__dict只是简单地由所有类实例共享的类级属性。

于 2009-11-24T18:54:07.627 回答