编程范式概述:
面向过程 和 面向对象 以及函数式编程
面向过程:(Procedure Oriented)是一种以事件为中心的编程思想。
就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。(即执行有先后顺序)
需要纵观全局,对每一个环节知根知底,每个步骤之间联系非常紧密。 支持面向过程的程序设计语言有:C语言 C++ Python等
面向对象:(Object Oriented,简称:OO)是一种以事务为中心的编程思想。
面向对象是把整体分为多个环节,对每个环节单独分析解决,最后整合到一起。 支持面向对象的程序设计语言有C++、Java、C#、Python等。
术语:面向对象的程序设计(Object Oriented Programming,简称为OOP )
函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可

举例对比面向过程 和 面向对象: 例如汽车!
区别:
“面向过程”的话:汽车启动是一个事件,汽车到站是另一个事件。
编程的时候我们关心的是:某一个事件,而不是汽车本身。
然后分别对启动和到站编写程序,类似的还有修理等等。
“面向对象”则是:需要建立一个汽车的实体,由实体引发事件。
编程的时候我们关心的是:由汽车抽象成的对象,这个对象有自己的属性,像发动机:型号,马力,产地等;
有自己的方法,像启动,行驶等;方法也就是汽车的行为,而不是汽车的每个事件。

联系:
“面向过程”其实是最为实际的一种思考方式;就算是面向对象的方法,也含有面向过程的思想。
可以说面向过程是一种基础的方法,它考虑的是实际功能的实现。一般的面向过程是从上往下步步求进,所以面向过程最重要的是模块化的思想方法。
而“面向对象”的方法主要是把事物给对象化,对象包括属性与行为。
当程序规模不是很大时,“面向过程”的方法还会体现出一种优势,因为程序的流程很清楚,按着模块与函数的方法可以很好的组织。
但是,当程序规模较大的时候,“面向对象”的方法优势就会明显的体现出来:具有程序结构清晰,实现简单,
可有效地减少程序的维护工作量,代码重用率高,软件开发效率高等优点。

另一个通俗的例子:印刷术
面向过程:传统的雕版印刷,把整个板子刻满字,每次印都要刻一块
面向对象:毕昇的活字印刷,把每个字分别雕好,用的时候拼到一起
因为面向过程的联系紧密,单个步骤出错对整体影响比较大,比如整本书需要雕10块木板,结果雕错一个字,一整块木板都要扔掉重新刻。

实例:用函数式编程的方式 实现打印输出如下内容:

小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,最爱打游戏
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,最爱打游戏
def foo (name,age,gender,content):
print(name,age,gender,content)
foo("小明","10岁","男","上山去砍柴")
foo("小明","10岁","男","开车去东北")
foo("小明","10岁","男","最爱打游戏") foo("老李","50岁","男","上山去砍柴")
foo("老李","50岁","男","开车去东北")
foo("老李","50岁","男","最爱打游戏")
#===========>>> 上边写法的不足: 参数调用 存在问题
#将上方的实例 改写成面向对象
class Bar:
def foo(self,name,age,gender,content):
print(self,name,age,gender,content)
obj = Bar()
obj.foo("小明","10岁","男","上山去砍柴")
obj.foo("小明","10岁","男","开车去东北")
obj.foo("小明","10岁","男","最爱打游戏")
#输出结果:其中,self 生成的了引用对象地址
#<__main__.Bar object at 0x0000000000705320> 小明 10岁 男 上山去砍柴
#<__main__.Bar object at 0x0000000000705320> 小明 10岁 男 开车去东北
#<__main__.Bar object at 0x0000000000705320> 小明 10岁 男 最爱打游戏
#上方改成了面向对象的方式 但是参数的传递 不够简洁 待优化!

一 定义:
函数:
def + 函数名(参数)
面向对象:
class 类=>> 上方名字叫Bar类
def 方法=>> 上方实例中叫foo
### self 此处必须写。 代指:调用方法的对象(中间人)这个参数是Python自动传递的。
二 执行:
函数:
函数名(参数)
面向对象:
obj = Bar() # 相当于创建了中间人,这个中间人就是一个对象。
obj.foo

理解方法中的self参数:
(1)当程序执行到obj = Bar()的时候,解释器会根据类名Bar()创建了一个中间人(对象),我们可以理解为是:对象应用了类
(2)当中间人(对象)obj执行.foo方法的时候,首先根据上方关联的类名查找.foo方法 然后执行foo方法。
(3)foo中的self 必须写,代指:调用方法的对象(中间人)该参数是Python自动传递的;执行之后,self输出结果,生成的是一个对象引用地址。
(4)中间人(对象)中可以添加参数,即:可以进行值传递。

self 代指:执行当前方法的对象!

而这个‘当前’需要另外注意:在涉及到继承关系的时候,无论对象是调用执行当前类中的方法,还是继承调用父类中的方法,self都是代指外部最开始调用相应方法的对象!

# 实例:理解方法中的self

class Bar:
def foo(self,arg):
print(self,self.name,self.age,arg) zhong_obj1 = Bar() # 中间人(对象1)
zhong_obj1.name = 'jesson' # 说明:中间人(对象)中可以带值 当作参数传递给类里边方法中的self
zhong_obj1.age = '' # 说明:中间人(对象)中可以带有多个值 当作参数传递
zhong_obj1.foo(888) zhong_obj2 = Bar() # 中间人(对象2) 说明:同一个类 可以被多个对象引用
zhong_obj2.name = 'pitter'
zhong_obj2.age = ''
zhong_obj2.foo(666) # 输出结果:
# <__main__.Bar object at 0x0000000000A65390> jesson 25 888
# <__main__.Bar object at 0x0000000000A65400> pitter 20 666

# 优化上方 面向对象改写的实例 [给对象存放值 当作参数传递]

#优化一
class Bar:
def foo(self,contnt):
print(obj.name,obj.age,obj.gender,contnt)
obj = Bar()
obj.name = '小明'
obj.age = 10
obj.gender = '男' obj.foo("上山去砍柴")
obj.foo("开车去东北")
obj.foo("最爱打游戏")

上方的优化 已经基本符合要求
但是还不够简洁 Python这个时候 提供了一种方式,即:构造方法 __init__() 用来封装相关对象默认字段的值

构造方法: 类名后边加括号 自动执行__init__方法   (即:实例化对象的时候,就会执行__init__方法)
特殊作用: [初始化] 用来存放一些默认字段
obj = 类名()
(1)创建对象
(2)通过对象执行类中的一个方法

#采用 构造方法__init__() 对上述实例进一步优化:
class Bar:
def __init__(self,n,a,g):
self.name = n
self.age = a
self.gender = g
def foo(self,contnt):
print(self.name,self.age,self.gender,contnt) obj = Bar("小明",10,"男") obj.foo("上山去砍柴")
obj.foo("开车去东北")
obj.foo("最爱打游戏")

小结:
通过上述实例的优化对比,可以看出,如果使用函数式编程,
需要在每次执行函数时传入相同的参数,如果参数多的话,又需要粘贴复制了..;
而对于面向对象只需要在创建对象时,将所有需要的参数封装到当前对象中,
之后再次使用时,通过self间接去当前对象中取值即可。

面向对象适用场景:
如果多个函数中有一些相同参数时,转换成面向对象。
面向对象的三大特性:
面向对象的三大特性是指:封装、继承和多态。

一、封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
将内容封装到某处
从某处调用被封装的内容

二、继承
继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

# 基本用法:
class 父类:
def 父类中的方法(self): class 子类(父类):
pass son = 子类()
son.父类中的方法()

实例:

class Father:
def f1(self):
print('Father.f1')
def f2(self):
print('Father.f2')
class Son(Father):
def s1(self):
print('Son.s1')
obj = Son()
obj.s1()
obj.f1()
# 输出结果:
# Son.s1
# Father.f1 # 继承了父类 调用执行父类中的f1方法。

我们知道 如果子类继承了父类 则可以调用父类中的所有方法
那 我们可不可以 调用的时候 不去继承执行父类的方法 而指定执行自己内部的方法呢?
答案:肯定是可以的!

情况1: 不执行父类的方法 执行自己的同名方法
在本地重写和父类中同名的方法 即:在自己内部写一个同名的方法:f2

实例:
class Father:
def f1(self):
print('Father.f1')
def f2(self):
print('Father.f2')
class Son(Father):
def s1(self):
print('Son.s1')
def f2(self):
print('Son.f2')
obj = Son()
obj.s1() # 输出结果:Son.s1
obj.f2() # 输出结果:Son.f2

# 情况2: 即可以执行父类的方法 同时也可以执行自己的同名方法
# 这里可以调用Python内置方法 super()

# 实例:
class Father:
def f1(self):
print('Father.f1')
def f2(self):
print('Father.f2')
class Son(Father):
def s1(self):
print('Son.s1')
def f2(self):
# 方式一
super(Son,self).f2()
# 方式二
Father.f2(self)
print('Son.f2')
obj = Son() # 输出结果:Son.s1
obj.s1() # 输出结果:Father.f2
obj.f2() # 输出结果:Son.f2

# *重点* 多继承的查找顺序# 先来看实例:
# 情况1:
# 子类继承两个父类 两个父类中都有子类调用的方法 该如何继承?

补充注意:子类继承多个父类的写法,即支持多继承!在C++和Python中是支持的,但 在C#和Java中,是不支持的,他们为了避免继承混淆,通常只支持子类继承一个父类的写法!

class Father1:
def a(self):
print('Father1.a')
class Father2:
def a(self):
print('Father2.a') class Son(Father2,Father1):
pass
obj = Son()
obj.a()
# 输出结果:说明:这种情况下 从左往右继承
# Father2.a

结论:

情况2
子类Son继承两个父类 其中一个父类Father1没有该子类调用的方法
而该父类又继承了别的类Grand Grand类中有子类Son调用的方法 然而另一个父类Father2中,也有该子类Son调用的方法,
此时 是找完Father1没找到,继续往上层Grand里边找,还是返回到另一个父类Father2中找? 该如何继承?
看图:

class Grand:
def a(self):
#def b(self): #如果将a方法改成b 则会返回父类Father2中查找方法a
print('Grand.a')
class Father1(Grand):
def b(self):
print('Father1.b')
class Father2:
def a(self):
print('Father2.a') class Son(Father1,Father2):
pass
obj = Son()
obj.a()
# 输出结果:结论:这种情况下 先从左往右继承Father1,发现找不到方法a,继续往上层找,如果还找不到,就返回到另一个父类Father2中查找。
# Grand.a

#情况三

#看图:

Python继承调用顺序        总结:【以下两个结论是在Python3环境下,得出的,也就是针对新式类而言!!!】

情况1:

    如果没有共同的基类(即:继承结构顶部没有交集),那么继承调用的时候,默认按照子类括号中的继承顺序,优先从左往右找,继承第一个父类,然后‘一条路走到黑’(即:一直往下找,找不到相应方法,才会返回来走第二个父类);

情况2:

    如果有共同的基类(即:继承结构顶部有交集),那么子类调用父类方法的时候,首先,默认还是按照括号中的继承顺序,从左往右找,如果父类中没有,父类的父类中也没有,而子类继承的右边第二个父类方法中有相应的方法,此时即使顶部交集的基类中有相应的方法,也不会继承调用基类,而是会返回来优先继承第二个父类中的方法;如果第二个父类方法中,没有相应的方法,则会像情况1那样,继承调用基类中的方法。简单来记,就是,子类继承父类的时候,如果继承结构顶部有交集,存在共同的base基类,那么base基类中的方法,被调用的优先级最低!

补充说明:Python面向对象,继承多个父类调用的时候,永远要清楚,调用方法的self到底代指的对象是谁!当遇到特殊情况,比如,子类对象son_obj继承调用父类中的方法func1,而父类中的该方法func1又调用指定了其他的方法func2,这个时候就要注意了,此时的self还是子类的那个对象,而不是说现在调用执行了父类中的方法func1,self就变成父类的对象;因此,此时即使父类中本身就有方法func2,子类也不一定会继承,因为此时的self对象仍旧是子类的son_obj对象;而是会这样执行,子类优先查找右边的第二父类中是否有相应的方法func2,有的话继承调用,没有的话,才会继承刚才父类中本身自带的方法func2!

经典类(继承 从左往右,深度优先)

新式类(继承 从左往右,广度优先)

对于Python3中全是新式类。 

对于Python2中有新式类和经典类之分,创建类的时候如果继承了(object)那么该类就是新式类;没有继承的话,则是经典类。

这里并不矛盾,上述结论同样适用于Python2,因为,Python创建新式类需要继承(object),这就相当于结论2中多个父类的顶部,有共同的基类,这种情况下遵循广度优先(即:新式类);而对于经典类,继承多个父类的顶部并没有交集,那么这个时候,就是一条路走到黑,深度优先。

结论:Python3虽然都是新式类了,继承的算法是基于C#算法,但是和Python2的继承规则实际上是完全吻合的。

另外,虽然我们暂时搞明白多个继承的调用顺序了,但是,复杂的多层父类继承编程方式,是不提倡的,这样可能会降低Python代码的整体执行效率。

# 多态

可以理解成:

例如:一个类为class A(name,age):

然后实例化的时候,student1 = A('jesson',22)

student2 = A('Tim',20)

这个时候,对象实例化的时候,由于传递的参数不同,实例化之后的对象是不同的。 可样,可以简单的理解成面向对象的多态。

体现:子类可以继承父类的方法,也可以调用自己的方法。

多态:http://www.cnblogs.com/hai-ping/articles/2807750.html

												




											

Python 面向对象 基础的更多相关文章

  1. python面向对象基础

    面向对象基础 1. 简述 编程方式: 面向过程: 根据代码在脚本的堆叠顺序,从上到下依次执行 函数式编程:将相同功能的代码封装到函数中,直接调用即可,减少代码重复性 面向对象:对函数进行分类和封装,将 ...

  2. Python 面向对象基础知识

    面向对象基础知识 1.什么是面向对象编程? - 以前使用函数 - 类 + 对象 2.什么是类什么是对象,又有什么关系? class 类: def 函数1(): pass def 函数2(): pass ...

  3. python 面向对象基础和高级复习

    面向对象基础 面向对象编程 面向过程编程:类似于工厂的流水线 优点:逻辑清晰 缺点:扩展性差 面向对象编程:核心是对象二字,对象属性和方法的集合体,面向对象编程就是一堆对象交互 优点:扩展性强 缺点: ...

  4. 十六、python面向对象基础篇

    面向对象基础: 在了解面向对象之前,先了解下变成范式: 编程范式是一类典型的编程风格,是一种方法学 编程范式决定了程序员对程序执行的看法 oop中,程序是一系列对象的相互作用 python支持多种编程 ...

  5. [python面向对象]--基础篇

    1.#类 #类就是一个模板,模板里可以包含多个函数,函数里实现一些功能 #定义一个类 class bar: def foo(self,agr): print(self,agr) obj = bar() ...

  6. Python面向对象基础:编码细节和注意事项

    在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名称空间 本篇是第4篇,用一个完整的示例来解释面向对象的一些细节. 例子的模型是父类Em ...

  7. Python面向对象基础一

    公司可能过一两个月就要从深圳搬到东莞松山湖,项目组的现在有的在转Java或其他语言的,问我们要不要转java+hoodap+spark方向,我还是先不转,毕竟之前是从ios转回C#,这现在在转其他的那 ...

  8. python面向对象基础-01

    面向对象(OOP)基本概念 前言 话说三国时期曹军于官渡大败袁绍,酒席之间,曹操诗兴大发,吟道:喝酒唱歌,人生真爽! 众将直呼:"丞相好诗",于是命印刷工匠刻板印刷以流传天下; 待 ...

  9. Python 面向对象基础

    面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机 ...

随机推荐

  1. codeforces 493A. Vasya and Football 解题报告

    题目链接:http://codeforces.com/contest/493/problem/A 题目意思:给出两个字符串,分别代表 home 和 away.然后有 t 个player,每个playe ...

  2. Node.Js之【Stream 之复制文件问题】

    var fs = require('fs'), path = require('path'), out = process.stdout; var filePath = 'F:/IMG_0221.MO ...

  3. Fedora 17 修改GRUB启动菜单顺序

    Fedora 16采用GRUB2,因此启动菜单编辑方式与以前版本有所不同 设置默认启动Windows 1. 首先找到Windows的menuentry # cat   /boot/grub2/grub ...

  4. 阅读underscore源码笔记

    本文为原创作品,可以转载,但请添加本文连接,谢谢传阅,本人博客已转移至github,地址为:jruif.github.io underscorejs,一个实用的的Javascript函数库,值得推荐, ...

  5. macOS 下配置 MAMP 开发环境(Mac + Apache + Mysql + PHP)

    macOS 中已经内置了 PHP.Python.Ruby.Perl 等常用的脚本语言,以及 Apache HTTP 服务器,所以使用起来非常方便.本文以最新的 macOS Sierra 10.12 配 ...

  6. DDD理论学习系列(9)-- 领域事件

    DDD理论学习系列--案例及目录 1. 引言 A domain event is a full-fledged part of the domain model, a representation o ...

  7. vscode调试angular

    之前在Asp.net MVC + Angular1 的项目中,要调试前台代码都是用浏览器的开发者工具,使用正常,也没有感觉太大的不方便. 后来接触Angular2项目,因为它是要经过编译的,所以在浏览 ...

  8. 基于注解方式@AspectJ的AOP

    启用对@AspectJ的支持 Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置: <aop:aspectj-autoproxy/> 这样Spring就能发现@ ...

  9. Linux性能监控(程序篇)

    性能数据的监控,除了针对整机进行外,还要求我们对某一运行的程序单独进行.常用的程序监控命令有ps和top. Ps ps命令最常用的还是用于监控后台进程的工作情况,因为后台进程是不和屏幕键盘这些标准输入 ...

  10. git之GitHub Pages

    git之GitHub Pages GitHub Pages是github的一项很实用的功能,它可以让我们将github里面的静态网站的代码在线上展示出来,可以用来做项目展示和个人博客的载体.  1.将 ...