简介

与java语言一样,python也属于面向对象编程,除此之外,还有面向过程编程、函数式编程。

  • 面向过程编程:依据业务逻辑自上而下一步一步编写, 可能会存在冗余现象
  • 函数式编程:需要编程语言可以将方法或函数作为返回值,python支持函数式编程,但java就不支持,编写函数,然后在使用时调用即可
  • 面向对象编程:将函数进行分类、封装,由不同对象进行调用触发,使得代码便于扩展与编写,减少代码重复

什么是面向对象编程呢?

面向对象是一种编程方式,主要通过对象实现,

类相当于是一个模板,里面提供了很多函数实现功能
对象就是模板中实例化后生成的对象,调用模板中的函数实现相应操作

所以整体的逻辑就是通过类创建对象->对象调用类中的方法

面向对象的三大特性

面向对象有三大特性:封装、继承、多态。

封装

将内容封装到一个函数中,提供给对外调用,调用者只需要调用实现相应功能,而无需知道内部实现逻辑。示例如下:

class Person:
def __init__(self, name, age) -> None:
self.name = name
self.age = age def run(self):
print(f"{self.name} run") def eat(self):
print(f"{self.name} eat") def sleep(self):
print(f"{self.name} sleep") p1 = Person("tom", 19)
p2 = Person("mike", 20)
p1.eat()
p2.eat()
p1.run()
p2.run()
tom eat
mike eat
tom run
mike run

人可以吃饭、睡觉、跑步,将这三个动作分别封装成三个方法,并使用构造方法创建对应的对象,对象直接调用类中的公开方法,当对象实例化后,相当于self变成了对象。

综上,封装就是使用构造方法创建对象后,对象直接或间接使用self调用类中的公开方法进行操作(获取封装的内容)。

继承

面向对象中的继承与实际生活中的继承是类似的,子类可以继承父类,并使用父类中的属性或者方法,示例如下:

class Animal:
def __init__(self, name) -> None:
self.name = name def run(self):
print(f"{self.name} run") def eat(self):
print(f"{self.name} eat") def sleep(self):
print(f"{self.name} sleep") class Person(Animal):
def __init__(self, name, age) -> None:
super().__init__(name)
self.age = age def read(self):
print(f"{self.name} read: age:{self.age}") p1 = Person("tom", 19)
p2 = Person("mike", 20)
p1.eat()
p2.eat()
p1.run()
p2.run()
p1.read()
p2.read()
tom eat
mike eat
tom run
mike run
tom read: age:19
mike read: age:20

每种动物都有吃饭、睡觉、跑步,可以将此类具有这三个行为的事物提取成一个公共的类,然后Person直接继承动物类,这样Person也可以调用动物类中的方法,也可以实现新的方法,避免了代码的冗余。

综上,继承就是将多个相同属性或者动作的对象的行为提取到一个公共类中,不同对象可以继承公共类而不需要实现每一个方法,并且可以实现新的方法。

那么既然有继承,涉及到多重继承和多继承。

多重继承

多重继承:子类继承父类,父类继承父类的父类,以此类推,子->父->爷

大部分编程语言都支持多重继承,此处以python为例:

class Animal:
def __init__(self, name) -> None:
self.name = name def run(self):
print(f"{self.name} run") def eat(self):
print(f"{self.name} eat") def sleep(self):
print(f"{self.name} sleep") class Person(Animal):
def __init__(self, name, age) -> None:
super().__init__(name)
self.age = age def read(self):
print(f"{self.name} read: age:{self.age}") class Child(Person):
def __init__(self, name, age) -> None:
super().__init__(name, age) def climb(self):
print(f"{self.name}: climb") p1 = Child("tom", 2)
p2 = Child("mike", 4)
p1.eat()
p2.eat()
p1.run()
p2.run()
p1.climb()
p2.climb()
tom eat
mike eat
tom run
mike run
tom: climb
mike: climb

上述,小孩继承人类,人类继承动物,形成了多重继承,自上而下的一层一层的,下一层级可以调用上一级的方法,即子类可以调用父类的属性或方法,父类不可以调用子类的属性或方法。

多重继承一般适用于存在多重类别的区分的情况,很多模块的源码中就是使用的多重继承。

多继承

顾名思义:多继承就是一个子类可以有多个父类。

python支持多继承,java、c等不支持多继承,示例如下

class Animal:
def __init__(self, name) -> None:
self.name = name def run(self):
print(f"Animal {self.name} run") def eat(self):
print(f"Animal {self.name} eat") def sleep(self):
print(f"Animal {self.name} sleep") class Person:
def __init__(self, name) -> None:
self.name = name def run(self):
print(f"Person {self.name} run") def eat(self):
print(f"Person {self.name} eat") def sleep(self):
print(f"Person {self.name} sleep") def thinking(self):
print(f"Person {self.name} thinking") class Child(Person, Animal):
def __init__(self, name) -> None:
super().__init__(name) def climb(self):
print(f"{self.name}: climb") p1 = Child("tom")
p2 = Child("mike")
p1.eat()
p2.eat()
p1.run()
p2.run()
p1.climb()
p2.climb()
p1.thinking()
p2.thinking()
Person tom eat
Person mike eat
Person tom run
Person mike run
tom: climb
mike: climb
Person tom thinking
Person mike thinking

小孩继承了Person,也继承了Animal,但是在调用父类相同方法时,调用了Person的方法,调用父类不存在的方法时,则调用子类自己的方法。

多继承过程中,子类在调用父类中同名的方法时,会按照继承的先后顺序来调用,从前到后依次查找直至找到为止。

继承过程中的深度优先与广度优先

python2中, 继承中的深度优先与广度优先一般出现在不同的类创建方式中,分别为经典类和新式类。

经典类

本类和父类未继承object类实现的类。

class D:
def run(self):
print("D.run") class C(D):
def run(self):
print("C.run") class B(D):
def run3(self):
print("B.run") class A(B, C):
def run2(self):
print("A.run") A().run()

python2

D.run

python3

C.run

新式类

本类或父类继承object类的类

class D(object):
def run(self):
print("D.run") class C(D):
def run(self):
print("C.run") class B(D):
def run3(self):
print("B.run") class A(B, C):
def run2(self):
print("A.run") A().run()

python2、python3

C.run

由上述结果可得出以下结论:

  • 在python2中,经典类调用run方法时,查找顺序为A -> B -> D -> C,属于深度优先,新式类调用run方法时,查找顺序为A -> B -> C -> D,属于广度优先。
  • 在python3中,无论是经典类还是新式类,都是广度优先

继承过程中,子类如何调用父类的方法或者属性呢?

使用super()来调用父类的方法

多态

python 不支持多态,也不用支持多态,崇尚鸭子类型

鸭子类型

在python中,有这么一个类型,一只鸟长的像鸭子,会游泳,就叫它鸭子,即鸭子类型。此类型的目的在于关于对象的使用(如何调用),而非关注对象的类型

总结

面向对象编程就是将对象中的共性提取成一个个方法或者属性,方便对象调用,减少了代码的冗余,提升了模块化能力,方便扩展。

参考

面向对象基础篇

python 面向对象理解的更多相关文章

  1. Python 面向对象 基础

    编程范式概述:面向过程 和 面向对象 以及函数式编程 面向过程:(Procedure Oriented)是一种以事件为中心的编程思想. 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现 ...

  2. python 面向对象编程学习

    1. 问题:将所有代码放入一个py文件:无法维护 方案:如果将代码才分放到多个py文件,好处: 1. 同一个名字的变量互相不影响 2.易于维护 3.引用模块: import module 2.包:解决 ...

  3. python 面向对象学习

    ------Python面向对象初 下面写一个类的简单实用,以便方便理解类 #python 3.5环境,解释器在linux需要改变 #阅读手册查询readme文件 #作者:S12-陈金彭 class ...

  4. python 面向对象、特殊方法与多范式、对象的属性及与其他语言的差异

    1.python 面向对象 文章内容摘自:http://www.cnblogs.com/vamei/archive/2012/06/02/2532018.html   1.__init__() 创建对 ...

  5. python 面向对象编程(一)

    一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class c ...

  6. Python 面向对象之一

    Python 面向对象之 类与属性 今天接触了一下面向对象,发现面向对象和之前理解的简直就是天壤之别,在学Linux的时候,一切皆文件,现在学面向对象了,so,一切皆对象. 之前不是一直在学的用面向函 ...

  7. Python面向对象篇之元类,附Django Model核心原理

    关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ...

  8. #5 Python面向对象(四)

    前言 本节将是Python面向对象的最后一篇博文了,这节将记录类的特殊方法.特殊成员方法.旧类和新类的不同,以及一些其他知识.Go! 一.类的特殊方法 Python有三种特殊方法:实例方法.静态方法. ...

  9. #4 Python面向对象(三)

    前言 前两节讲解了Python面向对象的思想和Python类中各种变量的含义以及区别.肯定有小伙伴会问,类初始化时是否可以传入参数?如果有多个类中含有共同的函数方法,是否可以重复利用?本节就带着这些问 ...

随机推荐

  1. 【mq】从零开始实现 mq-07-负载均衡 load balance

    前景回顾 [mq]从零开始实现 mq-01-生产者.消费者启动 [mq]从零开始实现 mq-02-如何实现生产者调用消费者? [mq]从零开始实现 mq-03-引入 broker 中间人 [mq]从零 ...

  2. 面试简历书写、Flask框架介绍与快速使用、Flask演示登录页面、用户信息页面案例

    今日内容概要 面试简历编写 Flask框架介绍与安装 内容详细 1.面试简历编写 # 千万不要几个小时把简历凑出来 几天到一周 # 有没有面试机会,取决于简历写得怎么样 简历写好是第一步 # 投简历的 ...

  3. 【mq】从零开始实现 mq-13-注册鉴权 auth

    前景回顾 [mq]从零开始实现 mq-01-生产者.消费者启动 [mq]从零开始实现 mq-02-如何实现生产者调用消费者? [mq]从零开始实现 mq-03-引入 broker 中间人 [mq]从零 ...

  4. 【多线程】线程同步 synchronized

    由于同一进程的多个线程共享同一块存储空间 , 在带来方便的同时,也带来了访问 冲突问题 , 为了保证数据在方法中被访问时的正确性 , 在访问时加入 锁机制synchronized , 当一个线程获得对 ...

  5. linux篇-linux命令大全

    Linux常用命令大全(非常全!!!) 最近都在和Linux打交道,感觉还不错.我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因,比较短 ...

  6. Java线程池ThreadPoolExecutor极简教程

    ThreadPoolExecutor 简介 ThreadPoolExecutor 是 java.util.concurrent 包下的一个类,在jdk1.5版本引入,帮助开发人员管理线程并方便地执行并 ...

  7. C# 蓄水池抽样

    蓄水池采样算法解决的是在给定但长度未知的大数据集中,随机等概率抽取一个数据.如果知道数据的长度,可以用随机数rand()%n得到一个确切的随机位置,或者分块取值来构造随机,那么该位置的对象就是所求的对 ...

  8. boost::bind 不能处理函数重载 (error: no matching function for call to 'bind')

    前言 最近任务多.工期紧,没有时间更新博客,就水一期吧.虽然是水,也不能太失水准,刚好最近工作中遇到一个 boost::bind 的问题,花费了半天时间来定位解决,就说说它吧. 问题背景 项目中使用了 ...

  9. Vben Admin 源码学习:项目初始化

    0x00 前言 Vue-Vben-Admin 是一个免费开源的中后台模版.使用了最新的vue3,vite2,TypeScript等主流技术开发,开箱即用的中后台前端解决方案考. 本系列本着学习参考的目 ...

  10. 如何用HMS Core位置和地图服务实现附近地点路径规划功能

    日常出行中,路径规划是很重要的部分.用户想要去往某个地点,获取到该地点的所有路径,再根据预估出行时间自行选择合适的路线,极大方便出行.平时生活中也存在大量使用场景,在出行类App中,根据乘客的目的地可 ...