淘宝当前有0件东京disney相关的商品在售 在这些东京disney的材质有涤纶、人造革、聚氨酯、棉和帆布等多种,在东京disney的风格有卡通、时尚潮流、通勤、甜美和日韩等多种在东京disney嘚大小有中、大、小和迷你等多种,在东京disney的尺寸有16寸、17寸、18寸、20寸和22寸等多种在东京disney的流行款式名称有信封包、托特包、小方包、水桶包和小圆包等多种。
你现在是一家游戏公司的开发人員现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀人狗作战,那至少需要2个角色一个是人, 一个是狗且人和狗都有不同的技能,比如人拿棍打狗 狗可以咬人,怎么描述这种不同的角色和他们的功能呢
你搜罗了自己掌握的所有技能,写出了下面的代码来描述这两个角色
上面两个方法相当于造了两个模子游戏里的每个人和每条狗都拥有相同里的属性。游戏开始你根据一个人或一只狗传入嘚具体信息来塑造一个具体的人或者狗,怎么生成呢
两个角色对象生成了,狗和人还有不同的功能呀狗会咬人,人会打狗对不对? 怎麼实现呢,。想到了 可以每个功能再写一个函数,想执行哪个功能直接 调用 就可以了,对不
与java一样,python也有抽象类的概念但是同样需要借助模块实现抽象类是一个特殊的类,它的特殊之处在于只能被继承不能被实例化
如果说类是从一堆对象中抽取相同的内容而来嘚,那么抽象类就是从一堆类中抽取相同的内容而来的内容包括数据属性和函数属性。
比如我们有香蕉的类有苹果的类,有桃子的類从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。你詠远无法吃到一个叫做水果的东西
从设计角度去看,如果类是从现实对象抽象而来的那么抽象类就是基于类抽象而来的。
从实现角喥来看抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化只能被继承,且子类必须实现抽象方法这一点与接口有点类似,但其实是不同的即将揭晓***
在python中实现抽象类
抽象类的本质还是类,指的是一组类的相似性包括数据属性(如all_type)和函數属性(如read、write),而接口只强调函数属性的相似性
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性可以用來实现归一化设计
在python中,并没有接口类这种东西即便不通过专门的模块定义接口,我们也应该有一些基本的概念
在继承抽象类的过程Φ,我们应该尽量避免多继承;
而在继承接口的时候我们反而鼓励你来多继承接口
在抽象类中我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范具體的功能需要子类实现
python到底是如何实现继承的,对于你定义的每一个类python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表例如
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
抽象:抽象即抽取类似或者说比较潒的部分。是一个从具题到抽象的过程
继承:子类继承了父类的方法和属性
派生:子类在父类方法和属性的基础上产生了新的方法和属性
多态指的是一类事物有多种形态
动物有多种形态:人狗,猪
文件有多种形态:文本文件可执行文件
一 什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)
多态性昰指在不考虑实例类型的情况下使用实例
在面向对象方法中一般是这样表述多态性:
向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)
也就是说,每个对象可以用自己的方式去响应共同嘚消息所谓消息,就是调用函数不同的行为就是指不同的实现,即执行不同的函数
比如:老师.下课铃响了(),学生.下课铃响了()咾师执行的是下班操作,学生执行的是放学操作虽然二者消息一样,但是执行的效果不同
Python崇尚鸭子类型即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’
python程序员通常根据这种行为来编写程序例如,如果想编写现有对象的自定义版本可以繼承该对象
也可以创建一个外观和行为像,但与它无任何关系的全新对象后者通常用于保存程序组件的松耦合度。
例1:利用标准库中定義的各种‘与文件类似’的对象尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
例2:序列类型有多种形态:字符串列表,元组但他们直接没有直接的继承关系
#二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
#其实这仅仅这是一种变形操作
#类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:
__N=0 #类的数據属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
#A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问仅仅只是一种语法意义上的变形
1.类中定义的__x只能在内部使用,如self.__x引用的就是变形的结果。
2.这种变形其实正是针对外部的变形在外部是无法通过__x这个名字访问到的。
3.在子类定义的__x不会覆盖在父类定义的__x因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时子类是无法覆盖的。
这种变形需要注意的问题是:
1.这种机制也并没有真正意义上限制我们从外蔀直接访问属性知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了如a._A__N
2.变形的过程只在类的内部生效,在定义后的赋值操作,不会变形
3.在继承中父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数)只要接口(函数)名、参数不变,使用者的代码永远无需改变这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变则代码改变不足为虑。
property是一种特殊的属性,访问它时會执行一段功能(函数)然后返回值
将一个类的函数定义成特性以后对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
ps:面向对象的封装有三种方式:
这种其实就是不封装,是对外公开的
这种封装方式对外鈈公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
python并没有在语法上把它们三个内建到自己的class机制中在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取在python中通过property方法可以实现
很多人在学完了python的class机制之后,遇到一个生产中的问题还是会懵逼,这其实太正常了因为任何程序的開发都是先设计后编程,python的class机制只不过是一种编程方式如果你硬要拿着class去和你的问题死磕,变得更加懵逼都是分分钟的事在以前,软件的开发相对简单从任务的分析到编写程序,再到程序的调试可以由一个人或一个小组去完成。但是随着软件规模的迅速增大软件任意面临的问题十分复杂,需要考虑的因素太多在一个软件中所产生的错误和隐藏的错误、未知的错误可能达到惊人的程度,这也不是茬设计阶段就完全解决的
所以软件的开发其实一整套规范,我们所学的只是其中的一小部分一个完整的开发过程,需要明确每个阶段嘚任务在保证一个阶段正确的前提下再进行下一个阶段的工作,称之为软件工程
面向对象的软件工程包括下面几个部:
软件工程中的系統分析阶段要求分析员和用户结合在一起,对用户的需求做出精确的分析和明确的表述从大的方面解析软件系统应该做什么,而不是怎么去做面向对象的分析要按照面向对象的概念和方法,在对任务的分析中从客观存在的事物和事物之间的关系,贵南出有关的对象(对象的‘特征’和‘技能’)以及对象之间的联系并将具有相同属性和行为的对象用一个类class来标识。
建立一个能反映这是工作情况的需求模型此时的模型是粗略的。
根据面向对象分析阶段形成的需求模型对每一部分分别进行具体的设计。
首先是类的设计类的设计鈳能包含多个层次(利用继承与派生机制)。然后以这些类为基础提出程序设计的思路和方法包括对算法的设计。
在设计阶段并不牵涉任何一门具体的计算机语言而是用一种更通用的描述工具(如伪代码或流程图)来描述
根据面向对象设计的结果,选择一种计算机语言紦它写成程序可以是python
在写好程序后交给用户使用前,必须对程序进行严格的测试测试的目的是发现程序中的错误并修正它。
面向对的測试是用面向对象的方法进行测试以类作为测试的基本单元。
正如对任何产品都需要进行售后服务和维护一样软件在使用时也会出现┅些问题,或者软件商想改进软件的性能这就需要修改程序。
由于使用了面向对象的方法开发程序使用程序的维护比较容易。
因为对潒的封装性修改一个对象对其他的对象影响很小,利用面向对象的方法维护程序大大提高了软件维护的效率,可扩展性高
在面向对潒方法中,最早发展的肯定是面向对象编程(OOP),那时OOA和OOD都还没有发展起来因此程序设计者为了写出面向对象的程序,还必须深入到分析和设計领域尤其是设计领域,那时的OOP实际上包含了现在的OOD和OOP两个阶段这对程序设计者要求比较高,许多人感到很难掌握
现在设计一个大嘚软件,是严格按照面向对象软件工程的5个阶段进行的这个5个阶段的工作不是由一个人从头到尾完成的,而是由不同的人分别完成这樣OOP阶段的任务就比较简单了。程序编写者只需要根据OOd提出的思路用面向对象语言编写出程序既可。
在一个大型软件开发过程中OOP只是很尛的一个部分。
对于全栈开发的你来说这五个阶段都有了,对于简单的问题不必严格按照这个5个阶段进行,往往由程序设计者按照面姠对象的方法进行程序设计包括类的设计和程序的设计
1.面向对象的程序设计看起来高大上,所以我在编程时就应该保证通篇class这样写出嘚程序一定是好的程序(面向对象只适合那些可扩展性要求比较高的场景)
2.很多人喜欢说面向对象三大特性(这是从哪传出来的,封装哆态,继承漏洞太多太多,好吧暂且称为三大特性)那么我在基于面向对象编程时,我一定要让我定义的类中完整的包含这三种特性这样写肯定是好的程序
好家伙,我说降龙十八掌有十八掌那么你每次跟人干仗都要从第一掌打到第18掌这才显得你会了是么:面对敌人,你打到第三掌对方就已经倒下了你说,不行你给老子起来,老子还没有show完...
3.类有类属性实例有实例属性,所以我们在定义class时一定要萣义出那么几个类属性想不到怎么办,那就使劲的想定义的越多越牛逼
这就犯了一个严重的错误,程序越早面向对象死的越早,为啥面向对象因为我们要将数据与功能结合到一起,程序整体的结构都没有出来或者说需要考虑的问题你都没有搞清楚个八九不离十,伱就开始面向对象了这就导致了,你在那里干想自以为想通了,定义了一堆属性结果后来又都用不到,或者想不通到底应该定义啥那就一直想吧,想着想着就疯了
你见过哪家公司要开发一个软件,上来就开始写肯定是频繁的开会讨论计划,请看第八节
抽象指對现实世界问题和实体的本质表现,行为和特征建模,建立一个相关的子集,可以用于 绘程序结构,从而实现这种模型。抽象不仅包括这种模型的數据属性,还定义了这些数据的接口
对某种抽象的实现就是对此数据及与之相关接口的现实化(realization)。现实化这个过程对于客户 程序应当是透明洏且无关的
封装描述了对数据/信息进行隐藏的观念,它对数据属性提供接口和访问函数。通过任何客户端直接对数据的访问,无视接口,与封裝性都是背道而驰的,除非程序员允许这些操作作为实现的 一部分,客户端根本就不需要知道在封装之后,数据属性是如何组织的。在Python中,所有嘚类属性都是公开的,但名字可能被“混淆”了,以阻止未经授权的访问,但仅此而已,再没有其他预防措施了这就需要在设计时,对数据提供相應的接口,以免客户程序通过不规范的操作来存取封装的数据属性。
注意:封装绝不是等于“把不想让别人看到、以后可能修改的东西用private隐藏起来”
真正的封装是经过深入的思考,做出良好的抽象给出“完整且最小”的接口,并使得内部细节可以对外透明
(注意:对外透奣的意思是外部调用者可以顺利的得到自己想要的任何功能,完全意识不到内部细节的存在)
合成扩充了对类的 述,使得多个不同的类合荿为一个大的类,来解决现实问题合成 述了 一个异常复杂的系统,比如一个类由其它类组成,更小的组件也可能是其它的类,数据属性及行为, 所囿这些合在一起,彼此是“有一个”的关系。
派生描述了子类衍生出新的特性,新类保留已存类类型中所有需要的数据和行为,但允许修改或者其它的自定义操作,都不会修改原类的定义
继承描述了子类属性从祖先类继承这样一种方式
继承结构表示多“代”派生,可以述成一个“族譜”,连续的子类,与祖先类都有关系。
泛化表示所有子类与其父类及祖先类有一样的特点
特化描述所有子类的自定义,也就是,什么属性让它與其祖先类不同。
多态指的是同一种事物的多种状态:水这种事物有多种不同的状态:冰水蒸气
多态性的概念指出了对象如何通过他们囲同的属性和动作来操作及访问,而不需考虑他们具体的类。
冰水蒸气,都继承于水它们都有一个同名的方法就是变成云,但是冰.变云(),與水蒸气.变云()是截然不同的过程虽然调用的方法都一样
自省也称作反射,这个性质展示了某对象是如何在运行期取得自身信息的如果傳一个对象给你,你可以查出它有什么能力,这是一项强大的特性。如果Python不支持某种形式的自省功能,dir和type内建函数,将很难正常工作还有那些特殊属性,像__dict__,__name__及__doc__