美文网首页python热爱者
一篇python纯干货,实打实的讲解面对对象的编程思维!

一篇python纯干货,实打实的讲解面对对象的编程思维!

作者: 48e0a32026ae | 来源:发表于2018-10-11 16:13 被阅读10次

    三大特性,五大准则

    三大特性是:封装,继承,多态

    所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。

    所谓继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

    所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

    五大基本原则

    单一职责原则SRP(Single Responsibility Principle)

    是指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,否则一天到晚虽然忙忙碌碌的,但效率却高不起来。

    开放封闭原则OCP(Open-Close Principle)

    一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,

    那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。

    替换原则(the Liskov Substitution Principle LSP)

    子类应当可以替换父类并出现在父类能够出现的任何地方。比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,

    也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。

    依赖原则(the Dependency Inversion Principle DIP) 具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,

    这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口:这样就达到

    了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造成循环依赖。一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。

    接口分离原则(the Interface Segregation Principle ISP)

    模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来

    封装

    定义:

    1. 封装 是面向对象编程的一大特点

    2. 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中

    3. 外界 使用 类 创建 对象,然后 让对象调用方法

    4. 对象方法的细节 都被 封装 在 类的内部

    为什么要封装?

    封装数据的主要原因是:保护隐私(作为男人的你,脸上就写着:我喜欢男人,你害怕么?)

    封装方法的主要原因是:隔离复杂度(快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了,比如你不必知道你自己的尿是怎么流出来的,你直接掏出自己的接口就能用尿这个功能)

    提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),就是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体

    百度搜索的例子:

    以下是demo1文件的代码

    from selenium import webdriver

    from time import sleep

    dr = webdriver.Chrome()

    dr.get('http://www.baidu.com')

    sleep(3)

    dr.find_element_by_id('kw').send_keys('demo')

    dr.find_element_by_id('su').click()

    sleep(3)

    dr.quit()

    从上面看,脚本从上往下按步骤执行。假如我想把以下的代码封装起来呢,

    dr.find_element_by_id(‘kw’).send_keys(‘demo’)

    dr.find_element_by_id(‘su’).click()

    那么我们怎么修改才能实现函数的封装,然后调用函数呢?

    首先我们新建一个demo2 的python文件。新建demo2的目的是把函数放在公共的模块,方便调用,其代码如下

    '''函数传参必须传入dr驱动,def search_text(dr):'''

    def search_text(dr):

    dr.find_element_by_id('kw').send_keys('demo')

    dr.find_element_by_id('su').click()

    demo1文件的代码修改如下

    from selenium import webdriver

    from time import sleep

    from demo2 import search_text #导入demo2的search_text函数

    dr = webdriver.Chrome()

    dr.get('http://www.baidu.com')

    sleep(3)

    '''函数传参必须传入dr驱动,search_text(dr)'''

    search_text(dr) #调用demo2的search_text(dr)

    sleep(3)

    dr.quit()

    继承

    面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

    通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”,继承的过程,就是从一般到特殊的过程。在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

    继承概念的实现方式主要有2类:实现继承、接口继承。

    实现继承是指使用基类的属性和方法而无需额外编码的能力。

    接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法)

    在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。

    OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

    python和C++一样,支持多继承。概念虽然容易,但是困难的工作是如果子类调用一个自身没有定义的属性,它是按照何种顺序去到父类寻找呢,尤其是众多父类中有多个都包含该同名属性。

    对经典类和新式类来说,属性的查找顺序是不同的。现在我们分别看一下经典类和新式类两种不同的表现:

    定义:

    执行的结果:

    p1-foo

    p2-bar

    将代码实例,画了一个图,方便理解:

    从上面经典类的输出结果来看,

    实例d调用foo()时,搜索顺序是 D => C1 => P1,

    实例d调用bar()时,搜索顺序是 D => C1 => P1 => P2

    总结:经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性。d先查找自身是否有foo方法,没有则查找最近的父类C1里是否有该方法,如果没有则继续向上查找,直到在P1中找到该方法,查找结束。

    子类对父类的重写

    多态

    多态顾名思义 即一个接口的多种实现方式,子类实力指向父类对象的用法称为多态中的向上转型,多用于方法参数,类中的实例属性,以及

    函数返回值中,向上转型时父类对象只能调用本类所拥有的实例,如果父类中有和子类定义相同名称的方法,则优先调用子类实例中的方法

    并且,父类对象不能调用子类中特有的方法(子类有父类没有)

    向下转型:则指父类实例赋值给子类对象,与向上转型不同的是子类实例不仅可以调用自己的方法,而且可以调用父类中的任何方法,包括

    父类所特有的方法,当所调用的方法与父类方法一致时则仍然调用自己的方法(毕竟子类继承了父类,所以父类中的属性和方法子类中同样拥有)

    A : 首先需要了解一下为什么需要提供函数重载:

    函数重载主要为了解决两个问题

    <1> 可变参数类型

    <2> 可变参数个数

    B :为了解决上述两个问题,Python以如下两条特性进行了处理

    特性一:在Python中,类型属于对象,变量是没有类型的。所有,Python中函数的参数没有类型,这就决定了对同一个参数,可以传入不同类型的值

    特性二:Python为函数提供了缺省参数,如下

    输出结果为:

    x : -1

    y :-1

    x : 1

    y :-1

    x : 1

    y :2

    类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 StudentTeacher ,并都写了一个 whoAmI() 方法:

    为什么要用多态(多态的好处)

    其实大家从上面多态性的例子可以看出,我们并没有增加上面新的知识,也就是说Python本身就是支持多态性的,这么做的好处是什么呢?

    (1)增加了程序的灵活性

    以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)

    (2)增加了程序额可扩展性

    通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用

    相关文章

      网友评论

        本文标题:一篇python纯干货,实打实的讲解面对对象的编程思维!

        本文链接:https://www.haomeiwen.com/subject/diibaftx.html