简体   繁体   English

来自Python 3中超类构造函数的属性是否已创建或可访问?

[英]Attributes from superclass constructor in Python 3 on created or accessible?

I am getting this traceback: 我得到此回溯:

Traceback (most recent call last):
File "/home/amentis/Dropbox/Rexi/index.py", line 21, in application
ui = Console.Console()
File "/home/amentis/Dropbox/Rexi/UI/Console.py", line 9, in __init__
self.__window = Window.Window(self, 'consoleWindow')
File "/home/amentis/Dropbox/Rexi/RxAPI/RxGUI/Window.py", line 16, in __init__
self.__parent.add_child(self)
AttributeError: 'Window' object has no attribute '_Window__parent'

Here is a portion of the Console class: 这是Console类的一部分:

class Console(Screen.Screen):

    def __init__(self):
        super().__init__("REXI Console")
        self.__window = Window.Window(self, 'consoleWindow')

Of the Window class: Window类的:

class Window(RxGUIObject.RxGUIObject):
    def __init__(self, parent, name):
        RxGUIObject.RxGUIObject.__init__(self, name, parent)
        self.__body = ""
        self.__javascript = ""
        self.__css = ""
        self.__parent.add_child(self)

and the RxGUIObject: 和RxGUIObject:

class RxGUIObject(RxObject.RxObject):
    def __init__(self, name, parent):
        RxObject.RxObject.__init__(self, name)
        self.__parent = parent
        self.__children = list

Is Window.__parent not created or not existent and why? Window.__parent未创建或不存在,为什么?

You just stumbled on python's name mangling . 您刚刚偶然发现python的名称修改 Every attribute that starts with a double underscore and ends with at most one trailing underscore, like your __parent , is renamed to _ClassName__attributename . 以双下划线开始,并在最多一个结尾下划线结束,喜欢你的每个属性__parent ,被重命名为_ClassName__attributename

>>> class A(object):
...     def __init__(self):
...             self.__a = 1
... 
>>> class B(A):
...     pass
... 
>>> b = B()
>>> b.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'B' object has no attribute '__a'
>>> b._A__a
1

Why is this done? 为什么要这样做? In order to prevent attributes clashes when subclassing. 为了防止子类化时属性冲突。 In particular the documentation states: 特别是文档指出:

Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses ), there is limited support for such a mechanism, called name mangling. 由于存在类专用成员的有效用例(即避免名称与子类定义的名称发生名称冲突 ),因此对这种称为名称修改的机制的支持有限。 Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam , where classname is the current class name with leading underscore(s) stripped. 形式为__spam任何标识符(至少两个前导下划线,至多一个下划线)在文本上被_classname__spam替换,其中classname是当前的类名,其中前导下划线被去除。 This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class. 只要不存在标识符的语法位置,就可以进行这种改写,只要它出现在类的定义内即可。

Note: name mangling does not mean an attribute is private. 注:名称重整并不意味着一个属性是私有的。 If you want to make an attribute "private" the convention is to use one underscore: eg _parent . 如果你想使一个属性为“私人”的约定是使用一个下划线:如_parent If you know that your class will be subclassed (often), then it may be a good idea to use name mangling to avoid name clashes. 如果您知道您的类将被子类化(通常),那么使用名称修饰以避免名称冲突可能是一个好主意。

Refer to Python name mangling: When in doubt, do what? 请参阅Python名称修饰:如果有疑问,该怎么办? to decide whether to use it or not, however in general you should not use it. 以决定是否使用与否,但一般而言,您应使用它。

Also note that, if subclasses must have access to __parent then you definitely should not use name mangling, since its very aim is to avoid subclasses accessing the attribute. 还要注意的是,如果子类必须能够访问__parent那么你绝对 应该使用名字改编,因为它非常的目的是为了避免子类访问属性。 In such cases simply use a public attribute and document it . 在这种情况下,只需使用公共属性并将其记录下来 In alternative you can use a private attribute with name mangling and a property/some method to access it as hidden internal state, however for simple cases this is an overkill. 或者,您可以使用带有名称修饰的私有属性和属性/某种方法以隐藏的内部状态访问它,但是对于简单的情况,这是一个过大的选择。

__parent is private property of RxGUIObject __parent是私有财产RxGUIObject

__double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes FooBar _boo; see below). __double_leading_underscore:命名类属性时,调用名称修饰(在类FooBar中,__boo变为FooBar _boo;请参见下文)。

because of this your __parent property of RxGUIObject will be considered as _RxGUIObject__parent 因为这是你的__parent财产RxGUIObject将被视为_RxGUIObject__parent

To avoid this please define it explicetely 为了避免这种情况,请明确定义

def __init__(self, parent, name):
    RxGUIObject.RxGUIObject.__init__(self, name, parent)
    self.__body = ""
    self.__javascript = ""
    self.__css = ""
    self.__parent = parent
    self.__parent.add_child(self)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM