Python中的私有成员

下边代码中在使用构造方法中定义了self.__age = 1,这个构造方法在创建对象时给对象进行初始化。
(1)既然使用了self.__age说明是利用self给对象赋值了__ageself的含义是什么?是不是代表为对象添加属性?
(2)这里可不可以理解成用self.__age = 1对象添加了一个对象的私有属性?而不是类的私有属性?
(3)为何对象无法直接访问__age,那么双下划线对属性的定义是不是绝对的?就是只要是双下划线就是类的私有属性,不管它在什么地方被定义都是类的私有属性。


class Person:
    def __init__(self, name):
        self.name = name  # 名称
        self.__age = 1  # 年龄,私有属性,默认1岁

    def set_age(self, new_age):
        if 0 < new_age <= 120:  # 判断年龄是否合法
            self.__age = new_age

    # 设置获取私有属性的方法
    def get_age(self):
        return self.__age


chinese = Person('小明')
print(chinese.__age)

(1)self 泛指对象本身,比如,小明、小刚都是Person对象,小明和小刚都有一个默认的成员变量self,用来表示“自己”。小明的self是代指小明,同理,小刚的self就代指小刚。即:
self是Person对象的一个隐含的成员变量,用来泛指对象本身。
age是Person对象的一个显示定义的成员变量。
self.__age说明,Person类中定义了一个私有成员变量age,self.__age=1就是把所有Peron对象的age变量都默认赋值为1。
(2)self.__age 在每个Person对象中都有,并且,所有Person对象的_age变量的值都初始化为1。self.__age=1不能说是某个对象的属性,而是所有Person对象都具有的属性,你可以理解为类的属性。
(3)在python中,实例变量名前如果以双下划线开头,就会变成私有变量,只有内部可以访问,外部不能访问。也就是如果声明如下:

p = Penson();
p.age=12  # 这里是错误的,因为age是Person类的私有成员变量,不能在类的外部被直接访问!!

必须通过定义函数来访问age变量(这就是类的封装性),也就是在Peron类中定义一个如下函数:

def set_age(self,a): 
    self.__age = a

然后调用 p.set_age(12) 来设置age的指。

参考GPT和自己的思路:首先,self是一个变量,它代表对象本身,在Python中一般将它作为实例方法的第一个参数。通过self我们可以访问实例自身的属性和方法,也可以在方法中给实例添加属性和方法。

其次,双下划线并不是绝对的私有属性,它是一种命名规范,Python会将以双下划线开头的属性名进行名称重整,变成_类名__属性名的形式。虽然这样做可以避免子类意外覆盖父类属性,但并不能真正禁止访问私有属性,因为我们仍然可以通过_类名__属性名的方式来访问它。所以,双下划线只是一种名称修饰,而不是绝对的访问限制。