Python面向对象编程之封装的艺术你了解吗

目录
  • 1.面向对象编程
    • 1.1OOP特点
    • 1.2OOP基本概念
  • 2.Python实现OOP
    • 2.1分析问题
    • 2.2类设计语法
    • 2.3创建对象语法
  • 3.OOP的封装性
    • 3.1广义角度:无处不封装
      • 封装的优点!
    • 3.2狭义角度:保证内部数据的完整性
      • 实施流程:
  • 4.总结

1. 面向对象编程

OOP ( Object Oriented Programming) 即面向对象编程。

面向对象编程是一种 编码思想 ,或是一种 代码组织方式 。如同编辑文章时,可以选择 分段、分节 的方式让文章看起来有层次、更方便阅读或修改。

编码时可以选择使用 OOP 方案,也可以选择不使用。如同行文一样,使用或不使用都不会对 核心逻辑 产生影响。

面向对象编程有自己的核心编码理论,对于任何一种计算机语言而言,如果选择支持此理论, 则称此计算机语言支持面向对象编程 。如 C++、Java、Python……

因每一种计算机语言语法上的差异性,在提供 OOP 实现时的 语法规范 会有很大的区别。除此之外,对于每一种语言而言,也可以在 OOP 基础理论上进行语法扩展或限制。如 Python 支持多继承。而 Java 语言只支持单根继承……

1.1 OOP 特点

要了解 OOP 的特点,可从 2 个角度进行阐述。

广义角度:让程序像人类解决问题一样去解决问题,让程序具有人的思维模式。

人类解决问题时,先是要了解问题域中会涉及到 哪些对象 ,然后再深入了解 每一个对象的特性或功能, 最后再做出相应的决策。

比如:为班级选一名班长。

选班长就是现实世界的一个问题域,如何才能选择一名符合要求的班长?

1.首先确定此问题中涉及的对象(此处便是班上的所有学生)。

2.然后了解每一个学生的兴趣、爱好、性格……以及个人能力等等。

3.从了解的群体中匹配一个符合 班长标准 的学生便可。

面向对象编程中的 对象一词 ,便是借鉴了现实世界中对象概念。

狭义角度:OOP 编码为整个程序维护带来的优势

OOP 组织的代码可让程序整体上有高度的可阅读性,除此之外,最主要的特点是可提高代码的 复用性、安全性、可扩展性。

任何事情都会 2 面性,OOP 会增加代码的理解难度。

1.2 OOP 基本概念

OOP 中有两个很重要的概念, 类和对象 。

对象从何而来?

现实世界中我们很少思考这个问题,在 选班长时 ,不会思考学生是从哪里来的,即使思考这个问题,也会认为那是哲学家的事情。

我们不思考现实世界中的手机、电脑、电视机是怎么来的……因为我们不关心这个,我们关心的是使用它们所提供的功能。

如果我们思考一下手机是怎么出现的,则会发现:

1.首先需要工程师设计手机蓝图。

2.在工厂里根据手机蓝图进行生产(可能生产很多)。

3.用户购买手机,了解手机特性和功能,使用手机。

我们身边的诸如 电视机、洗衣机、电脑……

无不例外的需要经过这几个过程后方能来到我们的世界。

即使是人也是女娲按自己的样子创建出来的……

同理,电脑世界里不会突然冒出手机、电脑、学生……如何才能让电脑出现此类对象。一样,先设计一个蓝图,此蓝图在电脑世界我们就称其为 “类” 。

有了 “类” 之后才可以 创建手机对象 ,有了对象后才能在程序代码中使用设计时为手机赋予功能完成程序逻辑。

现实世界设计手机蓝图时,需要设计手机的外观,如大小、形状、体重……需要赋予手机功能、如打电话、播放音乐、播放视频、上网……

在计算机的编码世界里,同样在设计类时需要为 “手机类” 设计外观和功能。 OPP 中称外观为属性,称功能为方法。

类是蓝图,具有抽象性特征

对象是根据蓝图创建出来的个体,具有具体性、实用性特征

2. Python 实现 OOP

如需使用 OOP 理念实现程序逻辑,则需遵循如下流程:

2.1 分析问题

首先需要明确问题: 如编写一个程序摸拟小狗的行为。

此问题中的对象便是小狗,所以程序中需要一只小狗。

按上所述,创建小狗之前需要设计“狗类”,因此需要为类的设计提供足够的信息。

分析可得在设计类时需要有小狗属性:姓名、年龄,小狗的行为:尊下、打滚。

2.2 类设计语法

class Dog():
    def __init__(self, name, age):
        """初始化属性name和age"""
        self.name = name
        self.age = age
    def sit(self):
        """小狗蹲下行为"""
        print(self.name.title() + " 乖乖的尊下了!")
    def roll_over(self):
        """小狗打滚"""
        print(self.name.title() + " 开始打滚哈!")

如上为 python 中类设计的结构语法:

  • 类的函数称为方法,方法的第一个参数须是 self 关键字。
  • __init__ 方法是必须的,其方法名不得修改。 此方法会在创建对象时被自动调用,用来初始化对象数据。
  • self.name 声明一个对象变量,此变量会保存对象的数据。

2.3 创建对象语法

有了类后,方可创建对象,有了对象后方可激活属性和方法。

my_dog = Dog('小雪', 6) print("小狗的名字:"+my_dog.name.title()+".") print("小狗今年"+str(my_dog.age)+" 岁了")
my_dog.sit() my_dog.roll_over()

创建小狗时,需调用和 类名相同的方法 ,如上述的 Dog( ) 方法,此方法也叫 构造方法 ,此方法实质是调用了类设计中的 __init__ 方法。所以需要传递小狗的具体姓名和年龄初始 name 和 age 变量。

调用类中的方法时,不需要为方法声明时的 self 参数传递值。

有了对象后,如需要使用此对象的数据时,可使用 . 运算符。如上 my_dog.name 得到小狗的姓名。

当然,在创建小狗后,也可以根据需要 修改小狗的姓名和年龄。

my_dog.name='小花'
my_dog.age=4

同样,也可以使用 . 运算符调用类设计时的方法。调用方法也不需要为第一个参数 self 传值。

运行结果:

小狗的名字:小雪.
小狗今年6 岁了
小雪 乖乖的尊下了!
小雪 开始打滚哈!

有了类之后,可以根据此类的设计方案,创建出多个对象。每一个对象有自己的数据空间,彼此之间的数据是独立且隔离的。

my_dog = Dog('小黑', 6)
your_dog = Dog('小白', 3)
print("我的小狗的名字: "+my_dog.name.title()+".")
print("我的小狗的年龄 "+str(my_dog.age)+"岁了.")
my_dog.sit()
print("\n你的小狗的名字: "+your_dog.name.title()+".")
print("你的小狗的年龄 "+str(your_dog.age)+" 岁了.")
your_dog.sit()

如同现实世界一样。现在有了 2 只小狗,它们是独立的个体。修改其中一只狗的名字,对另一只小狗是没影响的。

我的小狗的名字: 小黑.
我的小狗的年龄 6岁了.
小黑 乖乖的尊下了!
 
你的小狗的名字: 小白.
你的小狗的年龄 3 岁了.
小白 乖乖的尊下了!

3. OOP 的封装性

封装性可以从 2 个角度上展开讨论:

3.1 广义角度:无处不封装

类就是一个封装体:它把 数据 以及对 数据的相关操作 方法封装在了一起。

方法也是一个封装体: 封装了代码逻辑 。

封装的优点!

当我们通过对象使用 数据和方法 时,不需要了解其中的内部细节,如此实现了 设计和使用 的分离,和现实世界中我们使用手机一样,不需了解手机的内部结构和细节。

开发者在使用 python 提供的模块时,不需要了解模块中的相关实现细节,直接使用其功能便可。

设计和使用的分离能加速工业软件的开发效率。

3.2 狭义角度:保证内部数据的完整性

创建一只小狗后,可以编写如下代码修改小狗的年龄。

my_dog = Dog('小雪', 6)
my_dog.age=-4

显然这是不符合实际情况的,没有一只小狗的年龄可以是负 4 岁。但是,现在程序可以正常运行。

小狗今年-4 岁了

出现这样不合常理的想象,应该追究谁的责任。 类的设计者还是对象使用者?

我们应该要追究类设计者的责任,就如同我刚买的手机不能充电一样,是设计者的设计缺陷引起的。

我们应该在设计类的时候提供一种内部安全检查机制,保护 变量 能被赋予一个正确的、可靠的值。

实施流程:

1. 在变量、方法的前面加上双下划线(__)让变量成为私有概念

python 的语法有很大的弹性。添加下划性只是一种象征性或类似于道德层面的约定。并不能真正意义上让外部不能访问。

class Dog():
    def __init__(self, name, age):
        """初始化属性name和age"""
        self.name = name
        #私有化
        self.__age = age
    def sit(self):
        """小狗蹲下行为"""
        print(self.name.title() + " 乖乖的尊下了!")
    def roll_over(self):
        """小狗打滚"""
        print(self.name.title() + " 开始打滚哈!")

2. 在类中提供对应的 set 和 get 方法实现对内部变量的保护。

def get_age(self):
        return self.__age
    # 对数据进行检查
    def set_age(self, age):
        if age<0:
            print("小狗的年龄不可能为负数")
            return
        self.__age = age

3. 测试

my_dog = Dog('小雪', 6)
my_dog.set_age(-4)
print("小狗的名字:"+my_dog.name.title()+".")
print("小狗今年"+str(my_dog.get_age())+" 岁了")

输出结果

小狗的年龄不可能为负数
小狗的名字:小雪.
小狗今年6 岁了

python 还有一种更优雅的解决方案。使用注解方式。

class Dog():
    def __init__(self, name, age):
        self.name = name
        # 私有属性,属性名(age)前面双下划线的名称
        self.__age = age
    # 实例方法
    def run(self):
        print("{} 在跑……".format(self.name))
    # 使用 @property 定义age属性的 get 方法
    @property
    def age(self):
        return self.__age
    # 使用 @age.setter 定义 age 属性的 set 方法必须放在@property的后面
    @age.setter
    def age(self, age):
        if age < 0:
            print("小狗的年龄不能是负数")
            return
        self.__age = age
#实例化小狗
dog = Dog("小红", 3)
print("{0} 狗狗的年龄是 {1}".format(dog.name, dog.age))
#修改年龄
dog.age = -4
print("{0} 狗狗的年龄是 {1}".format(dog.name, dog.age))

输出结果

小红 狗狗的年龄是 3
小狗的年龄不能是负数
小红 狗狗的年龄是 3

4 . 总结

面向对象编程可以用《人类简史》中的一句话总结,人类文明的进步不一定能泽福到每一个个体。

类可以设计的很完美,但每一个对象作为个体可以有自己的命运。

封装是面向对象编程理念中最基本也是最重要的特性,没有封装便没有后续的更多。

封装可能让我们把相关联的数据与方法构建成一个逻辑上的整体,也可保护内部数据的安全性,毕竟 没有数据安全性的程序是没有意义的。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Python面向对象封装继承和多态示例讲解

    面向对象的三大特征:封装,继承,多态 1.封装: 提高程序的安全性 将数据(属性)和行为(方法)包装到类对象中,在方法内部对属性进行对象的外部调用方法. 这样无需关心内部的具体实现. 在python中没有专门的修饰符用于属性的私有,如果属性不希望被访问,前面使用两个下划线 2.继承: 提高代码的复用性 3.提高程序的可拓展性和可 维护性. 1. 封装 我们来看看私有方式的使用: # 作者:互联网老辛 # 开发时间:2021/4/4/0004 22:11 class Student: def __

  • Python面向对象三大特征 封装、继承、多态

    目录 1.封装 1.1 私有属性和私有方法 2.继承 2.1 方法的重写 2.2 在子类方法中调用父类方法 2.3 多继承 2.4 新式类和经典类 3.多态 1.封装 封装: 根据 职责 将 属性 和 方法 封装到一个 抽象的类 中将数据(属性)和行为(方法)包装到类对象中.在方法内部对属性进行操作,在类对象的外部调用方法.这样无需关心方法 内部的具体实现,从而隔离了复杂度 封装是面向对象编程的一大特点 面向对象编程的第一步.将属性和方法封装到一个抽象的类中 外界使用类创建对象,然后让对象调用方

  • Python面向对象编程之类的封装

    目录 1.封装的理解 2.私有类属性.公开类属性.私有实例属性和公开实例属性 2.1 公开类属性 2.2 私有类属性 2.3 公开实例属性 2.4 私有实例属性 2.5 私有属性不一定真的私有 3.私有方法和公开方法 4.类的保留属性 5.类的保留方法 1.封装的理解 封装(Encapsulation):属性和方法的抽象 属性的抽象:对类的属性(变量)进行定义.隔离和保护 分为私有属性和公开属性: 私有属性:只能在类内部访问 公开属性:可以通过类.对象名访问 可以选择公开或隐藏属性,隐藏属性的内

  • Python面向对象封装操作案例详解 II

    本文实例讲述了Python面向对象封装操作.分享给大家供大家参考,具体如下: 目标 士兵突击案例 身份运算符 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 -- 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 创建 对象,然后 让对象调用方法 对象方法的细节 都被 封装 在 类的内部 一个对象的 属性 可以是 另外一个类创建的对象 01. 士兵突击 需求 士兵 许三多 有一把 AK47 士兵 可以 开火 枪 能够 发射 子弹 枪 装填 装填子弹 -- 增加子弹数量

  • Python面向对象封装操作案例详解

    本文实例讲述了Python面向对象封装操作.分享给大家供大家参考,具体如下: 目标 封装 小明爱跑步 存放家具 01. 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 -- 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 创建 对象,然后 让对象调用方法 对象方法的细节 都被 封装 在 类的内部 02. 小明爱跑步 需求 小明 体重 75.0 公斤 小明每次 跑步 会减肥 0.5 公斤 小明每次 吃东西 体重增加 1 公斤 提示:在 对象的方法内部,是可以 直接访问

  • python 面向对象之class和封装

    # 封装 # Python并没有真正的私有化支持,但可用下划线得到伪私有 访问私有变量:实例._类名__变量名 访问私有方法:实例._类名__方法名() class Wife02(): def __init__(self,name,age,sex): # 负责对象的初始化 self.set_name(name) self.set_age(age) self.set_sex(sex) def set_name(self,value): if isinstance(value,str): # 数据类

  • Python面向对象编程之封装的艺术你了解吗

    目录 1.面向对象编程 1.1OOP特点 1.2OOP基本概念 2.Python实现OOP 2.1分析问题 2.2类设计语法 2.3创建对象语法 3.OOP的封装性 3.1广义角度:无处不封装 封装的优点! 3.2狭义角度:保证内部数据的完整性 实施流程: 4.总结 1. 面向对象编程 OOP ( Object Oriented Programming) 即面向对象编程. 面向对象编程是一种 编码思想 ,或是一种 代码组织方式 .如同编辑文章时,可以选择 分段.分节 的方式让文章看起来有层次.更

  • Python面向对象编程之继承与多态详解

    本文实例讲述了Python面向对象编程之继承与多态.分享给大家供大家参考,具体如下: Python 类的继承 在OOP(Object Oriented Programming)程序设计中,当我们定义一个class的时候,可以从某个现有的class 继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Super class). 我们先来定义一个class Person,表示人,定义属性变量 name 及 sex (姓名和性别): 定义一

  • 学习Javascript面向对象编程之封装

    Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类). 那么,如果我们要把"属性"(property)和"方法"(method),封装成一个对象,甚至要从原型对象生成一个实例对象,我们应该怎么做呢? 一. 生成对象的原始模式 假定我们把猫看成一个对象,它有"名字"和"颜色"两个属性. var C

  • 深入理解JavaScript系列(17):面向对象编程之概论详细介绍

    介绍 在本篇文章,我们考虑在ECMAScript中的面向对象编程的各个方面(虽然以前在许多文章中已经讨论过这个话题).我们将更多地从理论方面看这些问题. 特别是,我们会考虑对象的创建算法,对象(包括基本关系 - 继承)之间的关系是如何,也可以在讨论中使用(我希望将消除之前对于JavaScript中OOP的一些概念歧义). 英文原文:http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/ 概论.范式与思想 在进行E

  • Java面向对象编程之继承和多态以及包的解析与使用范例

    目录 1.继承 1.1继承的基本使用 1.2 protected 关键字 1.3 final 关键字 2.多态 2.1向上转型 2.2动态绑定 2.3方法重写 2.4向下转型 2.5super 关键字 2.5.1 super 关键字的基本用法 2.5.2 this和super的区别 3.包的使用 3.1导入包中的类 3.2常见系统包 1.继承 为什么要有继承? 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中, 那么多个类无需再定义这些属性和行为,只要继承那个类即可. 此处的多个类称为

  • python编程之requests在网络请求中添加cookies参数方法详解

    哎,好久没有学习爬虫了,现在想要重新拾起来.发现之前学习爬虫有些粗糙,竟然连requests中添加cookies都没有掌握,惭愧.废话不宜多,直接上内容. 我们平时使用requests获取网络内容很简单,几行代码搞定了,例如: import requests res=requests.get("https://cloud.flyme.cn/browser/index.jsp") print res.content 你没有看错,真的只有三行代码.但是简单归简单,问题还是不少的. 首先,这

  • python使用线程封装的一个简单定时器类实例

    本文实例讲述了python使用线程封装的一个简单定时器类.分享给大家供大家参考.具体实现方法如下: from threading import Timer class MyTimer: def __init__(self): self._timer= None self._tm = None self._fn = None def _do_func(self): if self._fn: self._fn() self._do_start() def _do_start(self): self.

  • Python编程之Re模块下的函数介绍

    re模块下的函数 compile(pattern):创建模式对象 import re pat=re.compile('A') m=pat.search('CBA') #等价于 re.search('A','CBA') print m <_sre.SRE_Match object at 0x9d690c8> #匹配到了,返回MatchObject(True) m=pat.search('CBD') print m None #没有匹配到,返回None(False) search(pattern,

  • python 编程之twisted详解及简单实例

    python 编程之twisted详解 前言: 我不擅长写socket代码.一是用c写起来比较麻烦,二是自己平时也没有这方面的需求.等到自己真正想了解的时候,才发现自己在这方面确实有需要改进的地方.最近由于项目的原因需要写一些Python代码,才发现在python下面开发socket是一件多么爽的事情. 对于大多数socket来说,用户其实只要关注三个事件就可以了.这分别是创建.删除.和收发数据.python中的twisted库正好可以帮助我们完成这么一个目标,实用起来也不麻烦.下面的代码来自t

  • Python编程之string相关操作实例详解

    本文实例讲述了Python编程之string相关操作.分享给大家供大家参考,具体如下: #coding=utf8 ''''' 字符串是Python中最常见的类型.可以通过引号见包含字符的方式创建. Python里面单引号和双引号的作用是相同的. 字符串是不可变类型,就是说改变一个字符串的元素需要新建一个新的字符串. 字符串是由独立的字符组成,并且这些字符可以通过切片操作顺序地访问. ''' class StringClass(object): ''''' 创建一个字符串就像使用一个标量一样简单.

随机推荐