Python基础52:面向对象三大特性--封装

# **************************************************************************
# Python学习
# **************************************************************************
# ** 所属主题: 类
# ** 所属分层: 04 面向对象三大特性--封装
# ** 功能描述: 04 面向对象三大特性--封装
# ** 创 建 者: 陈红伟
# ** 创建日期: 2021/6/19 4:14 下午
# **************************************************************************
# ** 修改日期     修改人    修改内容
# ** 2021/6/19   陈红伟    新增学习内容代码
# **************************************************************************

# 一、封装介绍:
# 封装是面向对象三大特性最核心的一个特性
# 封装 <--> 整合

# 二、将封装的属性进行隐藏(私有)操作
# 如何隐藏:在属性前加__前缀,就会实现一个对外隐藏属性的效果
"""
特点:
    隐藏的操作并没有严格意义上的限制外部访问,仅仅只是一种语法意义上的变形
    这种隐藏对外是隐藏的,对内是不隐藏的

"""


class Foo:
    __x = 1  # _Foo__x = 1
    y = 2

    def __func(self):
        print('__func', self.__x)

    def f(self):
        print('f')
        self.__func()


# 如何把私有属性暴露给外面用
class Student:
    def __init__(self, name):
        self.__x = name

    def get_name(self):
        return self.__x

    def set_name(self, name):
        self.__x = name


stu1 = Student('a1')
print(stu1.get_name())  # a1
stu1.set_name('b2')
print(stu1.get_name())  # b2

"""
property: 将类中的方法 装饰(伪装)成一个属性
    装饰器是在不修改被装饰对象源代码以及调用方式的前提下为被装饰对象添加新功能的可调用对象
    property:其实也是一个装饰器,是类装饰器。
"""
# property是一个装饰器,是用来干什么的?

# property 案例一、隐藏方法,并开接口给外面用,让外面感知不到,更人性化。
""" 
成年人BMI数值:
过轻:低于18.5 
正常:18。5-23。9 
过重:24-27
肥胖:28-32
非常肥胖:大于32
体质指数(BMI)= 体重(kg) / 身高 ^ 2 (m)
Eg: 70Kg/(1.75*1.75) = 22.86 
"""


class People:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

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


p1 = People('chw', 60, 1.62)

print(p1.bmi())  # 86236854138088
print(p1.bmi)  # <bound method People.bmi of <__main__.People object at 0x7fcf12c083a0>>


# 但是考虑到BMI是人的一项数值属性,而非一个功能呢,在调用时,却需要调用一个方法,有点不符合常人逻辑
# 但是BMI对于同一个人来说,是可以随时变化的。所以还是要写在方法里
# 这时,为了两种情况都能得到解决,引入了property这个定义
# 在该功能上方加上@property。

class People_2:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

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


p2 = People_2('chenhongwei', 60, 1.62)
# 加了@property后,相当于声明该方法变成一个属性了,所以获取的时候,只能用获取属性的方法获取
# print(p2.bmi())  # TypeError: 'float' object is not callable
print(p2.bmi)  # 22.86236854138088


# property 案例二、 隐藏属性,并开接口给外面用,让外面感知不到,更人性化。
class Person_3:

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

    def get_name(self):
        return self.__name

    def set_name(self, name):
        if type(name) is not str:
            print('必须传入str类型:')
            return
        self.__name = name

    def del_name(self):
        print('不让删除')

    # @property
    # def name(self):
    #     return self.get_name()

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

    # name123 = property(name,get_name,set_name,del_name)  # TypeError: 'property' object is not callable,
    # 因为name已经是property对象了
    name123 = property(get_name, set_name, del_name)
    name12355 = property(del_name)


p4 = Person_3('cc')
print(p4.name)  # cc
print(
    p4.name123)  # cc
p4.name123 = "qwer"
print(p4.name123)  # qwer
p4.name12355  # 不让删除

# 案例三:案例二的第2中写法:
""" 
1、先将get_name,set_name,del_name,name这四个方法全部都改成name
2、  
    @property 还是和案例二中的一样
    @name.getter 等价于案例二中的get_name
    @name.setter 等价于案例二中的set_name
    @name.deleter 等价于案例二中的del_name
"""


class Person_4:

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

    @property  # name = property(name)
    def name444(self):  # obj.name
        return self.__name

    #
    # @name.getter
    # def name(self):  # obj.name
    #     return self.__name

    @name444.setter
    def name444(self, name):  # obj.name = 'CHW'
        if type(name) is not str:
            print('必须传入str类型:')
            return
        self.__name = name

    @name444.deleter  # del p5.name444  # 不让删除
    def name444(self):  # del obj.name
        print('不让删除')


p5 = Person_4(444)
print(p5.name444)  # 444
p5.name444 = 1  # 必须传入str类型:
p5.name444 = 'person4'
print(p5.name444)  # person4
del p5.name444  # 不让删除


# 思考:
# 之前学的subprocess也是这样做了 (subprocess.PIPE)
# import subprocess
# subprocess.PIPE
上一篇:属性---@property将方法伪装成属性


下一篇:06_防火墙相关操作