为什么 Python 不用设计模式?

Python中的23种设计模式:详细分类与总结 设计模式是解决特定问题的通用方法,分为创建型模式、结构型模式和行为型模式三大类。本文是对每种模式的详细介绍,包括其核心思想、应用场景和优缺点。 阅读详情

点击上方“开发者技术前线”,选择“星标”

13:21 在看 真爱


作者: 刘欣| 责编: 可可  | 来源 :码农翻身


640?wx_fmt=jpeg




 

在遥远的Python王国,有一位少年,非常热爱编程,他的父母想给他报一个班,问了万能的朋友圈以后,发现大家都推荐同一个老师,人称吉先生。 


于是他的父母毫不犹豫就交了一笔不菲的学费,每周六日下午让孩子去学习。 


少年学习非常刻苦,很快就学会了Python语法、工具和框架。 


老师像是见到了可以雕刻的美玉, 倾囊相授,告诉他不仅要把代码写对,还要让代码漂亮、优雅、可读、可维护。 


少年又学会了单元测试,TDD,重构,努力让自己的代码达到老师所要求的标准。 


他还把“Python 之禅”贴在了自己的墙上,经常对照自己的代码,从来都不敢违反。 


The Zen of Python, by Tim Peters 


Beautiful is better than ugly. 

Explicit is better than implicit. 

Simple is better than complex. 

Complex is better than complicated. 

Flat is better than nested. 

Sparse is better than dense. 

Readability counts. 

......


三年以后,少年以为自己成为了Python的大师,直到有一天,老师给他布置了一个大作业,其实是个大项目,业务非常复杂。


少年通宵达旦地编程,可他悲惨地发现,无论他怎么努力,他的代码都是乱糟糟的,没有美感,他所写出的类,模块混成了一团。 


于是他只好去请教老师: “老师,我的Python和Flask框架已经用得滚瓜烂熟了,为什么完成不了这个项目呢?” 


老师说:“孩子,原来你只需要把框架的类给import进来,稍微写点儿代码就行了,现在你需要自己去设计类,自己去做出抽象了!” 


 “怎么设计呢?” 


“为师送你一本古书,《设计模式》 ,你回去好好看看吧。”


640?wx_fmt=png


少年如获至宝, 废寝忘食地去研究这本20多年前出的、泛黄的古书,还是用C++描述的。  


他看得云里雾里,似乎明白,又似乎不明白,只好再去请教老师。 


这一次,老师给了他另外一本书, 《Head First 设计模式》 


640?wx_fmt=png


少年翻开一看,这本书是用Java写的,于是又一头扎到了Java语言当中。 


这本书比较通俗易懂,少年看得大呼过瘾。 


终于,他信心十足地用Python开始那个大项目了。 


他用Python语言实现设计模式,解决一些设计问题,可是总觉得不对劲,和Java , C++相比,感觉怪怪的。 


另外他感觉到了动态语言的不爽之处,每次想重构的时候,总是不敢下手,他把困惑给老师说了。 


老师笑道:“我在Java王国的时候,人们总是说‘动态一时爽,重构火葬场’, 现在你体会到了吧!” 


“Java就能避免这个问题吗?”  


“Java是一门静态语言,变量类型一旦确定就不能改变,对重构的支持非常好,你有没有兴趣去看看?那里有很多的框架,像Spring,Spring Boot,MyBatis, Dubbo, Netty,非常繁荣发达。” 


少年心生向往,于是老师就给他写了个条子,告诉他说到了Java王国,找到IO大臣,一切事情都会畅通无阻。  


少年辞别老师,奔向了Java帝国,老师整了整衣冠, 望着东方Java帝国的方向,庄严地拜了三拜:“五年了,IO大人,我没有辜负您的重托,又忽悠了一个人去做Java了!”  


原来这位老师就是吉森! IO大臣派来传播Java文化和价值观的传教士,入境后不幸被识破,软禁在了Python王国。 


吉森的故事请移步《Java帝国对Python的渗透能成功吗?》  


Python没有接口?


Python国王收到边关的奏报,说是最近有不少年轻人奔向了Java王国,不知道是不是国内政策有变,导致人心浮动。 


Python国王震怒,下令严查。 查来查去,所有的线索都指向了一个人:吉森。 


这一天,Python特使带着士兵来到了吉森的住所,果然发现他又在忽悠年轻人了。 


特使又气又笑:“你学了半吊子的Python,居然敢来蛊惑人心,实在是可笑。” 


吉森看到自己的计谋已被识破,依然很镇静:“大人误会了,我教的就是正宗的面向对象的设计和设计模式啊,这设计模式用Python实现起来很别扭,我就推荐他们去学Java啊。”  


“胡说,Python写设计模式怎么会很别扭? Java 由于语法所限,表达能力比较弱,对于一些问题,只好用笨拙的设计模式来解决,我们Python有可能在语法层面就解决问题了!” 


“那你说说,设计模式的原则是什么?” 吉森问道。 


“1. 面向接口编程,而不是面向实现编程。2. 优先使用组合而不是继承。” 这是难不住特使的。


 “Python连接口都没有,怎么面向接口编程?”  吉森问道。 


特使哈哈大笑:“说你是半吊子吧,你还不服,你以为这里的接口就是你们Java的interface啊!你忘了Python的Duck Typing了?” 


class Duck:    def fly(self):        print("Duck flying")class Airplane:    def fly(self):        print("Airplane flying")def lift_off(entity):    entity.fly()duck = Duck()plane = Airplane()lift_off(duck)lift_off(plane)
    def fly(self):
        print("Duck flying")

class Airplane:
    def fly(self):
        print("Airplane flying")


def lift_off(entity):
    entity.fly()


duck = Duck()
plane = Airplane()

lift_off(duck)
lift_off(plane)


“看到没有, Duck和Airplane都没有实现你所谓的接口,但是都可以调用fly()方法,这难道不是面向接口编程, 如果你非要类比的话,这个fly就是一个自动化的接口啊。” 


吉森确实没想到这一层,至于第二个原则,优先使用组合而不是继承,可以是每个面向对象的语言都可以实现的,他叹了口气,也就不问了。 


Adapter模式


特使接着说:“Duck Typing非常强大,你不是提到了设计模式吗,在Duck Typing面前,很多设计模式纯属多此一举。我来给你举个例子,Adapter模式。假设客户端有这么一段代码,可以把一段日志写入文件当中。” 



 
def log(file,msg):    file.write('[{}] - {}'.format(datetime.now(), msg))
    file.write('[{}] - {}'.format(datetime.now(), msg))


“现在来了新的需求,要把日志写入数据库, 而数据库并没有write 方法,怎么办? 那就写个Adapter吧。” 



 
class DBAdapter:    def __init__(self, db):        self.db = db    def write(self, msg):        self.db.insert(msg)
    def __init__(self, db):
        self.db = db

    def write(self, msg):
        self.db.insert(msg)


“注意这个DBAdapter并不需要实现什么接口(我大Python也没有接口),就是一个单独的类,只需要有个write方法就可以了。” 



 
db_adapter = DBAdapter(db)log(db_adapter, "sev1 error occurred")"sev1 error occurred")


确实是很简单,只要有write 方法, 不管你是任何对象,都可以进行调用, 典型的Duck Typing 。   


既然Adapter可以这么写,那Proxy模式也是类似了,只要你的Proxy类和被代理的类的方法一样,那就可以被客户使用。 


但是这种方法的弊端就是,不知道log方法的参数类型,想要重构可就难了。 


单例模式


吉森又想到了一个问题,继续挑战特使:“Python连个private 关键字都没有,怎么隐藏一个类的构造函数,怎么去实现单例?” 


特使不屑地说:“忘掉你那套Java思维吧,在Python中想写个singleton有很多办法,我给你展示一个比较Python的方式,用module的方式来实现。”



 
#singleton.pyclass Singleton:    def __init__(self):        self.name = "i'm singleton"instance = Singleton()del Singleton  # 把构造函数删除

class Singleton:
    def __init__(self):
        self.name = "i'm singleton"

instance = Singleton()

del Singleton  # 把构造函数删除


使用Singleton:



 
import singletonprint(singleton.instance.name)  # i'm singletoninstance = Singleton() # NameError: name 'Singleton' is not defined

print(singleton.instance.name)  # i'm singleton

instance = Singleton() # NameError: name 'Singleton' is not defined


吉森确实没有想到这种写法,利用Python的module来实现信息的隐藏。


Visitor模式


不是每个设计模式都能这么干吧?  吉森心中暗想,他脑海中浮现了一个难于理解的模式:Visitor,自己当初为了学习它可是下了苦工。 


吉森说:“那你说说,对于Visitor,怎么利用Python的特色?” 


“我知道你心里想的是什么,无非就是想让我写一个类,然后在写个Visitor对它进行访问,是不是?” 



 
class TreeNode:    def __init__(self, data):        self.data = data        self.left = None        self.right = None    def accept(self, visitor):        if self.left is not None:            self.left.accept(visitor)        visitor.visit(self)        if self.right is not None:            self.right.accept(visitor)class PrintVisitor:    def visit(self,node):        print(node.data)root = TreeNode('1')root.left = TreeNode('2')root.right = TreeNode('3')visitor = PrintVisitor()root.accept(visitor)   #输出2, 1, 3
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
    def accept(self, visitor):
        if self.left is not None:
            self.left.accept(visitor)

        visitor.visit(self)

        if self.right is not None:
            self.right.accept(visitor)

class PrintVisitor:
    def visit(self,node):
        print(node.data)

root = TreeNode('1')
root.left = TreeNode('2')
root.right = TreeNode('3')

visitor = PrintVisitor()

root.accept(visitor)   #输出2, 1, 3


吉森说:“是啊, 难道Visitor模式不是这么写的吗? ”


"我就说你的Python只是学了点皮毛吧,Visitor的本质是在分离结构和操作, 在Python中使用generator可以更加优雅地实现。” 



 
class TreeNode:    def __iter__(self):        return self.__generator()    def __generator(self):        if self.left is not None:            yield from iter(self.left)         yield from self.data        if self.right is not None:            yield from iter(self.right) root = TreeNode('1')root.left = TreeNode('2')root.right = TreeNode('3')for ele in root:    print(ele)

    def __iter__(self):
        return self.__generator()

    def __generator(self):
        if self.left is not None:
            yield from iter(self.left) 
        yield from self.data

        if self.right is not None:
            yield from iter(self.right) 

root = TreeNode('1')
root.left = TreeNode('2')
root.right = TreeNode('3')

for ele in root:
    print(ele)


不得不承认,这种方式使用起来更加简洁,同时达到了结构和操作进行分离的目的。 


特使说道: “看到了吧,Python在语言层面对一些模式提供了支持,所以很多设计模式在我大Python看起来非常笨拙,我们这里并不提倡,当然我们还是要掌握面向对象设计的原则SOLID和设计模式的思想,发现变化并且封装变化,这样才能写出优雅的程序出来。” 


吉森叹了一口气,感慨自己学艺不精,不再反抗,束手就擒。 


尾声


Python王国审判了吉森,本来要判他死刑,但是Java帝国重兵压境,要求释放,否则就开战。 


吉森被送回Java王国,成为了人们心目中的英雄,回家他仔细对比了Java和Python,在Java虚拟机上把Python语言给实现了!国王为了表彰他的英勇事迹,把这个语言叫做Jython。640?wx_fmt=jpeg


ps. 本文故事受到了这个视频的启发:https://www.youtube.com/watch?v=G5OeYHCJuv0


END

开发者技术前线 ,汇集技术前线快讯和关注行业趋势,大厂干货,是开发者经历和成长的优秀指南。

历史阅读


Python 3.8  正式发布,新特性全面解读

Python 学习路线思维导图, 经典收藏!

Google Python 编码规范

640? 640?wx_fmt=gif 640?wx_fmt=png 喜欢就点个好看吧 640?wx_fmt=gif


Python 中最简最好的设计模式 作为这么一门有前途也有钱途的语言,还有什么理由不去学习和掌握呢? 阅读详情

相关推荐

【Python】Python设计模式

Python语言本身的设计,就已经蕴含了许多设计模式的思想。在我们学习具体模式之前,认识到这些语言层面的“内建模式”至关重要,因为它们往往是解决特定问题的首选方案。装饰器 (Decorators): 这是对经典装饰器模式 (Decorator Pattern) 和 代理模式 (Proxy Pattern) 的直接语法级支持。它允许我们以一种声明式、非侵入的方式,为函数或类附加额外的职责,如日志记录、性能测试、事务处理、权限校验等。上下文管理器 (Context Managers): 语句和、方法,是资源管理

宅男很神经 1174

Python的23种设计模式(完整版带源码实例)

设计模式是面对各种问题进行提炼和抽象而形成的解决方案。这些设计方案是前人不断试验,考虑了封装性、复用性、效率、可修改、可移植等各种因素的高度总结。它不限于一种特定的语言,它是一种解决问题的思想和方法最后的最后由本人水平所限,难免有错误以及不足之处, 屏幕前的靓仔靓女们 如有发现,恳请指出!你轻轻地点了个赞,那将在我的心里世界增添一颗明亮而耀眼的星!

编辑编辑器 2万+

手把手教你用Github提交CVE漏洞(附完整截图流程)

本文提供了在GitHub平台提交CVE漏洞的完整实战指南。从前期准备、目标搜寻与漏洞验证,到撰写规范的GitHub Issue进行披露,最后通过官方渠道完成CVE提交,手把手教你如何将安全研究成果转化为获得国际认可的CVE编号。

weixin_28309571的博客 330

python的设计模式

文章目录设计模式0、接口1、单例模式方法一:使用模块方法二、装饰器实现方法三、基于__new__方法2、工厂模式3、建造者模式 设计模式 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 0、接口 定义:一种特殊的类,声明了若干方法,要求继承该接口的类必须实现这种方法,作用:限制继承接口的类的方法的名称及调用方式,隐藏了类的内部实现 1、单例模式 ​ 单例模式(Singleton Pattern)是一种常用的软

weixin_43673156的博客 8841

中科蓝讯蓝牙开发:从源码到固件的自动化构建链路解析

本文详细解析了中科蓝讯AB530X蓝牙芯片从源码到最终固件的完整自动化构建链路。通过剖析prebuild.bat、GCC编译、postbuild.bat等关键环节,阐述了资源打包、配置生成、代码编译与固件合成的全过程,并重点介绍了如何实现一键编译与自动下载,为开发者高效进行嵌入式蓝牙开发提供清晰指南。

weixin_29193259的博客 121

SolidWorks+ADAMS双验证:你的机械臂力矩计算真的靠谱吗?

本文探讨了机械臂力矩计算中手工计算的局限性,并介绍了SolidWorks和ADAMS双验证方法的重要性。通过实际案例展示了动态工况下传统计算方法的误差,详细解析了SolidWorks精准质心捕捉和ADAMS动力学仿真的关键技术,帮助工程师构建计算-仿真-实测闭环验证流程,确保机械臂设计的可靠性和安全性。

grafana6viz的博客 230

python设计模式总结

介绍 每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样你就能一次又一次地使用该方案而不必做重复劳动。—— Christopher Alexander 软件危机催生了设计模式,面向对象,软件工程。是什么每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。热身既然是针对面向对象的,让我们先来回顾一下面向的三大特性和接口面向对象的三大特性:

Ayhan_huang的博客 2207

SAP SD跨公司销售IDOC自动记账配置实战指南

本文详细介绍了SAP SD模块中跨公司销售IDOC自动记账的配置实战指南。通过IDOC技术实现集团企业间交易的自动化处理,显著提升财务效率和准确性。文章涵盖前置配置、RFC连接、合作伙伴参数设置及财务科目分配等关键步骤,并提供了常见错误排查和性能优化建议,帮助用户快速掌握这一高效业务流程。

weixin_29284885的博客 772

python设计模式有哪几种?

Python设计的几种模式

派森的博客 1483

博图HMI多语言文本列表一键生成攻略:从Excel模板到TIA Portal的完整流程

本文详细介绍了如何利用Excel模板和TIA Portal API实现博图HMI多语言文本列表的一键生成。通过标准化Excel模板设计、解析TIA Portal的XML结构,并结合C#代码实现自动化导入,大幅提升多语言项目的开发效率。特别适用于需要支持多语言版本的自动化设备HMI界面开发。

weixin_26934905的博客 218

数据科学常见模型总结(二)-倾向性得分匹配模型

PSM的核心思想是从未受干预的用户群体中,找到和干预对象一模一样的用户,这样就可以把因果效应归因到干预上。

wudelong0112的专栏 4896

为什么Python不用设计模式?

在遥远的Python王国,有一位少年,非常热爱编程,他的父母想给他报一个班,问了万能的朋友圈以后,发现大家都推荐同一个老师,人称吉先生。于是他的父母毫不犹豫就交了一笔不...

码农翻身 3696

Cisco Packet Tracer 7.3免登录技巧:3种方法快速跳过注册界面(附详细截图)

本文针对Cisco Packet Tracer 7.3启动时遇到的登录界面问题,提供了三种合法高效的解决方案。详细介绍了如何利用官方访客模式快速启动、注册思科账号实现一劳永逸登录,以及通过调整本地安装配置优化启动流程,帮助网络学习者与备考者绕过繁琐步骤,快速进入实验环境。

weixin_29305337的博客 742

python用设计模式吗_为什么Python不用设计模式?

为什么Python不用设计模式?

weixin_39532352的博客 287

OpenGL 进阶系列10 - 光线跟踪实现简介(Ray Tracing)

OpenGL 实现光线跟踪(Ray Tracing)是一个相对复杂但有趣的挑战,通常用于生成高度逼真的图像效果,如反射、折射、阴影等。OpenGL 本身并不是为光线跟踪设计的,但可以通过结合计算着色器和现代 OpenGL 功能实现光线跟踪。光线跟踪的基本思路是从相机(或视点)出发,发射光线并计算这些光线与场景中物体的交点。光线与场景中物体相交的计算。计算交点的光照(基于表面法线、光源位置、材质等)。反射和折射的处理(如果物体是透明或反射的)。

GPU全栈博主 1534

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

为什么Python不用设计模式? -- EuroPython 2017笔记

刚刚看了EuroPython 2017一篇演讲,Why You Don’t Need Design Patterns in Python,为什么python不用设计模式。演讲者是STXNEXT的Sebastian Buczynski。 他对设计模式的定义是: 常见问题的通用可复用解决方案 定型的最佳实践 他说设计模式是一种似曾相识(Anology),是一种大纲(Outline),他认为设计模式并不是拿来就能用的。 Singleton 第一个是Singleton模式,Singleton的精髓就是任何时候

juwikuang的专栏 1413

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

python 动态语言的设计模式_为何大量设计模式在动态语言中不适用?

有些设计模式仅仅是为了克服静态语言的缺点而存在==========================================划个重点“有些”,原文中也说了,23个pattern中的16个,说明还有7个是适用的。其他的也并不是不适用,而是有更简单的设计,通常是直接使用类或者callable来代替接口。而且相同的问题在动态语言当中往往可以有多得多的设计方式,不同设计方式有不同的特点和优劣,并没有...

weixin_39851918的博客 117

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

设计模式实践教程 - 基于 micooz/DesignPattern 开源项目

设计模式实践教程 - 基于 micooz/DesignPattern 开源项目 项目介绍 该项目由 Github 用户 micooz 维护,是针对软件开发中常见设计模式的实现集合。它旨在提供一个学习和理解各种设计模式的实战平台,涵盖了从单例模式到观察者模式等二十多种经典设计模式。通过此仓库,开发者可以深入学习每种模式的概念、应用场景及其实现细节,助力提升代码质量和可维护性。 项目快速启动 环境要求...

gitblog_00751的博客 819

你应该避免的18种常见 Python“反设计模式”

从优美的代码中可以学到很多东西,从糟糕的代码中也一样可以。 编者按:编程也需要养成良好的习惯,遵循正确的规范。过分的炫技和糟糕的习惯都要不得,那会令你的代码难以识别和维护,最终成为一个谁都不愿意接手的烂摊子。无论你是初学者还是有了一定经验的开发者,了解这些不好的反设计模式(Anti-Pattern)都会有帮助。本文译自Medium,作者 Ahmed Besbes,原标题为“18 Common Python Anti-Patterns I Wish I Had Known Before”。 我使用.

m0_46163918的博客 8935

从生活中领悟设计模式(Python)

课程介绍 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、无数工程师实践的代码设计经验的总结,它是面向对象思想的高度提炼和模板化。使用设计模式将会让代码具有更高的可重用性、更好的灵活性和可拓展性、更容易阅读和理解。 程序不应只是冷冰冰的代码,更应赋予它生活的乐趣和特殊的意义。本课程内容将会从生活的角度,在生活的每一个细节和故事中解读一个个设计模式。力求用最通俗的语言阐述最难...

GitChat 8073
上一篇: Android 1.5 -10.0 都有哪些新特性?
下一篇: 学不动了 ,京东跨端移动开发平台 Ares 发布!
DevolperFront
博客等级 码龄8年 465粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值