我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python的单一职责原则怎么实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python的单一职责原则怎么实现

今天小编给大家分享一下python的单一职责原则怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    一,封装

    封装是面向对象编程思想的重要特征之一。

    (一)什么是封装

    封装是一个抽象对象的过程,它容纳了对象的属性和行为实现细节,并以此对外提供公共访问。

    这样做有几个好处:

    • 分离使用与实现。可直接使用公共接口,但不需要考虑它内部具体怎么实现。

    • 拥有内部状态隐藏机制,可实现信息/状态隐藏。

    (二)封装与访问

    就面向对象编程来说,类就是实现对象抽象的手段,封装的实现,就是将对象的属性与行为抽象为类中属性与方法。

    举个例子:

    对象 AudioFile ,需要有文件名,还需要能播放与停止播放。用类封装的话,就类似于下面这个实现:

    class AudioFil:    def __init__(self, filename):        self.filename = filename    def play(self):        print("playing...")    def stop(self):        print("stop playing...")

    self参数必须是传入类方法的第一个(最左侧)参数;Python 会通过这个参数自动填入实例对象(也就是调用这个方法的主体)。这个参数不必叫self,其位置才是重点(C++或Java程序员可能更喜欢把它称作this,因为在这些语言中,该名称反应的是相同的概念。在Python中,这个参数总是需要明确的)。

    封装之后,能轻松实现访问:

    if __name__ == "__main__":    file_name = "金刚葫芦娃.mp3"    current_file = AudioFil(filename=file_name)    print(current_file.filename)    current_file.play()    current_file.stop()>>>金刚葫芦娃.mp3playing 金刚葫芦娃.mp3...stop playing 金刚葫芦娃.mp3...

    同时能在外部修改内部的属性:

    if __name__ == "__main__":    file_name = "金刚葫芦娃.mp3"    current_file = AudioFil(filename=file_name)    print(current_file.filename)    current_file.play()    current_file.stop()    current_file.filename = "舒克与贝塔.ogg"    print(current_file.filename)    current_file.play()    current_file.stop()>>>金刚葫芦娃.mp3playing 金刚葫芦娃.mp3...stop playing 金刚葫芦娃.mp3...舒克与贝塔.oggplaying 舒克与贝塔.ogg...stop playing 舒克与贝塔.ogg...

    (三)私有化与访问控制

    尽管能通过外部修改内部的属性或状态,但有时出于安全考虑,需要限制外部对内部某些属性或者方法的访问。

    一些语言能显式地指定内部属性或方法的有效访问范围。比如在 Java 中明确地有 publicprivate 等关键字提供对内部属性与方法的访问限制,但 python 并提供另一种方式将它们的访问范围控制在类的内部:

    • _ 或 __来修饰属性与方法,使之成为内部属性或方法。

    • 用 __method-name__ 来实现方法重载。

    1,属性与方法的私有化

    举个例子:

    class AudioFil:    def __init__(self, filename):        self._filename = filename    def play(self):        print(f"playing {self._filename}...")    def stop(self):        print(f"stop playing {self._filename}...")if __name__ == "__main__":    file_name = "金刚葫芦娃.mp3"    current_file = AudioFil(filename=file_name)    print(current_file._filename)    current_file.play()    current_file.stop()

    python的单一职责原则怎么实现

    注意 _filename 的格式,单下划线开头表明这是一个类的内部变量,它提醒程序员不要在外部随意访问这个变量,尽管是能够访问的。

    更加严格的形式是使用双下划线:

    class AudioFil:    def __init__(self, filename):        self.__filename = filename    def play(self):        print(f"playing {self.__filename}...")    def stop(self):        print(f"stop playing {self.__filename}...")if __name__ == "__main__":    file_name = "金刚葫芦娃.mp3"    current_file = AudioFil(filename=file_name)    print(current_file.__filename)#AttributeError: 'AudioFil' object has no attribute '__filename'    current_file.play()    current_file.stop()

    注意 __filename 的格式,双下划线开头表明这是一个类的内部变量,它会给出更加严格的外部访问限制,但还是能够通过特殊手段实现外部访问:

        # print(current_file.__filename)    print(current_file._AudioFil__filename)

    _ClassName__attributename

    总之,这种私有化的手段“防君子不防小人”,更何况这并非是真的私有化——伪私有化。有一个更加准确的概念来描述这种机制:变量名压缩。

    2,变量名压缩

    Python 支持变量名压缩(mangling,起到扩展作用)的概念——让类内某些变量局部化。

    压缩后的变量名通常会被误认为是私有属性,但这其实只是一种把类所创建的变量名局部化的方式而已:名称压缩并无法阻止类外代码对它的读取。

    这种机制主要是为了避免实例内的命名空间的冲突,而不是限制变量名的访问。因此,压缩过的变量名最好称为“伪私有”,而不是“私有”。

    类内部以 _ 或 __ 开头进行命名的操作只是一个非正式的惯例,目的是让程序员知道这是一个不应该修改的名字(它对Python自身来说没有什么意义)。

    3,方法重载

    python 内置的数据类型自动地支持有些运算操作,比如 + 运算、索引、切片等,它们都是通过对应对象的类的内部的以 __method-name__ 格式命名的方法来实现的。

    方法重载可用于实现模拟内置类型的对象(例如,序列或像矩阵这样的数值对象),以及模拟代码中所预期的内置类型接口。

    最常用的重载方法是__init__构造方法,几乎每个类都使用这个方法为实例属性进行初始化或执行其他的启动任务。

    方法中特殊的self参数和__init__构造方法是 Python OOP的两个基石

    举个例子:

    class AudioFil:    def __init__(self, filename):        self.__filename = filename    def __str__(self):        return f"我是《{self.__filename}》"    def play(self):        print(f"playing {self.__filename}...")    def stop(self):        print(f"stop playing {self.__filename}...")if __name__ == "__main__":    file_name = "金刚葫芦娃.mp3"    current_file = AudioFil(filename=file_name)    print(current_file)#>>> 我是《金刚葫芦娃.mp3》

    (四)属性引用:getter、setter 与 property

    一些语言使用私有属性的方式是通过 getter 与 setter 来实现内部属性的获取与设置。python 提供 property 类来达到同样的目的。举个例子:

    class C:    def __init__(self):        self._x = None    def getx(self) -> str:        return self._x    def setx(self, value):        self._x = value    def delx(self):        del self._x    x = property(getx, setx, delx, "I'm the 'x' property.")if __name__ == '__main__':    c = C()    c.x = "ccc" # 调用setx    print(c.x)  # 调用getx    del c.x     # 调用delx

    property的存在让对属性的获取、设置、删除操作自动内置化。

    更加优雅的方式是使用@property装饰器。举个例子:

    class C:    def __init__(self):        self._x = None    @property    def x(self):        """I'm the 'x' property."""        return self._x    @x.setter    def x(self, value):        self._x = value    @x.deleter    def x(self):        del self._xif __name__ == '__main__':    c = C()    c.x = "ccc"    print(c.x)      del c.x

    二,单一职责原则

    (一)一个不满足单一职责原则的例子

    现在需要处理一些音频文件,除了一些描述性的属性之外,还拥有播放、停止播放和信息存储这三项行为:

    class AudioFile:    def __init__(self, filename, author):        self.__filename = filename        self.__author = author        self.__type = self.__filename.split(".")[-1]    def __str__(self):        return f"我是《{self.__filename}》"    def play(self):        print(f"playing {self.__filename}...")    def stop(self):        print(f"stop playing {self.__filename}...")    def save(self, filename):        content = {}        for item in self.__dict__:            key = item.split("__")[-1]            value = self.__dict__[item]            content[key] = value        with open(filename+".txt", "a") as file:            file.writelines(str(content)+'\n')if __name__ == '__main__':    file_name = "金刚葫芦娃.mp3"    author_name = "姚礼忠、吴应炬"    current_file = AudioFile(filename=file_name,author=author_name)    current_file.save(filename="info_list")

    这个类能够正常工作。

    注意观察 save 方法,在保存文件信息之前,它做了一些格式化的工作。显然后面的工作是“临时添加”的且在别的文件类型中可能也会用到。
    随着项目需求的变更或者其他原因,经常会在方法内部出现这种处理逻辑的扩散现象,即完成一个功能,需要新的功能作为前提保障。

    从最简单的代码可重用性的角度来说,应该将方法内可重用的工作单独提出来:

    至于公共功能放在哪个层次,请具体分析。

    def info_format(obj):    content = {}    for item in obj.__dict__:        key = item.split("__")[-1]        value = obj.__dict__[item]        content[key] = value    return contentclass AudioFile:    ...    def save(self, filename):        content = info_format(self)        with open(filename+".txt", "a") as file:            file.writelines(str(content)+'\n')

    但是,给改进后的代码在遇到功能变更时,任然需要花费大力气在原有基础上进行修改。比如需要提供信息搜索功能,就可能出现这种代码:

    class AudioFile:    ...    def save(self, filename):        ...    def search(self, filename, key=None):        ...

    如果后期搜索条件发生变更、或者再新增功能,都会导致类内部出现功能扩散,将进一步增加原有代码的复杂性,可读性逐渐变差,尤其不利于维护与测试。

    (二)单一职责原则

    单一职责原则(Single-Responsibility Principle,SRP)由罗伯特·C.马丁于《敏捷软件开发:原则、模式和实践》一书中提出。这里的职责是指类发生变化的原因,单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。

    该原则提出对象不应该承担太多职责,如果一个对象承担了太多的职责,至少存在以下两个缺点:

    • 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;

    • 当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。

    举个例子:一个编译和打印报告的模块。想象这样一个模块可以出于两个原因进行更改。

    首先,报告的内容可能会发生变化。其次,报告的格式可能会发生变化。这两件事因不同的原因而变化。单一职责原则说问题的这两个方面实际上是两个独立的职责,因此应该在不同的类或模块中。

    总之,单一职责原则认为将在不同时间因不同原因而改变的两件事情结合起来是一个糟糕的设计。

    看一下修改后的代码:

    class AudioFile:    def __init__(self, filename, author):        self.__filename = filename        self.__author = author        self.__type = self.__filename.split(".")[-1]    def __str__(self):        return f"我是《{self.__filename}》"    def play(self):        print(f"playing {self.__filename}...")    def stop(self):        print(f"stop playing {self.__filename}...")class AudioFileDataPersistence:    def save(self, obj, filename):        ...class AudioFileDataSearch:    def search(self, key, filename):        ...if __name__ == '__main__':    file_name = "金刚葫芦娃.mp3"    author_name = "姚礼忠、吴应炬"    current_file = AudioFile(filename=file_name, author=author_name)    data_persistence = AudioFileDataPersistence()    data_persistence.save(current_file, filename="info_list")    data_search = AudioFileDataSearch()    data_search.search(file_name, filename="info_list")

    但这样将拆分代码,是不是合理的选择?

    三,封装与单一职责原则

    从封装的角度看来说,它的目的就是在对外提供接口的同时,提高代码的内聚性和可重用性,但功能大而全的封装更加的不安全。

    单一职责原则通过拆分代码实现更低的耦合性和更高的可重用性,但过度拆分会增加对象间交互的复杂性。

    关于两这的结合,有一些问题需要事先注意:

    • 需求的粒度是多大?

    • 维护的成本有多高?

    作为面向对象编程的基础概念与实践原则,二者实际上是因果关系——如果一个类是有凝聚力的,如果有一个更高层次的目的,如果它的职责符合它的名字,那么 SRP 就会自然而然地出现。SRP 只是代码优化后的实际的结果,它本身并不是一个目标。

    以上就是“python的单一职责原则怎么实现”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    python的单一职责原则怎么实现

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    python的单一职责原则怎么实现

    今天小编给大家分享一下python的单一职责原则怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一,封装封装是面向对象
    2023-06-29

    Java单一职责原则怎么实现

    这篇文章主要讲解了“Java单一职责原则怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java单一职责原则怎么实现”吧!1.什么是单一职责原则?首先我们可以对某个类来说,即一个类应该
    2023-06-29

    java设计模式的单一职责原则怎么实现

    这篇“java设计模式的单一职责原则怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“java设计模式的单一职责原则怎么
    2023-06-17

    单一职责原则与PHP中的实践

    单一职责原则(Single Responsibility Principle,SRP)是面向对象设计中的一个重要概念,它指出一个类应该只有一个引起变化的原因。换句话说,一个类应该只负责完成一个单一的职责或功能。在PHP中,遵守单一职责原则有
    2023-10-21

    什么实现Java项目中的单一职责原则

    这期内容当中小编将会给大家带来有关什么实现Java项目中的单一职责原则,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。问题由来:类T
    2023-05-31

    C++单一职责原则的代码怎么写

    今天小编给大家分享一下C++单一职责原则的代码怎么写的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。单一职责原则:就一个类而言
    2023-07-05

    原生js怎么实现表单的正则验证

    这篇文章将为大家详细讲解有关原生js怎么实现表单的正则验证,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。JavaScript可以做什么1.可以使网页具有交互性,例如响应用户点击,给用户提供更好的体验。2.
    2023-06-14

    python的简单四则运算语法树可视化怎么实现

    本文小编为大家详细介绍“python的简单四则运算语法树可视化怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“python的简单四则运算语法树可视化怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。简
    2023-07-05

    Android怎么实现一个简单的单词本

    这篇文章主要介绍了Android怎么实现一个简单的单词本的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android怎么实现一个简单的单词本文章都会有所收获,下面我们一起来看看吧。本文基于Java实现了一个简单
    2023-06-29

    Python中怎么实现一个简单遗传算法

    今天就跟大家聊聊有关Python中怎么实现一个简单遗传算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。遗传算法遗传算法是模仿自然选择过程的优化算法。 他们没有使用"数学技巧",而是
    2023-06-16

    java设计模式的依赖倒置原则怎么实现

    这篇文章主要讲解了“java设计模式的依赖倒置原则怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java设计模式的依赖倒置原则怎么实现”吧!依赖倒置原则(Dependence Inv
    2023-06-17

    怎么使用python实现一个简单的贪吃蛇游戏

    本篇内容主要讲解“怎么使用python实现一个简单的贪吃蛇游戏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用python实现一个简单的贪吃蛇游戏”吧!pygame 写的“贪吃蛇”小游戏:
    2023-07-02

    怎么使用Python元类编程实现一个简单的ORM

    这篇文章主要讲解了“怎么使用Python元类编程实现一个简单的ORM”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用Python元类编程实现一个简单的ORM”吧!概述什么是ORM?  
    2023-07-05

    python中的单向链表怎么实现

    这篇文章主要介绍了python中的单向链表怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇python中的单向链表怎么实现文章都会有所收获,下面我们一起来看看吧。一、单向链表概念单向链表的链接方向是单向的
    2023-06-29

    怎么实现Python的add5()单元测试

    本篇内容介绍了“怎么实现Python的add5()单元测试”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!TestAdd5类由unittest
    2023-06-17

    C++怎么实现一个简单的线程池

    本文小编为大家详细介绍“C++怎么实现一个简单的线程池”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++怎么实现一个简单的线程池”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、设计线程池应该包括保存线程的容
    2023-06-30

    CSS怎么实现一个简单的Loading效果

    CSS实现Loading在前端开发中,Loading是一个非常常见的功能。当网页数据加载时,我们希望能够在用户等待的同时,给其一个视觉上的反馈,来增强用户体验。在这篇文章中,我们将通过CSS来实现一个简单的Loading效果。1.使用Animation动画实现LoadingAnimation是CSS3新增的一个模块,它可以用来创建非常复杂的动画效果。这里我们通过Animatio
    2023-05-14

    Python全栈的单项循环怎么实现

    本篇内容介绍了“Python全栈的单项循环怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 多项_巢状分支多项分支 (多选一)""
    2023-06-21

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录