详解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实现基本数据结构中队列的操作方法示例
Dec 04 Python
PyTorch学习笔记之回归实战
May 28 Python
pandas值替换方法
Jul 10 Python
python实现推箱子游戏
Mar 25 Python
python学生管理系统学习笔记
Mar 19 Python
python3.6环境安装+pip环境配置教程图文详解
Jun 20 Python
使用APScheduler3.0.1 实现定时任务的方法
Jul 22 Python
使用PyCharm进行远程开发和调试的实现
Nov 04 Python
Python 中 -m 的典型用法、原理解析与发展演变
Nov 11 Python
TensorFlow基本的常量、变量和运算操作详解
Feb 03 Python
DRF框架API版本管理实现方法解析
Aug 21 Python
vue.js刷新当前页面的实例讲解
Dec 29 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
php4的session功能评述(二)
2006/10/09 PHP
php intval的测试代码发现问题
2008/07/27 PHP
PHP中防止SQL注入实现代码
2011/02/19 PHP
php简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
DWZ+ThinkPHP开发时遇到的问题分析
2016/12/12 PHP
php操作redis常见方法示例【key与value操作】
2020/04/14 PHP
列表内容的选择
2006/06/30 Javascript
用dom+xhtml+css制作的一个相册效果代码打包下载
2008/01/24 Javascript
JavaScript中switch语句的用法详解
2015/06/03 Javascript
jQuery获取当前点击的对象元素(实现代码)
2016/05/19 Javascript
jQuery插件MovingBoxes实现左右滑动中间放大图片效果
2017/02/28 Javascript
js实现多行文本框统计剩余字数功能
2017/03/28 Javascript
Javascript刷新页面的实例
2017/09/23 Javascript
浅谈js获取ModelAndView值的问题
2018/03/28 Javascript
解决Vue.js由于延时显示了{{message}}引用界面的问题
2018/08/25 Javascript
JS实现数组去重及数组内对象去重功能示例
2019/02/02 Javascript
原生js实现trigger方法示例代码
2019/05/22 Javascript
vue中在vuex的actions中请求数据实例
2019/11/08 Javascript
mpvue微信小程序开发之实现一个弹幕评论
2019/11/24 Javascript
[05:35]DOTA2英雄梦之声_第13期_拉比克
2014/06/21 DOTA
Python的另外几种语言实现
2015/01/29 Python
简单谈谈Python流程控制语句
2016/12/04 Python
利用Python读取文件的四种不同方法比对
2017/05/18 Python
python双端队列原理、实现与使用方法分析
2019/11/27 Python
tensorflow获取预训练模型某层参数并赋值到当前网络指定层方式
2020/01/24 Python
pytorch实现保证每次运行使用的随机数都相同
2020/02/20 Python
python中Ansible模块的Playbook的具体使用
2020/05/28 Python
Python读写csv文件流程及异常解决
2020/10/20 Python
学前教育学生自荐信范文
2013/12/31 职场文书
元旦获奖感言
2014/03/08 职场文书
趣味运动会策划方案
2014/06/02 职场文书
班级出游活动计划书
2014/08/15 职场文书
遗失说明具结保证书
2015/02/26 职场文书
小学生优秀作文范文(六篇)
2019/07/10 职场文书
原生Js 实现的简单无缝滚动轮播图的示例代码
2021/05/10 Javascript
Python 类,对象,数据分类,函数参数传递详解
2021/09/25 Python