如何吃透Python的面向对象(OOP)
本篇可乐和大家一起来吃透 Python 的面向对象,类和实例。
面向对象(OOP)
解释:面向对象它是一种编程的思想,将现实事物抽象化为编程对象。
举例说明:喝可乐
① 选择自己根据配方买对应的材料然后制作可乐,最后喝可乐。
② 自己去小卖部直接买可乐喝。
第一种属于面向过程(对应到编程当中,也就是每一个步骤都需要一步一步实现)
第二种就是面向对象,我们并不需要知道每一步是如何实现的,只需要知道最后能够喝可乐即可。
一、类
解释:类是面向对象的重要组成部分,类是对相同特征和行为事物的统称,是一个抽象的概念。
语法
class 类名:
实际代码
举例:以人为例子
# 人有眼睛,鼻子,嘴巴这些特征。可以玩电脑,走路这些行为。
# 代码如下:
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print("我会玩电脑")
def walk(self):
print("我会走路")
# self:下面会细讲,并用代码演示
二、对象
解释:对象是类创建出来真实存在的事物,对象又可以称为实例。
语法
对象名 = 类名()
举例:以上述人为例子
人是一个抽象的概念,并不能代表实实在在的事物,但是可乐和在座的各位同学都是实际存在的事物,我们都属于人。
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print("我会玩电脑")
def walk(self):
print("我会走路")
# 创建 kele 对象
kele = Person()
2.1 调用对象方法
语法
对象.方法名(参数)
举例
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print("我会玩电脑")
def walk(self):
print("我会走路")
# 创建 kele 对象
kele = Person()
kele.play_computer()
# 输出 我会玩电脑
解释实例方法中的 self 是什么
先上代码
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print("我会玩电脑")
def eye(self):
print(self.eyes)
self.eyes = "卡兹然大眼睛"
print(self.eyes)
kele = Person()
kele.eye()
# 输出结果是 眼睛 卡兹然大眼睛
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print("我会玩电脑")
def eye(self):
pass
kele = Person()
print(kele.eyes)
kele.eyes = "卡兹然大眼睛"
print(kele.eyes)
# 输出 眼睛 卡兹然大眼睛
到这里可能有一部分同学已经明白 self 实际上是个什么东东了,为了更加通俗易懂,可乐再举一个例子:
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print(f"self是{self}")
kele = Person()
kele.play_computer()
print(f"kele是{kele}")
结果:
根据上述两个示例,我们可以知道 self 实际上就是类创建出来的实例对象。
对象在调用方法的时候不需要手动传 self 值,因为 python 解释器会自动将实例引用传递给 self 。
2.2 获取对象属性
解释:属性就是特征。例如:人的手,人的鼻子,人的身高,人的体重。
语法
① 对象名.属性名 (这种在类外部使用)
② self.属性名 (这种在类内部使用)
举例1:还是以人为例子
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print(f"self是{self}")
kele = Person()
print(kele.nose)
# 输出 鼻子
举例2
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def get_nose(self):
print(self.nose)
kele = Person()
kele.get_nose()
# 输出 鼻子
2.3 修改/设置对象属性
语法
① 对象名.属性名 = 值 (这种在类外部使用)
② self.属性名 = 值 (这种在类内部使用)
举例1:依旧以人为例子
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def play_computer(self):
print(f"self是{self}")
kele = Person()
kele.nose = "卡兹然大鼻子"
print(kele.nose)
# 输出 卡兹然大鼻子
举例2
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
def modify_nose(self):
self.nose = "卡兹然大鼻子"
kele = Person()
kele.modify_nose()
print(kele.nose)
# 输出 卡兹然大鼻子
2.4 魔法方法
解释:所谓的魔法方法也就是 python 内部已经提供的方法,他们的表现形式是 xxx 。
2.4.1 魔法方法 init
解释 init 方法它是用于对象生成之后进行初始化的函数,不需要程序员手动调用,python 解释器会在对象创建之后自动调用。
例如:人与生俱来就有嘴巴,鼻子,眼睛。那么我们在构造类的时候,就可以将这些属性放进 init 方法中。
举例
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
print(self.eyes)
kele = Person()
# 输出 眼睛
他并不需要程序员手动调用。
2.4.2 魔法方法 new
解释:我们之前一直在说对象是由类创建出来的,那么类又是怎么创建出来的呢?就是通过 new 方法,这个方法的功能就是创建对象。
如何通过 new 方法实现单例
解释:所谓的单例就是一个类创建出来的对象都是相同的。
在默认情况下类创建出来的各个对象都是不一样的,如果我们想一个类创建出来的对象都是一样的,那该怎么做呢?答案就是通过 new 方法。
类创建不同的对象代码
class Person:
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
kele1 = Person()
kele2 = Person()
print(kele1)
print(kele2)
结果如图:
单例代码
class Person:
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = super(Person, cls).__new__(cls, *args, **kwargs)
return cls.instance
def __init__(self):
self.eyes = "眼睛"
self.nose = "鼻子"
self.mouth = "嘴巴"
kele1 = Person()
kele2 = Person()
print(kele1)
print(kele2)
先贴出结果:
解释一下代码:
具体代码在下面讲解完继承,类属性,类方法之后就知道什么含义了,可乐先讲一下代码的大致意思:用变量 instance 存储对象的内存地址,开始时只为 None ,当第一个对象创建之后,将该内存地址赋值给 instance 变量,后续的对象创建时判断变量 instance 是否有值了。如果有,那么将之前的对象地址给新对象。这样就保证了,后续的对象都和第一个对象的内存地址一样,即该类创建出来的对象都是同一个。
2.5 类属性
解释:类对象所拥有的属性,该类创建出来的所有对象共享同一个类属性,类属性在内存中只会有一个副本。
使用场景
如果在一个类中所有的对象都有一个共同的属性,并且这个属性的值是一样的,那么我们就可以将属性设置为类属性,如果这个属性的值每个对象都有其自己的含义,那么我们可以将其定义为实例属性。
语法
在类里面 属性名 = 值
举例
class Person:
nose = "鼻子"
def __init__(self, name):
self.name = name
kele1 = Person("可乐1号")
kele2 = Person("可乐2号")
2.5.1 获取类属性
语法
① cls.属性名 (在类里面)
② 类.属性名 (在类外面)
③ 实例.属性名 (在类外面)
举例
class Person:
nose = "鼻子"
kele = Person()
print(kele.nose)
print(Person.nose)
# 输出 鼻子 鼻子
2.5.2 修改类属性的值
语法
① cls.属性名 = 值 (在类里面)
② 类.属性名 = 值 (在类外面)
不可用实例.属性名 = 值来修改,这个含义代表添加实例属性。
举例
class Person:
nose = "鼻子"
Person.nose = "卡自然大鼻子"
print(Person.nose)
# 输出 卡自然大鼻子
2.6 类方法
解释:类方法是类对象所拥有的方法,用 @classmethod 来对方法进行修饰。
使用场景
类方法一般搭配类属性来使用,常常用于对类属性的修改。
语法
@classmethod
def 类方法名(cls):
举例
class Person:
nose = "鼻子"
@classmethod
def add(cls):
pass
2.6.1 调用类方法
语法
① 类.类方法名 (在类外面)
② 实例.类方法名 (在类外面)
③ cls.类方法名 (在类里面)
举例1
class Person:
nose = "鼻子"
@classmethod
def add(cls, nose):
cls.nose = nose
@classmethod
def update(cls):
cls.add("卡自然大鼻子")
Person.update()
print(Person.nose)
# 输出 卡自然大鼻子
举例2
class Person:
nose = "鼻子"
@classmethod
def update(cls):
cls.nose = "卡自然大鼻子"
Person.update()
print(Person.nose)
# 输出 卡自然大鼻子
举例3
class Person:
nose = "鼻子"
@classmethod
def update(cls):
cls.nose = "卡自然大鼻子"
kele = Person()
kele.update()
print(kele.nose)
# 输出 卡自然大鼻子
2.7 静态方法
解释:静态方法可以理解为就是普通的函数,只不过他的作用域限制于类里面,但是和类和实例本身并没有多大的关系,他通过 @staticmethod 来修饰。
使用场景
如果想定义一个函数,但是该函数和类本身或者实例对象没有多大关系,但是限制于该类中就可以使用静态方法来定义。
举例
class Person:
@staticmethod
def play_game():
print("可乐打游戏")
kele = Person()
kele.play_game()
# 输出 可乐打游戏
三、面向对象三大特性
特性:封装,继承,多态。
3.1 封装
解释:将代码写到类里面即是封装,并且封装还可以给属性或者方法设置权限。在上述代码中已经使用了封装的特性。
3.2 继承
解释:指的是类当中的从属关系,子类自动拥有父类所有的属性和方法。
所有的类都默认继承Object类。
3.2.1 单继承
单继承:只继承一个父类。
举例
class Father:
def __init__(self):
self.name = "可乐家族"
def get_name(self):
print(self.name)
class Son(Father):
pass
son = Son()
son.get_name()
# 输出 可乐家族
3.2.2 多继承
多继承:子类同时继承多个父类。
举例1
class Father:
def __init__(self):
self.name = "可乐家族"
def get_name(self):
print(self.name)
class Mother:
def __init__(self):
self.name = "妈妈家族"
def get_name(self):
print(self.name)
def add_nose(self):
self.nose = "鼻子"
class Son(Mother, Father):
pass
son = Son()
son.get_name()
# 输出 妈妈家族
举例2
class Father:
def __init__(self):
self.name = "可乐家族"
def get_name(self):
print(self.name)
class Mother:
def __init__(self):
self.name = "妈妈家族"
def get_name(self):
print(self.name)
def add_nose(self):
self.nose = "鼻子"
class Son(Father, Mother):
pass
son = Son()
son.get_name()
# 输出 可乐家族
如果继承的父类当中拥有相同的属性或者方法,那么优先继承第一个父类的属性和方法。
3.2.3 mro确认继承顺序
继承顺序:如果一个类继承多个父类,并且继承关系比较复杂,那么我们可以使用内置方法 mro 来确定继承顺序。
举例
class Father:
def __init__(self):
self.name = "可乐家族"
def get_name(self):
print(self.name)
class Mother:
def __init__(self):
self.name = "妈妈家族"
def get_name(self):
print(self.name)
def add_nose(self):
self.nose = "鼻子"
class Son(Mother, Father):
pass
print(Son.__mro__)
结果如图:
3.2.4 重写父类的方法
继承中,支持子类对父类的方法进行重写。
举例
class Father:
def __init__(self):
self.name = "可乐家族"
def get_name(self):
print(self.name)
class Mother:
def __init__(self):
self.name = "妈妈家族"
def get_name(self):
print(self.name)
def add_nose(self):
self.nose = "鼻子"
class Son(Mother, Father):
def get_name(self):
print("子类重新方法")
son = Son()
son.get_name()
# 输出 子类重新方法
3.2.5 继承之super
super:子类重写父类方法,但是还需要调用父类的其他方法或同名方法时,使用 super 可以不用关心继承的是哪个父类,在语法上只需要填写子类类名即可。
举例1
class Father:
def __init__(self):
self.name = "可乐家族"
def get_name(self):
print(self.name)
class Mother:
def __init__(self):
self.name = "妈妈家族"
def get_name(self):
print(self.name)
def add_nose(self):
self.nose = "鼻子"
class Son(Mother, Father):
def get_name(self):
print("子类重新方法")
Mother.get_name(self)
Father.__init__(self)
Father.get_name(self)
son = Son()
son.get_name()
# 输出 子类重新方法 妈妈家族 可乐家族
举例2
class Father:
def __init__(self):
self.name = "可乐家族"
def get_name(self):
print(self.name)
class Mother:
def __init__(self):
self.name = "妈妈家族"
def get_name(self):
print(self.name)
super(Mother, self).__init__()
super(Mother, self).get_name()
def add_nose(self):
self.nose = "鼻子"
class Son(Mother, Father):
def get_name(self):
print("子类重新方法")
super(Son, self).get_name()
son = Son()
son.get_name()
# 输出 子类重新方法 妈妈家族 可乐家族
super 会自动查找父类,且顺序遵循__mro__顺序,适合单继承使用;
super 只能继承最近的上一级父类,顺序按照__mro__顺序。
3.3 多态
解释:不同的对象,有不同的结果,子类重写父类的方法,并且调用不同的子类的相同父类方法,有不同的结果。
我们先上代码来看:
class Person:
def get_sex(self):
print("人")
class Man(Person):
def get_sex(self):
print("男人")
class Women(Person):
def get_sex(self):
print("女人")
man = Man()
women = Women()
man.get_sex()
women.get_sex()
# 输出 男人 女人
代码解释:
一个 Person 类中有一个父类公共方法 get_sex ,子类 man 和 women 通过重写父类方法,产生不同的效果,这就是多态。那么多态有什么好处呢?多态可以使得代码变得更加灵活,更通用,适应的业务场景多。
到此,我们在本篇中学习了 python 面向对象。各位同学在学习过程中遇到疑问可以私聊可乐,可乐看到了都会一一回复的。那么下一篇可乐将和大家看一下闭包,装饰器和深拷贝,浅拷贝。谢谢大家的支持~~~
< END>
如何吃透Python的面向对象(OOP)的更多相关文章
- [Python_4] Python 面向对象(OOP)
0. 说明 Python 面向对象(OOP) 笔记.迭代磁盘文件.析构函数.内置方法.多重继承.异常处理 参考 Python面向对象 1. 面向对象 # -*-coding:utf-8-*- &quo ...
- python基础----面向对象的程序设计(五个阶段、对小白的忠告、关于OOP常用术语)、类、对象
一.面向对象的软件开发有如下几个阶段 1.面向对象分析(object oriented analysis ,O ...
- Python面向对象OOP
一 OOP 与C++和Java一样,Python同样具有OOP设计. 过程式:从前到后,一条一条,机器能接受的顺序性方式:方式大概为"首先你应该做什么,第二应该做什么,高级点的做点假 ...
- python基础——面向对象编程
python基础——面向对象编程 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的 ...
- python学习------面向对象的程序设计
一 面向对象的程序设计的由来 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据.简单来说,就是直接编写 和 的序列来代表程序语言 ...
- 【转】Python之面向对象与类
[转]Python之面向对象与类 本节内容 面向对象的概念 类的封装 类的继承 类的多态 静态方法.类方法 和 属性方法 类的特殊成员方法 继承层级关系中子类的实例对象对属性的查找顺序问题 一.面向对 ...
- what's the python之面向对象
编程分为面向过程和面向对象,首先我们要了解什么是面向对象. 面向对象 面向过程就是我们之前学的内容,主要是函数式,其核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全 ...
- Python之面向对象类和对象
Python之面向对象类和对象 定义一个类:class 定义类的语法: class Test(object): """ 类里定义一类事物共同的技能. 可以是变量,也可是函 ...
- python初始面向对象
阅读目录 楔子 面向过程vs面向对象 初识面向对象 类的相关知识 对象的相关知识 对象之间的交互 类命名空间与对象.实例的命名空间 类的组合用法 初识面向对象小结 面向对象的三大特性 继承 多态 封装 ...
随机推荐
- python中如何添加模块导入路径?
python中自定义模块导入路径的方式主要有以下3种: (1)使用sys.path.append() 随着程序执行,会动态地添加模块导入的路径,但是程序执行结束后就会立即失效(临时性的) import ...
- MySQL的安装、改密及远程连接
一.下载MySQL压缩包后的安装步骤 将压缩包解压到指定的目录 编辑好配置文件 [mysql] #设置MySQL客户端默认字符集 default-character-set=utf8 [mysqld] ...
- [WPF 学习] 18. 摄像头(肢解DirectShow)
公司的产品需要人脸比对,摄像头相关的需求如下(突然发现除了英文不太好外,实际上中文也不太好,所以直接上一个接口) using System; using System.Drawing; using S ...
- fzu2200 cleaning
Problem Description N个人围成一圈在讨论大扫除的事情,需要选出K个人.但是每个人与他距离为2的人存在矛盾,所以这K个人中任意两个人的距离不能为2,他们想知道共有多少种方法. In ...
- Codeforces #624 div3 C
You want to perform the combo on your opponent in one popular fighting game. The combo is the string ...
- Codeforces Round #658 (Div. 2) D. Unmerge (思维,01背包)
题意:有两个数组\(a\)和\(b\),每次比较它们最左端的元素,取小的加入新的数组\(c\),若\(a\)或\(b\)其中一个为空,则将另一个全部加入\(c\),现在给你一个长度为\(2n\)的数组 ...
- CF1474-A. Puzzle From the Future
CF1474-A. Puzzle From the Future 题意: 有两个由\(0,1\)组成的.长度相等字符串\(a, b\),两个字符串按位相加得到一个新的字符串\(s\),对\(s\)取\ ...
- 力扣992.K个不同整数的子数组-C语言实现
题目 原题链接 给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续.不一定独立的子数组为好子数组. (例如,[1,2,3,1,2] 中有 3 个不同的整数: ...
- ssh原理及加密传输
1.ssh??(保证过程中是加密的,即安全的)ssh 是 Secure Shell 的缩写,是一个建立在应用层上的安全远程管理协议.ssh 是目前较为可靠的传输协议,专为远程登录会话和其他网络服务提供 ...
- k8s二进制部署 - node节点安装
创建kubelet配置 • set-cluster # 创建需要连接的集群信息,可以创建多个k8s集群信息 [root@hdss7-21 ~]# kubectl config set-cluster ...