面向对象三大特征之封装及property

Ⅰ 面向对象三大特征之封装

【一】面向对象的三大特性

# 继承
# 封装
# 多态
# 其中之一就是封装:就是将数据与功能整合到一起
# 类里面定义数据和方法的时候,都会有一个需求,某些方法和属性是不能让别人看到的

【二】什么是封装

# 封装就是对具体的对象的一种抽象
# 意思就是将某部分功能和代码隐藏起来,在程序外边看不到,只能在程序内部使用

【三】为什么要封装?

# 封装最主要的原因就是为了保护隐私,将不想让用户看到的功能隐藏起来
class Student():
    ...

    # 初始化
    def __init__(self, name):
        self.name = name

    def change_name(self):
        self.name = 'nb_' + self.name

stu1 = Student(name='silence')
stu1.change_name()
print(stu1.name)  # nb_silence

【四】封装的方法

比如
# 你自己的身体其实也有封装的部分
# 膀胱,你自己有并且自己能用但是别人看不到也也用不了
# 在变量名前面加 __

【五】封装隐藏属性

【1】数据属性

class Person:
    # 在变量名前面加 __
    SCHOOL_NAME = '清华'

    def __init__(self, name):
        self.name = name


student = Person(name='silence')
print(student.name)
# 查看类的民称空间
# {'SCHOOL_NAME': '清华'}
print(Person.__dict__)
print(student.SCHOOL_NAME)
class Person:
    # 并没有真正的隐藏,只是自动转换成了特定的语法
    # 在变量名前面加 __ : 在类初始化对象的时候会对当前变量名进行变形 变形成 _Person__变量名
    # 封装功能只在类定义阶段才生效
    __SCHOOL_NAME = '清华'

    def __init__(self, name):
        self.name = name


student = Person(name='silence')
print(student.name)
# 查看类的民称空间
# {'_Person__SCHOOL_NAME': '清华',}
print(Person.__dict__)
print(student.__SCHOOL_NAME) # 找不到 
print(student._Person__SCHOOL_NAME) # 能找到   __SCHOOL_NAME变成_Person__SCHOOL_NAME

【2】函数属性

class Person:
    # 在变量名前面加 __ : 在类初始化对象的时候会对当前变量名进行变形 变形成 _Person__变量名
    __SCHOOL_NAME = '清华'

    def __init__(self, name):
        self.name = name

    # 函数属性 : 在类初始化对象的时候会对当前变量名进行变形 变形成 _Person__变量名
    def __change_name(self):
        self.name = 'nb_' + self.name


student = Person(name='silence')

print(student.name)
# 查看类的民称空间
# {'_Person__SCHOOL_NAME': '清华','_Person__change_name': <function Person.__change_name at 0x000001D09384C0D0>,}
print(Person.__dict__)

print(student.__change_name())

# 当我们在对象中调用相关属性的时候会发现,找不到

【3】补充

# 变形只发生在类初始化得到对象的时候
# 并且变形只会发生一次
print(student.name)
print(Person.__dict__) 
student.__SCHOOL_NAME = '北大'
print(student._Person__SCHOOL_NAME)
print(Person.__dict__)
print(student.__dict__)
print(student.__SCHOOL_NAME)

【六】什么是开放接口

# 定义属性,并且隐藏属性或者方法是为了不让用户看到对应的功能和逻辑
# 但是我要给用户提供修改的接口
class Teacher:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def set_info(self, name, age):
        # 修改名字和修改年龄之前要校验当前的格式是否正确
        # 名字前面必须 + lj_
        if not name.startswith('lj_'):
            raise ValueError("名字必须是 lj 前缀")
        # 年龄必须是数字且大于 0
        if not age.isdigit():
            raise ValueError("年龄必须是数字")
        if int(age) < 0:
            raise ValueError("年龄超出常人,建议回炉重造!")
        self.__name = name
        self.__age = age

    # 做一个接口查看当前讲师的个人信息
    def tell_info(self):
        print(f"当前讲师是 :>>>> {self.__name} 年龄是 :>>>> {self.__age}")


teacher = Teacher(name="silence", age=18)
# teacher.tell_info()
#修改当前讲师的姓名和年龄
teacher.set_info(name='lj_happy',age='15')
teacher.tell_info()

【七】小结

# 隐藏属性和开放接口本质上都是为了明确的区分内外,在类内部可以随意修改我的代码,但是在类外部不允许使用者修改代码
# 类外部只需要拿到一个接口,只要接口名不变,里面的逻辑就可以随意实现
# 接口只要基础不变,代码就可以任意修改

【八】拓展:property

【1】什么是property

# 是一种特殊的属性,将函数的返回值作为数据属性返回
class Student:
    def __init__(self, name):
        self.name = name

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

student = Student(name='silence')
print(student.name)
print(student.vip_name)
# print(student.vip_name())

【2】BMI例子

# BMI : 衡量一个人的体重和身高对健康影响的指标
# 指标
#   ○ 过轻:低于18.5
#   ○ 正常:18.5-23.9
#   ○ 过重:24-27
#   ○ 肥胖:28-32
#   ○ 非常肥胖, 高于32
# 计算公式
#   ○ 体质指数(BMI)=体重(kg)÷身高^2(m)
#   ○ EX:70kg÷(1.75×1.75)=22.86
class BMI:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

    @property
    def bmi(self):
        return self.weight / (self.height ** 2)


dream = BMI(name='silence', weight=70, height=1.7)

print(dream.bmi)

【3】为什么要使用property

# 【1】在所有编程语言中都有三种封装方式
# public : 公开
# protected : 对外不公开但是对美公开
# private : 对谁都不公开
# 【2】上面三种封装方式就用到了我们的类中

class PersonOne(object):
    def __init__(self, name):
        self.name = name


person_one = PersonOne(name='silence')
# 查看
print(person_one.name) # silence
# 修改
person_one.name = '666'
print(person_one.name) # 666
# 删除
del person_one.name
print(person_one.name) # 'PersonOne' object has no attribute 'name'
class Person(object):
    def __init__(self, name):
        self.__name = name

    # 给当前函数名添加装饰器 property
    # 将当前 函数名作为一个数据属性返回
    @property
    def vip_name(self):
        # 返回值可以是字符串也可以是其他内容
        return self.__name

    # 修改 和 property 包装的函数名一致 并且加 .setter
    # 修改当前变量民的时候会触发
    @vip_name.setter
    def vip_name(self, value):
        print(value)
        self.__name = value
    
    # 删除  和 property 包装的函数名一致 并且加 .deleter
    # 删除当前变量民的时候会触发
    @vip_name.deleter
    def vip_name(self):
        del self.__name


person = Person(name='silence')
# 查看
print(person.vip_name)
# <bound method Person.name of <__main__.Person object at 0x000001EE86C22340>>

# 修改
person.vip_name = 'happy'
print(person.vip_name)

# 删除
del person.vip_name
print(person.vip_name)
class Person(object):
    def __init__(self, name):
        self.__name = name

    # 给当前函数名添加装饰器 property
    # 将当前 函数名作为一个数据属性返回
    def get_vip_name(self):
        # 返回值可以是字符串也可以是其他内容
        return self.__name

    # 修改 和 property 包装的函数名一致 并且加 .setter
    # 修改当前变量民的时候会触发
    def set_vip_name(self, value):
        print(value)
        self.__name = value

    # 删除  和 property 包装的函数名一致 并且加 .deleter
    # 删除当前变量民的时候会触发
    def del_vip_name(self):
        del self.__name

    vip_name = property(get_vip_name, set_vip_name, del_vip_name)

person = Person(name='silence')
# 查看
print(person.vip_name)
# <bound method Person.name of <__main__.Person object at 0x000001EE86C22340>>

# 修改
person.vip_name = 'happy'
print(person.vip_name)

# 删除
del person.vip_name
print(person.vip_name)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值