为什么“名字”是这样的? __setattr__ 的参数包括该类,但 __getattr__ 不包括该类?

发布于 2024-08-23 17:44:08 字数 571 浏览 7 评论 0原文

以下代码:

class MyClass():
    def test(self):
        self.__x = 0

    def __setattr__(self, name, value):
        print name

    def __getattr__(self, name):
        print name
        raise AttributeError(name)

x = MyClass()
x.test()
x.__y

输出:

_MyClass__x
__y
Traceback (most recent call last):
...
AttributeError: __y

文档完全没有帮助,说明“名称”是“属性的名称”,但由于某种原因,它会有所不同,具体取决于您是设置它还是获取它。

我想知道的是:

  • 我在这里做的是根本错误的事情吗?
  • 在第一种情况下如何获取 x 而不是 _MyClass__x

The following code:

class MyClass():
    def test(self):
        self.__x = 0

    def __setattr__(self, name, value):
        print name

    def __getattr__(self, name):
        print name
        raise AttributeError(name)

x = MyClass()
x.test()
x.__y

Outputs:

_MyClass__x
__y
Traceback (most recent call last):
...
AttributeError: __y

The documentation is utterly unhelpful stating the "name" is the "name of the attribute", yet for some reason it's different depending on whether you are setting it or getting it.

What I want to know is:

  • Am I doing something fundamentally wrong here?
  • How do I get x in the first case instead of _MyClass__x?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

习ぎ惯性依靠 2024-08-30 17:44:08

双下划线调用名称修改。如果您不需要名称修改,请不要使用双 undescore

对象名称之前的单下划线和双下划线的含义是什么?

来自 Python 文档

9.6。私有变量

Python 中不存在只能从对象内部访问的“私有”实例变量。然而,大多数 Python 代码都遵循一个约定:以下划线前缀的名称(例如 _spam)应被视为 API 的非公共部分(无论是函数,方法或数据成员)。它应被视为实施细节,如有更改,恕不另行通知。

由于类私有成员有一个有效的用例(即避免名称与子类定义的名称发生名称冲突),因此对这种称为名称修饰的机制的支持有限。任何 __spam 形式的标识符(至少两个前导下划线,最多一个尾随下划线)在文本上都会替换为 _classname__spam,其中 classname 是带有前导下划线的当前类名称( s) 剥离。这种修改的完成与标识符的语法位置无关,只要它出现在类的定义中即可。

请注意,修改规则主要是为了避免意外而设计的;仍然可以访问或修改被视为私有的变量。这甚至在特殊情况下很有用,例如在调试器中。

请注意,传递给 execeval()execfile() 的代码不会将调用类的类名视为当前班级;这类似于全局语句的效果,其效果同样仅限于字节编译在一起的代码。同样的限制适用于 getattr()setattr()delattr() 以及引用 __dict__ 时> 直接。

The double underscore invokes name mangling. If you don't need name mangling, don't use double undescore

What is the meaning of a single- and a double-underscore before an object name?

From the Python docs

9.6. Private Variables

“Private” instance variables that cannot be accessed except from inside an object, don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.

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. 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 that the mangling rules are designed mostly to avoid accidents; it still is possible to access or modify a variable that is considered private. This can even be useful in special circumstances, such as in the debugger.

Notice that code passed to exec, eval() or execfile() does not consider the classname of the invoking class to be the current class; this is similar to the effect of the global statement, the effect of which is likewise restricted to code that is byte-compiled together. The same restriction applies to getattr(), setattr() and delattr(), as well as when referencing __dict__ directly.

痴意少年 2024-08-30 17:44:08

我不确定为什么会发生这种情况,但如果您使用 _x 而不是 __x ,它会按您的预期工作。

I'm not sure exactly why this occurs, but if you use _x rather than __x it works as you would expect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文