详解Python模块化编程与装饰器


Posted in Python onJanuary 16, 2021

我们首先以一个例子来介绍模块化编程的应用场景,有这样一个名为requirements.py的python3文件,其中两个函数的作用是分别以不同的顺序来打印一个字符串:

# requirements.py
def example1():
  a = 'hello world!'
  print (a)
  print (a[::-1])

def example2():
  b = 'hello again!'
  print (b)
  print (b[::-1])

if __name__ == '__main__':
  example1()
  example2()

其执行结果如下所示:

[dechin@dechin-manjaro decorator]$ python3 requirements.py 
hello world!
!dlrow olleh
hello again!
!niaga olleh

在两个函数中都使用到了同样的打印功能,这时候我们可以考虑,是不是可以将这两个打印语句封装为一个函数呢,这样不就可以重复利用了?这就是模块化编程思维的雏形,让我们先对样例代码进行模块化的改造:

# requirements.py
def rprint(para):
  print (para)
  print (para[::-1])

def example1():
  a = 'hello world!'
  rprint(a)

def example2():
  b = 'hello again!'
  rprint (b)

if __name__ == '__main__':
  example1()
  example2()

这里我们将两个打印语句的功能实现封装进了rprint的函数,执行结果如下:

[dechin@dechin-manjaro decorator]$ python3 requirements.py 
hello world!
!dlrow olleh
hello again!
!niaga olleh

结果当然还是与模块化之前一致的。

向下封装与向上封装

在上一章节中,我们讨论了python中的模块化编程。由于在编程过程中有可能有大量的代码需要复用,这时候就需要用一个函数来进行封装,来避免大量重复的工作。但是如果细分来看,这种封装模式只解决了一类的问题:向下封装。让我们再看一次上述改进后样例中的代码结构:

.
├── example1
│   └── rprint
└── example2
  └── rprint

我们可以发现,这里复用的rprint实际上属于两个example函数的下层,我们可以称之为向下封装了一个rprint函数。那么,如果我们转换一下需要复用的模块,变成如下的代码结构,那我们又需要用什么样的方式来实现呢?

.
├── example
│  └── rprint1
└── example
  └── rprint2

问题解读:该代码结构表示的意义为,有一个大的example函数,该函数内部嵌套不同的rprint函数可以实现不同的功能。为了方便理解,读者可以想象成是有两个函数example1和example2,这两个函数中除了rprint1和rprint2这两个函数模块不一致以外,其他的部分都是完全一样的,也就是可共用的。

Python的嵌套函数与装饰器

首先,我们为了复盘上述章节中的问题,来构造这样的一个python测试代码:

# requirements.py
def example1():
  def rprint1(para):
    print (para)
  a = 'hello world!'
  rprint1(a)

def example2():
  def rprint2(para):
    print (para[::-1])
  a = 'hello world!'
  rprint2(a)

if __name__ == '__main__':
  example1()
  example2()

以上代码的执行结果为:

[dechin@dechin-manjaro decorator]$ python3 requirements.py 
hello world!
!dlrow olleh

这个案例用到了python中嵌套函数的用法,在函数中可以嵌套实现另外的函数。这里我们注意到,虽然为了在同一个代码串中嫩够运行,两个example函数的名字取的不同,但是实际上内容是完全相同的,符合上一章节中遗留问题的代码结构。这里我们需要考虑的问题是,我们能否做到向上封装,将example的同样功能的代码实现进行归类?那么我们需要引入装饰器的用法,这里我们直接展示如何构造修饰器,以及修饰器使用的效果。

# decorator.py
def example(func):
  def wrapper(*args, **kwargs):
    a = 'hello world!'
    return func(a)
  return wrapper

@example
def rprint1(para):
  print (para)

@example
def rprint2(para):
  print (para[::-1])

if __name__ == '__main__':
  rprint1()
  rprint2()

这个代码的执行结果为:

[dechin@dechin-manjaro decorator]$ python3 decorator.py 
hello world!
!dlrow olleh

从结果上我们就可以看到,这个代码是实现了一样的效果。通过example这个装饰器,不仅封装了上层函数中所实现的功能,而且还有一个重大意义是,通过装饰器向下层函数传递了参数。这就使得,我们最终调用rprint函数的时候,不需要传入任何的参数,因为在example内已经定义了可以共享的参数。

关于Python装饰器的总结

Python的装饰器并不是一个非常难以实现的特性,其关键意义在于实现了向上封装的模块化编程。在我们过往的编程实现中,更多的是向下封装常用的、可复用的代码模块。这里通过Python所提供的装饰器特性,我们就可以将函数外部所共享的代码模块也进行封装。因此,由函数和装饰器分别实现的向下封装与向上封装的特性,共同构成了提高编码效率和编码可读性提升的模块化编程模式。

以上就是详解Python模块化编程与装饰器的详细内容,更多关于python 模块化编程与装饰器的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
在Python中使用__slots__方法的详细教程
Apr 28 Python
Python使用QRCode模块生成二维码实例详解
Jun 14 Python
Python探索之URL Dispatcher实例详解
Oct 28 Python
python+tkinter编写电脑桌面放大镜程序实例代码
Jan 16 Python
Python3.6基于正则实现的计算器示例【无优化简单注释版】
Jun 14 Python
python3人脸识别的两种方法
Apr 25 Python
python 使用装饰器并记录log的示例代码
Jul 12 Python
Python 格式化打印json数据方法(展开状态)
Feb 27 Python
keras中epoch,batch,loss,val_loss用法说明
Jul 02 Python
PyQt5的相对布局管理的实现
Aug 07 Python
解决Pytorch半精度浮点型网络训练的问题
May 24 Python
解决Pytorch dataloader时报错每个tensor维度不一样的问题
May 28 Python
删除pycharm鼠标右键快捷键打开项目的操作
Jan 16 #Python
基于pycharm 项目和项目文件命名规则的介绍
Jan 15 #Python
python制作抽奖程序代码详解
Jan 15 #Python
python中PyQuery库用法分享
Jan 15 #Python
python中pdb模块实例用法
Jan 15 #Python
python实现马丁策略的实例详解
Jan 15 #Python
pycharm 多行批量缩进和反向缩进快捷键介绍
Jan 15 #Python
You might like
PHP初学者头疼问题总结
2006/10/09 PHP
PHP高级对象构建 工厂模式的使用
2012/02/05 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
2019/03/12 PHP
javascript 获取select下拉列表值的代码
2009/09/07 Javascript
jQuery设置和移除文本框默认值的方法
2015/03/09 Javascript
Bootstrap Chart组件使用教程
2016/04/28 Javascript
JS仿hao123导航页面图片轮播效果
2016/09/01 Javascript
jquery Banner轮播选项卡
2016/12/26 Javascript
jQuery如何跳转到另一个网页 就这么简单
2016/12/28 Javascript
基于jquery trigger函数无法触发a标签的两种解决方法
2018/01/06 jQuery
jQuery中可见性过滤器简单用法示例
2018/03/31 jQuery
对Vue.js之事件的绑定(v-on: 或者 @ )详解
2018/09/15 Javascript
用Fundebug插件记录网络请求异常的方法
2019/02/21 Javascript
基于 jQuery 实现键盘事件监听控件
2019/04/04 jQuery
[01:14]英雄,所敬略同——2018完美盛典宣传视频
2018/12/05 DOTA
Python+django实现文件上传
2016/01/17 Python
利用python微信库itchat实现微信自动回复功能
2017/05/18 Python
django项目运行因中文而乱码报错的几种情况解决
2017/11/07 Python
详解Python最长公共子串和最长公共子序列的实现
2018/07/07 Python
修改默认的pip版本为对应python2.7的方法
2018/11/06 Python
pycharm 取消默认的右击运行unittest的方法
2018/11/29 Python
基于python二叉树的构造和打印例子
2019/08/09 Python
python用tkinter实现一个简易能进行随机点名的界面
2020/09/27 Python
英国电子专家:maplin
2019/09/04 全球购物
GWT的应用有哪两种部署模式
2012/12/21 面试题
宠物店的创业计划书范文
2014/01/11 职场文书
上班离岗检讨书
2014/01/27 职场文书
中学家长会邀请函
2014/02/03 职场文书
合作意向书模板
2014/03/31 职场文书
四风对照检查材料思想汇报
2014/09/20 职场文书
幼儿园门卫安全责任书
2015/05/08 职场文书
入党积极分子半年考察意见
2015/06/02 职场文书
大学毕业谢师宴致辞
2015/07/27 职场文书
公司车辆管理制度
2015/08/04 职场文书
单位车辆管理制度
2015/08/05 职场文书
大队委员竞选演讲稿
2015/11/20 职场文书