19.7.26
作者:互联网
面向对象封装:
封装就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装的真谛在于明确地区分内外,封装的属性可以直接在内部使用,而不能被外部直接使用,
然而定义属性的目的终归是要用,外部要想用类隐藏的属性,需要我们为其开辟接口,
让外部能够间接地用到我们隐藏起来的属性;被封装的内容的特点:1.外界不能直接访问,2.内部依然可以使用。
两个目的:
1.为了保证 关键数据的安全性。
2.对外部隐藏实现细节,隔离复杂度。
封装原则:
1. 将不需要对外提供的内容都隐藏起来;
2. 把属性都隐藏,提供公共方法对其访问。
学习了封装后就可以控制属性的权限;在python只要两种权限,
1.公开的.默认就是公开的。
2.私有的,只能由当前类自己使用。
在外界访问私有的内容:
属性虽然被封装了,但是还是需要使用的,在外界如何访问。
通过定义方法类完成对私有属性的修改和访问。
什么时候应该封装:
当有一些数据不希望外界可以直接修改时
当有一些函数不希望给外界使用时
如何使用封装呢?语法如下:
""" 在python中用双下划线开头的方式将属性隐藏起来(设置成私有的) 其实这仅仅这是一种变形操作且仅仅只在类定义阶段发生变形 类中所有双下划线开头的名称如__x都会在类定义时自动变形成:_类名__x的形式: """ class A: __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N def __init__(self): self.__X=10 #变形为self._A__X def __foo(self): #变形为_A__foo print('from A') def bar(self): self.__foo() #只有在类内部才可以通过__foo的形式访问到. #A._A__N是可以访问到的, #这种,在外部是无法通过__x这个名字访问到。
封装方法:
其目的是隔离复杂度。
""" 在编程语言里,对外提供的接口(接口可理解为了一个入口),
可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。 """ # 取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱 # 对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做 # 隔离了复杂度,同时也提升了安全性 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() a=ATM() a.withdraw()
封装数据:
""" 将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,
然后我们可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格控制。 """ class Teacher: def __init__(self,name,age): # self.__name=name # self.__age=age self.set_info(name,age) def tell_info(self): print('姓名:%s,年龄:%s' %(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 t=Teacher('jack',18) t.tell_info() t.set_info('jack',19) t.tell_info()
property装饰器:
property就是将一个类的函数定义成特性以后,对象再去使用的时候obj.name,
根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。
""" property装饰就是为了使得调用方式一致;有三个相关的装饰器 : 1.property 该装器用在获取属性的方法上 2.@key.setter 该装器用在修改属性的方法上 3.@key.deleter 该装器用在删除属性的方法上 key是被property装饰的方法的名称 也就是属性的名称 内部会创建一个对象 变量名称就是函数名称 所以在使用setter和deleter时 必须保证使用对象的名称取调用方法 所以是 key.setter """ class Foo: def __init__(self,val): self.__NAME=val #将所有的数据属性都隐藏起来 @property def name(self): return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置) @name.setter def name(self,value): if not isinstance(value,str): #在设定值之前进行类型检查 raise TypeError('%s must be str' %value) self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME @name.deleter def name(self): raise TypeError('Can not delete') f=Foo('egon') print(f.name) # f.name=10 #抛出异常'TypeError: 10 must be str' del f.name #抛出异常'TypeError: Can not delete'
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;
而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。
这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。
abc模块的使用:
抽象类概念
抽象类是一个特殊的类,只能被继承,不能实例化
2.为什么要有抽象类
其实在未接触抽象类概念时,我们可以构造香蕉、苹果、梨之类的类,然后让它们继承水果这个的基类,水果的基类包含一个eat函数。
但是你有没有想过,我们可以将香蕉、苹果、梨实例化,去吃香蕉、苹果、梨。但是我们却不能将水果实例化,因为我们无法吃到叫水果的这个东西。
所以抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。
3.抽象类的作用
在不同的模块中通过抽象基类来调用,可以用最精简的方式展示出代码之间的逻辑关系,让模块之间的依赖清晰简单。
抽象类的编程,让每个人可以关注当前抽象类的方法和描述,而不需要考虑过多的实现细节,这对协同开发有很大意义,也让代码可读性更高。
""" abc 不是随意取的 而是单词的缩写 abstract class 翻译为抽象类 抽象类的定义 : 类中包含 没有函数体的方法 """ import abc class AClass(metaclass=abc.ABCMeta): @abc.abstractmethod def run(self): pass @abc.abstractmethod def run1(self): pass class B(AClass): def run(self): print("runrunrurn...") b = B()
接口:
接口是一套协议规范,明确子类们应该具备哪些功能;抽象类是用于强制要求子类必须按照协议中规定的来实现;
然而,python不推崇限制你的语法, 我们可以设计成鸭子类型,既让多个不同类对象具备相同的属性和方法;
对于使用者而言,就可以以不变应万变,轻松的使用各种对象;只要遵循了USB接口协议,都能够被电脑所调用;
接口主要是方便了对象的使用者,降低使用者的学习难度;只要学习一套使用方法,就可以以不变应万变。
class Interface: def f1(self): ''' to do something :return: ''' class Something(Interface): def f1(self): print('to do something...') def f2(self): print('to do other..')
标签:__,26,19.7,name,self,.__,print,def 来源: https://www.cnblogs.com/sweet-i/p/11252771.html