1.我们先来看一个例子:
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
def __str__(self):
return '{year}/{month}/{day}'.format(year=self.year,month=self.month,day=self.day)
class User:
def __init__(self,birthday):
self.birthday = birthday
def get_age(self):
#返回年龄=当前年份-出生年份(这里的birthday成为一个Date实例对象)
return 2019 - self.birthday.year
if __name__ == '__main__':
user = User(Date(1998,1,1))
print(user.birthday)
print(user.get_age())
结果:成功输出了出生日期及年龄
2.我们思考一个问题:如果我们的birthday属性不想被人看到怎么办?或者说birthday属性不能被人随意修改怎么办?
- 在java里面其实是可以利用private protect进行属性修饰的,这时将属性变为私有属性或可保护属性。
- 但是在python中,我们怎么做?在python中也有定义私有属性的方法,即在属性前加‘__’(双下划线)。
我们完善一下上面的例子:
class User:
def __init__(self,birthday):
#进行私有属性的封装
self.__birthday = birthday
#私有属性只能通过类里的方法进行访问
def get_age(self):
#返回年龄
return 2018 - self.__birthday.year
if __name__ == '__main__':
user = User(Date(1998,1,1))
#print(user.__birthday) 出错:显示没有这个属性
print(user.get_age())
可以看到,我们定义了__birthday这样的私有属性,在类外部,使用实例对象访问私有属性的时候就会出错,原因是它已经成为了私有的,外部自然无法访问。
注:我们只能在类内部通过方法来访问该私有属性
- 再来看一个有趣的现象:
user.__birthday = 30
print(user.__birthday)
运行结果: 咦这是为什么呢? 不是说在类外部已经没有__birthday这个属性了嘛?
其实,我们在这里的user.__birthday = 30,实际上是给当前的user对象又重新增加了一个属性__birthday,然后给它赋值并输出,和我们之前在类里定义的私有属性没有任何关系。
如果你直接这样输出:
print(user.__birthday)
则会报错:
3.私有机制:
在python中,一个属性定义为私有,实际上是给该属性做了一个变形,变成了‘_classname__attr’的形式
比如将‘birthday’变成了‘_User__birthday’,是一种‘伪私有’!!
你可以实践证明一下
if __name__ == '__main__':
user = User(Date(1998,1,1))
#print(user.__birthday) 出错:显示没有这个属性
#实际上python内部会对私有属性进行变形,变成_classname__attr形式,只是进行了变形,并不是真正意义上的安全,是一种“伪安全”
print(user._User__birthday)
print(user.get_age())
结果:
4.当存在继承时:
class Student(User):
def __init__(self,birthday):
self.__birthday = birthday
if __name__ == '__main__':
user = User(Date(1998,1,1))
student = Student(Date(1999,1,1))
print(student.__dict__)
print(user.__dict__)
结果:
可以看到,子类和父类的私有属性虽然是同一个,但形式却不同。