使用双下划线时,名称修饰发生在什么时候?

3
class Test():

    def __init__(self):
        self.__test = "cats"
        print(self.__test)

    def __example(self):
        print("Hello World")

x = Test()
print(x.__dict__)

通过我上面编写的代码,打印语句将显示要访问变量test,我需要编写_Test__test,但是如上所示,如果我在__init__方法中直接调用它,我可以打印变量。 所以我的问题是,如果我可以通过名称直接声明后直接访问它,即self.__test,那么它何时会被破坏?


1
似乎很简单 - 每次在类内部尝试访问名称时,它都会在查找之前被混淆。这是在创建它以及使用它时发生的。 - Mark Ransom
为什么在第5行键入print(self.__test)时它没有被篡改? - J.doe
2个回答

1

通过.__访问的属性在类体中的任何位置都会被修改(但内部类声明将首先获得它)。

把它看作是语法糖。

Test类体的上下文中,self.__test是指向缠结名称self._Test__test的别名;在上下文中,它们意味着完全相同的事情

演示将使这一点更清晰。 首先,一些帮助器类。

class PrintAttrAccess:
    def __getattr__(self, name):
        print(name)

class Empty: pass

现在进行演示:
class Test:
    print('IN TEST BODY')
    (lambda: PrintAttrAccess().__in_lambda)()  # Anywhere in the class body works.
    classfoo = Empty()
    classfoo.__foo = 'foo'
    print("Same thing?", classfoo.__foo is classfoo._Test__foo)
    print("vars() of classfoo:", vars(classfoo))

    class Inner:
        print('IN INNER')
        PrintAccess().__inner

    def __init__(self):
        print('IN INIT')
        print("Who am I?", self)
        self.__test = "cats"
        print(self._Test__test)  # It's ALREADY MANGLED!
        # This line means exactly the same as the one above.
        print(self.__test)
        localfoo = Empty()
        localfoo.__spam = 'spam' # "self" isn't special.
        print("vars() of localfoo:", vars(localfoo))


def outside_method(self):
    print('OUTSIDE BODY')
    print("Who am I?", self)
    self.__test = "dogs"
    print(self._Test__test)
    print(self.__test)  # Sugar doesn't apply outside of class body.

Test.outside_method = outside_method  # Add a new method to Test class.

Test().outside_method()  # init and call as method.

输出结果为:

IN TEST BODY
_Test__in_lambda
Same thing? True
vars() of classfoo: {'_Test__foo': 'foo'}
IN INNER
_Inner__inner
IN INIT
Who am I? <__main__.Test object at 0x000001CCF3048978>
cats
cats
vars() of localfoo: {'_Test__spam': 'spam'}
OUTSIDE BODY
Who am I? <__main__.Test object at 0x000001CCF3048978>
cats
dogs

0
如果我可以通过其名称直接访问它,即self.__test在什么时候会变成混淆的?
当你从类外部引用它时,它就会变成混淆的。
你的第5行print(self.__test)不是混淆的,因为你是从类内部引用它。只有当你从类外部引用它时,它才会被混淆。因此,你应该调用
print(x._Test__test)

请注意,您也可以在类内使用self._Test__test
class Test():
    def __init__(self):
        self.__test = "cats"

    def get(self):
        return self._Test__test

x = Test()
print(x.get())                      ##  cats

我认为这篇文章解释得很清楚:Python中下划线的含义


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接