码迷,mamicode.com
首页 > 其他好文 > 详细

02-封装

时间:2020-04-08 22:55:42      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:card   raise   ini   atm   打印   数据隐藏   基本概念   字符   info   

一、封装的基本概念

面向对象编程有三个特性:封装继承多态,其中封装特性极为重要。封装指的是把数据与功能整合到一起。当然针对封装到对象或者类中的属性,我们还可以严格控制对它们的访问,分两步实现:隐藏开放接口

二、隐藏属性

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

class Foo:
    __N = 0	# 变形为_Foo__N

    def __init__(self):	# 定义函数时,会检测函数语法,所以__开头的属性也会变形
        self.__x = 10	# 变形为self._Foo__x

    def __f1(self):	# 变形为_Foo__f1
        print("__f1 run")

    def f2(self):	# 定义函数时,会检测函数语法,所以__开头的属性也会变形
        self.__f1()	# 变形为self._Foo__f1()

print(Foo.__N)	# 报错AttributeError:类Foo没有属性__N

obj = Foo()
print(obj.__x)	# 报错AttributeError:对象obj没有属性__x

这种变形需要主要的问题是:

  1. 在类外部无法直接访问双下划线开头的属性,但知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如Foo._A__N,所以说这种操作并没有严格意义上地限制外部访问,仅仅只是语法意义上的变形
>>> Foo.__dict__
mappingproxy({..., ‘_Foo__N‘: 0, ...})
>>> obj.__dict__
{‘_Foo__x‘: 10}

>>> Foo._Foo__N
0
>>> obj._Foo__x
10
>>> obj._Foo__N
0
  1. 在类内部时可以直接访问双下划线开头的属性的,比如self.__f1(),因为在类定义阶段内部双下划线的属性统一发生了变形
>>> obj.f2()
__f1 run
  1. 变形操作只是类定义阶段发生一次,在类定义之后的赋值操作,不会变形
>>> Foo.__M=100
>>> Foo.__dict__
mappingproxy({..., ‘__M‘: 100,...})
>>> Foo.__M
100

>>> obj.__y=20
>>> obj.__dict__
{‘__y‘: 20, ‘_Foo__x‘: 10}
>>> obj.__y
20

三、开放接口

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

1.隐藏数据属性

将数据隐藏起来就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制

class Teacher:
    def __oct__(self,name,age): # 将名字和年纪都隐藏起来
        self.__name = name
        self.__age = age

    def tell_info(self): # 对外提供访问老师信息的接口
        print("姓名:{},年龄:{}".format(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

teacher_obj = Teacher()
teacher_obj.set_info("LiLi","19")
"""
TypeError: 年龄必须是整型
"""
teacher_obj.set_info("lili",18)
teacher_obj.tell_info()
"""
姓名:lili,年龄:18
"""

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 witudraw(self): # 取款功能
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()

ATM_obj = ATM()
ATM_obj.witudraw()

总结隐藏属性与开放接口,本质就是为了明确地区分开内外,类内部可以修改封装地东西而不影响外部调用者的代码,使用者均无需改变代码。这就提供一个良好的合作基础,只要接口这个基础约定不变,则代码的修改不足为虑

02-封装

标签:card   raise   ini   atm   打印   数据隐藏   基本概念   字符   info   

原文地址:https://www.cnblogs.com/zhuyouai/p/12663234.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!