zoukankan      html  css  js  c++  java
  • python之封装

    python之封装

    一、什么是封装?

    • 面向对象编程有三大特性:封装、继承、多态,其中最重要的一个特性就是封装。

    • 封装:指的就是把数据与功能都整合到一起

    • 分两步实现:隐藏与开放接口

    二 隐藏属性

    ​ Python的Class机制采用双下划线开头的方式将属性隐藏起来(设置成私有的),但其实这仅仅只是一种变形操作,类中所有双下滑线开头的属性都会在类定义阶段、检测语法时自动变成“_类名__属性名”的形式:

    • 定义阶段就发生了变形操作

    代码实现:

    class Foo:
        __N = 1
        def __init__(self,x,y):
            self.x = x
            self.__y = y
        def __f1(self):
            print('我是 f1')
        def f2(self):
            print(self.__N,self.__y)
    
    print(Foo.__N)  #变量N前面加了 '__',N被隐藏了起来,这是是调用不到N的咯
    print(Foo.__f1) #函数也一样哦
    '''
    此处列出自定义的变量、函数
    __N  --->_Foo__N
    __f1 ---> _Foo__f1
    '''
    # #那要怎么调用?
    # print(Foo._Foo__N)  #可是这样没意义,因为我们实际上要隐藏起来
    

    这种变形需要注意的问题是:

    ​ 1、在类外部无法直接访问双下滑线开头的属性,但知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如Foo._A__N,所以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。

    print(Foo.__N)  #变量N前面加了 '__',N被隐藏了起来,这是是调用不到N的咯
    print(Foo.__f1) #函数也一样哦
    

    ​ 2、在类内部是可以直接访问双下滑线开头的属性的,比如self.__f1(),因为在类定义阶段类内部双下滑线开头的属性统一发生了变形。

        def f2(self):
        print(self.__N,self.__y)   #实际上执行的是print(Foo._Foo__N,Foo._Foo__y)
        
    obj = Foo(1,2)
    obj.f2()
    

    ​ 3、变形操作只在类定义阶段发生一次,在类定义之后的赋值操作,不会变形。

    三、封装的真正意义

    首先:定义属性就是为了使用,所以隐藏并不是目的

    3.1 隐藏数据属性

    • 实际上我们要做的是把属性隐藏起来然后开个接口,让外面进行访问
    • 接口:tell_info、set_info方法。类似于JAVA的get、set

    代码:(版本一)

    class Studio:
        # 将名字和年纪都隐藏起来
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        # 对外提供访问学生信息的接口
        def tell_info(self):
            print(F'我是{self.__name},今年{self.__age}岁')
    
        # 对外提供改变学生信息的接口
        def set_info(self,name,age):
            self.__name = name
            self.__age = age
    
    stu1 = Studio('tom',18)
    stu1.tell_info()
    
    

    代码:(版本二)

    class Studio:
        # 将名字和年纪都隐藏起来
        def __init__(self,name,age):
            #这2行直接使用下面的函数传入,修改值。改一次调用一次!
            #self.__name = name
            #self.__age = age
            self.set_info(name, age)
    
        # 对外提供访问学生信息的接口
        def tell_info(self):
            print(F'我是{self.__name},今年{self.__age}岁')
    
        # 对外提供改变学生信息的接口
        def set_info(self,name,age):
            self.__name = name
            self.__age = age
    
    stu1 = Studio('tom',18)
    stu1.tell_info()
    

    代码:(版本三)

    class Studio:
        # 将名字和年纪都隐藏起来
        def __init__(self,name,age):
            self.set_info(name, age)
    
        # 对外提供访问学生信息的接口
        def tell_info(self):
            print(F'我是{self.__name},今年{self.__age}岁')
    
        # 对外提供改变学生信息的接口,且加个判断
        def set_info(self,name,age):
            if not isinstance(name, str):
                raise TypeError('姓名必须是字符串类型')
            if not isinstance(age, int):
                raise TypeError('年龄必须是整型')
            self.__name = name
            self.__age = age
    
    #初始化传入的值
    stu1 = Studio('tom',18)
    stu1.tell_info()  #我是tom,今年18岁
    
    #修改怎么修改?调用set_info函数
    stu1.set_info('tt',19)
    #调用
    stu1.tell_info()  #我是tt,今年19岁
    
    #报错:raise TypeError('姓名必须是字符串类型')TypeError: 姓名必须是字符串类型
    stu1.set_info(333,19)
    

    所有最终意义:外部想修改我的类的属性,那么必须严格按照我定义的方法去修改!我是老大听我的!懂?

    3.2 隐藏函数属性

    • 目的的是为了隔离复杂度
    • 内部:把一件事拆分成几件小事
    • 外部:做这件事的人还是做这件事
    • 例如ATM程序的取款功能,该功能有很多其他功能组成,比如插卡、身份认证、输入金额、打印小票、取钱等,而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来
    class ATM:
        def __card(self):  # 插卡
            print('插卡')
    
        def __auth(self):  # 身份认证
            print('用户认证')
    
        def __input(self):  # 输入金额
            print('输入取款金额')
    
        def __print_bill(self):  # 打印小票
            print('打印账单')
    
        def __take_money(self):  # 取钱
            print('取款')
    
        def withdraw(self):  # 取款功能
            self.__card()
            self.__auth()
            self.__input()
            self.__print_bill()
            self.__take_money()
    
    obj = ATM()
    obj.withdraw()
    

    四、封装之property

    什么时候用?
    • 当你想得到某个值,而且这个值必须通过计算属性才能得到,并且访问的时候想通过访问数据属性(P1.h = 1.69)一样访问到它的时候,就可以把这个功能(函数)加上property,让它变成数据属性。

    BMI指数是用来衡量一个人的体重与身高对健康影响的一个指标,计算公式为

    体质指数(BMI)=体重(kg)÷身高^2(m)
    EX:70kg÷(1.75×1.75)=22.86
    

    代码举例:

    class Pleone:
        def __init__(self,name,age,h,w):
            self.name = name
            self.age = age
            self.h = h
            self.w = w
        @property
        def bmi(self):
            return self.w / (self.h ** 2)
    
    P1 = Pleone('xy',18,1.68,53)
    print(P1.bmi)
    #可以更改h、或者w,就可以动态更改bmi
    P1.h = 1.69
    print(P1.bmi)
    

    实际应用:

    class Pleone:
        def __init__(self,name):
            self.__name = name
    
        @property
        def name(self):
            return self.__name
    
        #要想修改name就调用个setter
        @name.setter
        def name(self,obj):
            self.__name = obj
    
        #想删除就调用@name.deleter
        @name.deleter
        def name(self):
            print('不让删除')
            del self.__name
    
    
    p = Pleone('xxx')
    #调用name之前删除 name属性,下面就调用不到
    del p.name
    print(p.name)
    
    #修改,如果不调用@name.setter 会报错
    p.name = 'qqq'
    print(p.name)
    
  • 相关阅读:
    如何查看跟踪查看LINUX内核中的源码
    LINUX中的虚拟文件系统结构
    《linux程序设计》笔记 第一章 入门
    ajax基本用法
    Redis PHP连接操作
    Redis使用详细教程
    PHP缓存技术的多种方法小结
    PHPStorm+XDebug进行调试
    phpstorm配置Xdebug进行调试PHP教程
    Mac上简单常用Terminal命令
  • 原文地址:https://www.cnblogs.com/hsyw/p/13682260.html
Copyright © 2011-2022 走看看