python中getattr(self, '__a')和self.__a有什么区别?

11 投票
1 回答
2418 浏览
提问于 2025-04-18 04:19

我之前以为它们是一样的,直到我运行了这段代码:

class B(object):
    def show(self):
        self.__a = "test"
        print "B"

    def this_b(self):
        print "this_b"
        print self.__a
        print getattr(self, '__a') #exception


class C(B):
    def show(self):
        print "C"
        # B.show(self)
        super(C, self).show()


    def call(self):
        print "call"
        self.show()
        self.this_b()
        # print self.__a

C().call()

这段代码引发了一个错误,提示 AttributeError: 'C' object has no attribute '__a',但是为什么会这样呢?

1 个回答

12

这是因为有一个叫做 私有名称改名的规则。

私有名称改名:当一个在类定义中出现的名字以两个或更多的下划线开头,并且不以两个或更多的下划线结尾时,这个名字就被认为是该类的私有名称。私有名称在生成代码之前会被转换成一个更长的形式。这个转换会把类名(去掉前面的下划线,并在前面加一个下划线)放到名字前面。例如,在一个叫做 Ham 的类中出现的 __spam 会被转换成 _Ham__spam。这个转换和名字使用的上下文没有关系。如果转换后的名字非常长(超过255个字符),可能会被截断。如果类名只有下划线,那么就不会进行任何转换。

当你执行

self.__a

时,私有名称改名会自动处理。但是当你执行

print getattr(self, '__a')

时,你需要手动处理,就像这样

print getattr(self, '_B__a')
# test

撰写回答