下边代码中在使用构造方法中定义了self.__age = 1
,这个构造方法在创建对象时给对象进行初始化。
(1)既然使用了self.__age
说明是利用self
给对象赋值了__age
,self
的含义是什么?是不是代表为对象添加属性?
(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会将以双下划线开头的属性名进行名称重整,变成_类名__属性名
的形式。虽然这样做可以避免子类意外覆盖父类属性,但并不能真正禁止访问私有属性,因为我们仍然可以通过_类名__属性名
的方式来访问它。所以,双下划线只是一种名称修饰,而不是绝对的访问限制。