详解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中datetime模块参考手册
Jan 13 Python
浅谈Python2.6和Python3.0中八进制数字表示的区别
Apr 28 Python
python批量从es取数据的方法(文档数超过10000)
Dec 27 Python
Python2与Python3的区别实例分析
Apr 11 Python
django创建简单的页面响应实例教程
Sep 06 Python
python模块hashlib(加密服务)知识点讲解
Nov 25 Python
Python实现手机号自动判断男女性别(实例解析)
Dec 22 Python
django3.02模板中的超链接配置实例代码
Feb 04 Python
Django操作session 的方法
Mar 09 Python
django的autoreload机制实现
Jun 03 Python
浅析python函数式编程
Sep 26 Python
通过代码实例了解Python3编程技巧
Oct 13 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读取mysql的简单实例
2014/01/15 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
PHP创建PowerPoint2007文档的方法
2015/12/10 PHP
php获取远程图片并下载保存到本地的方法分析
2016/10/08 PHP
PHP重定向与伪静态区别
2017/02/19 PHP
PHP判断是否是微信打开,浏览器打开的方法
2018/03/14 PHP
基于node实现websocket协议
2016/04/25 Javascript
微信小程序 实例应用(记账)详解
2016/09/28 Javascript
浅谈react.js 之 批量添加与删除功能
2017/04/17 Javascript
JS组件系列之JS组件封装过程详解
2017/04/28 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
2017/08/19 Javascript
JavaScript实现图片轮播特效
2019/10/23 Javascript
[03:49]显微镜下的DOTA2第十五期—VG登基之路完美团
2014/06/24 DOTA
使用python删除nginx缓存文件示例(python文件操作)
2014/03/26 Python
Python实现扫描指定目录下的子目录及文件的方法
2014/07/16 Python
Python实现的简单文件传输服务器和客户端
2015/04/08 Python
Python常见工厂函数用法示例
2018/03/21 Python
Python使用matplotlib实现的图像读取、切割裁剪功能示例
2018/04/28 Python
Python实现基于KNN算法的笔迹识别功能详解
2018/07/09 Python
解决python3 安装完Pycurl在import pycurl时报错的问题
2018/10/15 Python
Python3列表内置方法大全及示例代码小结
2019/05/10 Python
Apache,wsgi,django 程序部署配置方法详解
2019/07/01 Python
python pandas模块基础学习详解
2019/07/03 Python
安装2019Pycharm最新版本的教程详解
2019/10/22 Python
Django异步任务线程池实现原理
2019/12/17 Python
理肤泉俄罗斯官网:La Roche-Posay俄罗斯
2018/07/24 全球购物
慕尼黑山地运动、户外服装和体育用品专家:Sporthaus Schuster
2019/08/27 全球购物
财务分析个人的自荐书范文
2013/11/24 职场文书
4s店总经理岗位职责
2013/12/31 职场文书
党风廉政承诺书
2014/03/27 职场文书
综艺节目策划方案
2014/06/13 职场文书
另类冲刺标语
2014/06/24 职场文书
2015年挂职干部工作总结
2015/05/14 职场文书
全陪导游词开场白
2015/05/29 职场文书
大学生活委员竞选稿
2015/11/21 职场文书
2019员工保密协议书(3篇)
2019/09/23 职场文书