python学习14类(3)之封装

封装就是对对象的成员进行访问限制

封装的三个级别:公开 public

               受保护的 protected

               私有的 private

判别对象的位置:对象内部

                对象外部

                子类中

私有:

私有成员是最高级别的封装,只能在当前类或对象中访问

在成员前面添加两个下划线即可

class Person():

   #name是共有的成员

name=”liuyang”

   #__age是私有成员

   __age=23

p= Person()

print(p.name)

#__age是私有变量

print(p.__age) #报错:没有该属性!

Python的私有不是真私有,是一种称为name mangling的改名策略

name mangling技术:Person.__dict__

访问__age:p._Pearson__age

class Student(object):
    def __init__(self,name,age,sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

one = Student('wsx',18,'男')

#访问Student类的属性
print(one._Student__name)
print(one._Student__age)
print(one._Student__sex)
#修改__age属性
one._Student__age = 20
print(one._Student__age)

#print(one.__name)       # 报错,__name被私有化,封装起来了,所以外界无法访问,找不到该属性
#print(one.name)         # 报错,无该属性

上述封装方式,调用起来比较麻烦。

现在我将name,age,sex设置为私有属性,但是我又想让他们通过我指定的接口去访问或者修改我的属性,应该如何实现了?

class Student1(object):

    def __init__(self,name,age,sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

    def get_name(self):
        return self.__name  #这种方式是在类的内部,所以我们可以通过.__name的方式获得该属性

   
def set_name(self,name):
        if len(name) > 1 :
            self.__name = name
        else:
            print("name的长度必须要大于1个长度")

    def get_age(self):
        return self.__age

    def set_age(self, age):
        if age > 0 and age < 150:
            self.__age = age
        else:
            print("输入的年龄必须要大于0,小于150岁")

two = Student1('wsx',18,'男')

two.set_name('a')       # 通过自己设置接口,可以有效规避脏数据
print(two.get_name())       # 通过接口获取数据

two.set_age(20)         # 通过自己设置接口,可以有效规避脏数据
print(two.get_age())    # 通过接口获取数据

这样我们就自定义了自己属性的接口,它的好处在于:规避脏数据

问题:使用接口设置获取数据和使用点方法(one.name = 18 或者print(one.name))设置数据相比, 点方法使用更方便,我们有什么方法达到既能使用点方法,同时又能让点方法直接调用到我们的接口了?

class Student2(object):

    def __init__(self,name,age,sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self,name):
        if len(name) > 1 :
            self.__name = name
        else:
            print("name的长度必须要大于1个长度")

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        if age > 0 and age < 150:
            self.__age = age
        else:
            print("输入的年龄必须要大于0,小于150岁")

three = Student2('wsx',18,'男')

three.name = 'ly'
print(three.name)

three.age = 170
print(three.age)

@property:装饰器:负责把一个方法变成属性来调用

@属性名.setter:要把一个方法变成属性,只需要在get方法上加上@property,此时@property自身又创建了另一个装饰器,@属性名.setter,用于对属性值的赋值

posted @ 2020-02-25 16:39  程序员王不错  阅读(191)  评论(0)    收藏  举报