python笔记系列-day11 类和对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fk002008/article/details/84966708

目录

 

回顾

面向对象编程的元素

  初阶面向对象

 高阶面向对象

Python的类 class

定义对象

空类具有的属性

定义成员方法

python的构造函数

self的使用

相对的隐藏性

类的继承

__init__方法

多继承

顶层父类

super()函数

super()调用和直接使用父类名调用的区别

pass 关键字使用

Python多态

函数式接口的Python表达


回顾

      前面几天已经学到了Python的基础知识了,有那些知识我们按照面向过程的方法进行编程了。

但是python也给我们提供了面向对象编程的元素机制。面向过程和面向对象在于方法使用不在于编程语言特点。

从c转入java的也是拿着面向对象的语言写着面向过程的程序。如果你领悟了面向对象那么你即使使用了c也可以开发出面向对象的

程序,当然你要灵活使用指针来自己去造面向对象元素的轮子。

面向对象编程的元素

  初阶面向对象

          从C++学起再到java ,一直离不开面向对象.

   基础阶段的面向对象编程元素 : 封装 , 继承 , 多态  。

    可能大家对继承比较偏爱,这三大法宝里面其实 封装 是最难的,也是最灵活的,

   因为有个粒度和度的把握,也是面向对象艺术编程的体现。

   多态活化了对象,使面向对象多姿多彩。

  反而是继承,初阶面向对象我们使用继承来扩展,疑问这是面向对象的精髓,恰恰误导了我们。

   因为封装,提出了类的概念,但是类只是实现封装的一种机制而已不是唯一。

  从类我们出现了继承的概念,那么继承和类是出现在一起的,类是为了去描述定义的,那么继承也是用它来进行概念的描述

  更贴近它的用途。

   封装最不好把控,可大可小,依据的角度也很多。所以好好领悟封装的奥义就把握了面向对象的命脉。

 高阶面向对象

  从初阶过来习惯了使用 继承来做扩展,但是庞大的继承层次反而消掉了灵活性。

  到高阶将要学会多种设计思想并且使用它们指导面向对象开发。

  第一个就是使用  组合来代替继承做扩展

 第二个 面向接口编程

 第三个  设计模式中的几个思想 

 第四个 AOP

从这里围绕着如何对程序的扩展做到 开闭 目的展开

至此需要知道,实现封装的手段很多,实现继承的手段也很多(了解下nodejs中的prototype)

那么python也有自己的类和自己的封装机制

有着C体系的面向对象基础学习python的这个是很简单的,触类旁通

Python的类 class

使用 class 关键字来定义一个类,非常的简单,注意范围仍然是 从 冒号开始的

定义对象

定义对象和我们的 C++使用类似,看样子是调用了构造函数,但是呢

python自己有自己的机制,后面我们会说道 __inti__才是 主因

目前我们就记住 创建对象使用  C++那种构造函数调用即可

空类具有的属性

前面说过 查看属性使用   dir()函数进行

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

空类具有的属性也就是这个对象具有的属性。

定义成员方法

C++和java中的成员方法是被封装于类中啊,没用static修饰的函数,每个成员方法内部有一个 this 的对象

其实呢这个this 是隐藏的,可以写可以不写,最终调用该方法的时候会将  发起消息的对象 传给this

这个就实现了当前对象调用方法执行的数据都是当前对象的。

我们如果再拓展下,如果将这个方法中的this 作为方法的一个参数,也是可以实现的

那么python就用了这种方式,但是python中不是this  , 而是 self 

还有一点,python的类里面可以定义成员方法也可以定义普通的函数的

所以python定义的成员方法就 很突出明显 ,只要在函数的参数中第一个加入一个 self 

调用成员方法的对象会把当前调用的对象传递给self,当然调用的时候这个参数是可以忽略传值的。

如果我们的函数没有self这个参数,那么这个函数就是类的函数了。对象自己是无法进行调用的。

例如下面我们在 命令行中定义一个类

(命令行中定义的时候,注意缩进,第二行笔第一行多一个空格

    如果是def内部,那么语句比 def 中的d 右移一个空格

   空格不对会报语法错误的

下面这个类No 定义了 两个 属性,一个是成员方法,一个是类的方法

可以看到在外部对象是无法使用这个类的方法的.

python的构造函数

C++和Java中的构造函数定义是函数名字必须和类的名字相同

但是python呢,使用固有的函数名字  __inti__来表示一个构造函数,但是也需要和成员方法一样加入 self这个额外参数

但是外部调用的时候我们要用  C++创建对象的方式使用 

self的使用

python对象的属性定义不像 C++和 Java , 需要在类中定义对象的成员属性。

python的成员属性定义在了 self 的属性中

然而  这种定义简直和 javascript 对象属性的定义一样,灵活,不拘一格。

只要给 self 增加属性就可以了,self的属性就是这个类创建出对象的属性

这个加大了对象创建的灵活度,属性增加很自由的。

对象所需要的属性我们在 构造函数 __init__的时候进行设置增加就可以了

相对的隐藏性

Java等语言中我们可以通过  public , private 等访问控制符来控制属性包括方法的访问

但是python 呢,我们只能做多相对的隐藏。我们可以 给一个对象里面设置 getter/setter 方法

但是,self里面的属性,对象使用的时候仍然是可以直接访问的,因为并没有 如同Java类似的权限进行限制

例如下面这个例子,我们使用的时候,直接可以访问

(这里使用的时候我们 使用了 import ,这个是模块的概念,Java里面有类似的包机制,我们目前认为

py文件要使用里面定义的东西的时候需要导入这个文件才可以.

这个例子 我们的 py 文件名是  No  ,No.py

恰巧的是 文件名和类名是一样的,这个不是必然的要求)

我们可以看到  可以直接访问这个对象的属性的,前提你要是知道这个对象有这么个属性的话

我们如果要进行隐藏,也只能是 控制住这个属性不被外部知道,通过api方式控制住

外部使用者只能从api中知道可以使用的属性

 

类的继承

没有如同java中优雅的 extend 来表示继承

python类的继承方式很简单,通过如下的方式进行继承

class 类名(父类名) :

如果需要使用父类的东西,就要使用 父类.属性

__init__方法

我们知道子类的构造函数定义时候必须要调用父类的构造函数

因此 对于 __init__方法来说,子类的需要调用父类的__init__

调用父类的 __init__方法的时候,注意 self也要传递进去

然后对于重写方法,只要覆盖定义一遍就行

例如下面的代码:这里用到了模块

模块目前你认为就是一个python的源文件就行

Man继承了Person,然后再初始化的时候调用了父类的__init__

因此Man也具有Person的getName,getAge 等方法

多继承

到目前为止我们发现python好多类的使用上是和C++类似的,C++可以继承多个类,Java只能继承一个类

那么Python呢,Python也是可以继承多个类的

class 类名(父类1,父类2,父类3,...) :

但是多继承带来的困扰就是 父类中 方法重名的问题如何进行辨析

当继承多个父类时,如果父类中有相同的方法,那么子类会优先使用最先被继承的方法

顶层父类

和java一样,python也有一个顶层的父类,称为 Object

例如上面定义的类 No ,类属性中有一个  __bases__属性,表示了其父类

我么再做一个 No的子类,看看这个__bases__属性

我们再做一个 No2,继承多个类,我们发现__bases__属性 

super()函数

C体系中是super 关键字表示了父类

但是在python中要使用 super() 函数来表示父类

super()调用和直接使用父类名调用的区别

使用 父类名调用的时候,每次执行都会重新定义

但是super()只会定义一次

还有很多的区别需要我们发掘。

pass 关键字使用

如果一个类内部不想做任何定义,直接使用pass 就可以了

Python多态

C体系中的多态,总是通过如下的方式

父类  对象 = new 各种子类

然后通过后面的实际分配的子类对象的地址的数据从而达到多态

也就是前面的的对象调用统一的api方法时候,根据实际对象呈现不同的效果

但是Python中我们定义对象并不需要这个  类型的声明限制

因此 只能 靠着 api的呈现,由于没有 类型的约束限制,所以这种多态只要对象具有约定的方法就可以进行.

没有类型约束有坏处,我们编写的时候不能使用父类或者接口做统一的入参约束,

没有类型约束也有好处,定义对象自由,没有类型约束

但我们依然可以 像Java一样画葫芦 来进行 多态的实现

例如上面例子中给  people 类中增加 marrige成员方法,这样 

man 和 women 都覆盖这个方法之后,他们各自 生产的对象 都有  marrige方法

进行调用时候就呈现出了 多态。

函数式接口的Python表达

Java8中出现的函数式接口给使用  Java 的 lambda表达式提供了实现机制

通过函数式接口我们可以 规范行为。

猜你喜欢

转载自blog.csdn.net/fk002008/article/details/84966708