AdvancePython-python中的数据封装以及私有属性

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())



结果:
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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__)

结果:

可以看到,子类和父类的私有属性虽然是同一个,但形式却不同。

5.我们在实际中,并不推荐在外部去访问私有属性,不然定义私有也失去了它本身的意义,保护机制将毫无作用。

发布了16 篇原创文章 · 获赞 4 · 访问量 1782

猜你喜欢

转载自blog.csdn.net/qq_40509206/article/details/103507134
今日推荐