详解Python为什么不用设计模式


Posted in Python onJune 24, 2021

前言

刚刚看了EuroPython 2017一篇演讲,Why You Don't Need Design Patterns in Python,为什么python不用设计模式。演讲者是STXNEXT的Sebastian Buczynski。

他对设计模式的定义是:

  • 常见问题的通用可复用解决方案
  • 定型的最佳实践

他说设计模式是一种似曾相识(Anology),是一种大纲(Outline),他认为设计模式并不是拿来就能用的。

Singleton

详解Python为什么不用设计模式

第一个是Singleton模式,Singleton的精髓就是任何时候,只有一个类的实例。

《设计模式》里面给出的Singleton代码是

声明:

class Singleton {
public:
	static Singleton* Instance();
protected:
	Singleton();
private:
	static Singleton* _instance;
};

实现:

Singleton* Singleton::_instance = 0;

Sebastian 在 Google 上面找Singleton的Python实现,找到了以下代码:

声明:

class Singleton:
	_instance = None
	def __new__(cls, *args, **kwargs):
		if not cls._instance:
			cls._instance = super().__new__(cls, *args, **kwargs)
		return cls._instance

实现:

one_instance = Singleton()
another_instance = Singleton()
one_instance is another_instance # True

Sebastian指出,照抄C++,当然也可以解决问题,但是在python里面有更好的解决方案。比如,可以用@classmethod。不过,最好的解决方案是直接用module。因为module本身就是唯一的,相当于module就实现了singleton,那么,我们为什么要大费周章,搞一个singleton出来呢?

我回忆了一下,尽管Singleton是最简单的设计模式了,但是,我这么多年一直没用。以前写C#的时候,我用的是静态类,静态类本身就是唯一的,所以我不需要singleton。当然,我看到有人也用C#写了和C++一样的Singleton,但是我觉得解决问题就可以了,没必要为了写设计模式而写设计模式。同样,写VB.net的时候,我直接用的module,也不需要singleton。

结论:当年《设计模式》里面的Singleton模式,是为了只有一个类实例。如果编程语言本身,如python, c#, vb.net,已经提供了这样的能力,就没有必要再用C++的套路了。或者说,设计模式就不需要了。

Facade

详解Python为什么不用设计模式
详解Python为什么不用设计模式

(以上图片来自参考[1])

Facade的基本概念是,子系统用Facade来屏蔽内部的复杂实现。

这时,我们可以把子系统的python文件统一放在一个文件夹里,然后在这个文件夹里放一个__init__.py文件。

详解Python为什么不用设计模式

Command

Command模式把请求封装成对象。

Sebastian认为,在python里面,函数就是一等公民,所以没有必要创建对象。

def command(discount_rate):
some_obj.notify_users_about_discount()

也可以用functools创建command

import functools
command = functools.partial(
some_obj.notify_users_about_discount, discount_rate=0.5
)
command()
# equals to
some_obj.notify_users_about_discount(discount_rate=0.5)

Visitor

Python里面没有接口,没有方法重载。那么怎么实现Visitor呢?

Sebastian指出,可以用@SingleDispatch。

from functools import singledispatch
@singledispatch
def visit(node):
	type_name = type(node).__name__
	raise AttributeError(f'No handler found for {type_name}')
from ast_nodes import Assign, FunctionDef
@visit.register(Assign)
def visit(node):
	pass
@visit.register(FunctionDef)
def visit(node):
	pass

我们看到,这里的实现,并没有class。

Decorator

Decorator可以用来扩展一个对象。

它实现的方法是新建一个类,这个类和原来的类属于同一个接口。然后这个类接受一个原来的类的对象,每个方法都调用原来的类的方法。

如果套用c++的《设计模式》,我们有

class OriginalClass:
	def get_text(self):
		pass
	def get_number(self):
		pass

    
class Decorator:
	def __init__(self, decorated_obj):
		self.decorated_obj = decorated_obj
	def get_text(self):
		return f'<b>{self.decorated_obj.get_text()}</b>'
	def get_number(self):
		return self.decorated_obj.get_number()

但是,这里可以用python的__getattr__特性来简化实现。

class Decorator:
	def __init__(self, decorated_obj):
		self.decorated_obj = decorated_obj
	def get_text(self):
		return f'{self.decorated_obj.get_text()}'
	def __getattr__(self, attr_name):
		return getattr(self.decorated_obj, attr_name)

总结

Sebastian指出,python非常灵活。和25年前的C++大相径庭。很多地方,都非常容易插入逻辑。过去的设计模式,可能并不适用了。我们应该很好的了解python,并借鉴其他语言,而不是生搬硬套。

我觉得,再好的东西,也要和实际相结合。任何脱离实际的做法,都是多余的,甚至有害的。任何理论,方法的产生,都有当时的历史背景,技术背景。如果不了解背后的机制,不了解背后的精神和目的,而是专注于招式本身,那只能是越来越僵化。看似坚持,实际上是背叛。坚持是说固执的坚持原来的做法,背叛是指背叛了初衷。

参考

[1] Why You Don't Need Design Patterns in Python

[2] Design Patterns ? Elements of Reusable Object-Oriented Software

到此这篇关于详解Python为什么不用设计模式的文章就介绍到这了,更多相关Python设计模式内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
浅析Python中的join()方法的使用
May 19 Python
Python做简单的字符串匹配详解
Mar 21 Python
浅述python中深浅拷贝原理
Sep 18 Python
python实现简单多人聊天室
Dec 11 Python
详解10个可以快速用Python进行数据分析的小技巧
Jun 24 Python
解决python中导入win32com.client出错的问题
Jul 26 Python
Python内置加密模块用法解析
Nov 25 Python
Python常用库大全及简要说明
Jan 17 Python
记一次pyinstaller打包pygame项目为exe的过程(带图片)
Mar 02 Python
关于python 跨域处理方式详解
Mar 28 Python
Python定义函数实现累计求和操作
May 03 Python
python多线程方法详解
Jan 18 Python
linux中nohup和后台运行进程查看及终止
Jun 24 #Python
Python面向对象之成员相关知识总结
Jun 24 #Python
Python面向对象之内置函数相关知识总结
Jun 24 #Python
python面向对象版学生信息管理系统
Python实现学生管理系统(面向对象版)
Jun 24 #Python
Pycharm连接远程服务器并远程调试的全过程
Python函数中的不定长参数相关知识总结
Jun 24 #Python
You might like
php基础知识:类与对象(2) 自动加载对象
2006/12/13 PHP
php中的数组操作函数整理
2008/08/18 PHP
PHP面向对象程序设计类的定义与用法简单示例
2016/12/27 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
2017/07/20 PHP
PHP实现无限极分类的两种方式示例【递归和引用方式】
2019/03/25 PHP
laravel在中间件内生成参数并且传递到控制器中的2种姿势
2019/10/15 PHP
让iframe子窗体取父窗体地址栏参数(querystring)
2009/10/13 Javascript
关于递归运算的顺序测试代码
2011/11/30 Javascript
window.open不被拦截的实现代码
2012/08/22 Javascript
javascript判断是否按回车键并解决浏览器之间的差异
2014/05/13 Javascript
JS交换变量的方法
2015/01/21 Javascript
js插件dropload上拉下滑加载数据实例解析
2016/07/27 Javascript
纯js实现的积木(div层)拖动功能示例
2017/07/19 Javascript
JS实现把一个页面层数据传递到另一个页面的两种方式
2018/08/13 Javascript
微信小程序 WXML节点信息查询详解
2019/07/29 Javascript
vue-quill-editor 自定义工具栏和自定义图片上传路径操作
2020/08/03 Javascript
vue data变量相互赋值后被实时同步的解决步骤
2020/08/05 Javascript
如何在JavaScript中等分数组的实现
2020/12/13 Javascript
[07:39]第一届亚洲邀请赛回顾视频
2017/02/14 DOTA
python发送邮件接收邮件示例分享
2014/01/21 Python
在Python下利用OpenCV来旋转图像的教程
2015/04/16 Python
Python编写电话薄实现增删改查功能
2016/05/07 Python
使用numba对Python运算加速的方法
2018/10/15 Python
python2和python3应该学哪个(python3.6与python3.7的选择)
2019/10/01 Python
pytorch动态网络以及权重共享实例
2020/01/06 Python
python基于property()函数定义属性
2020/01/22 Python
Python+Appium实现自动化测试的使用步骤
2020/03/24 Python
Anaconda+spyder+pycharm的pytorch配置详解(GPU)
2020/10/18 Python
用Python自动清理系统垃圾的实现
2021/01/18 Python
荷兰本土平价百货:HEMA
2017/10/23 全球购物
初中英语课后反思
2014/04/25 职场文书
倡议书格式
2014/08/30 职场文书
2015年销售部工作总结范文
2015/04/27 职场文书
义卖募捐活动总结
2015/05/09 职场文书
主持人开场白台词
2015/05/29 职场文书
Python time库的时间时钟处理
2021/05/02 Python