Python模块化编程与装饰器
Python的模块化编程
我们首先以一个例子来介绍模块化编程的应用场景,有这样一个名为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函数式编程之装饰器(一)
1.开放封闭原则 简单来说,就是对扩展开放,对修改封闭 在面向对象的编程方式中,经常会定义各种函数. 一个函数的使用分为定义阶段和使用阶段,一个函数定义完成以后,可能会在很多位置被调用 这意味着如果函 ...
- python高级编程之装饰器04
from __future__ import with_statement # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrat ...
- python函数式编程之装饰器(二)
以前用装饰器,都是定义好了装饰器后,使用@装饰器名的方法写入被装饰函数的正上方 在这里,定义的装饰器都是没有参数的 在定义装饰器的函数的时候,没有在括号里定义参数,这就叫做无参装饰器 既然有无参装饰器 ...
- Python函数式编程之装饰器
原则:对修改是封闭的,对扩展是开放的,方法:一般不修改函数或者类,而是扩展函数或者类 一:装饰器 允许我们将一个提供核心功能的对象和其他可以改变这个功能的对象’包裹‘在一起, 使用装饰对象的任何对象与 ...
- Python编程举例-装饰器
装饰器的通常用途是扩展已定义好的函数的功能 一个浅显的装饰器编程例子 #装饰器函数 def outer(fun): def wrapper(): #添加新的功能 print('验证') fun() r ...
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
- C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗
前言 最近成功把「前端带师」带入C#的坑(实际是前端带师开始从cocos转unity游戏开发了) 某天,「前端带师」看到这段代码后问了个问题:[这个是装饰器]? [HttpGet] public Re ...
- python函数与方法装饰器
之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...
- guxh的python笔记三:装饰器
1,函数作用域 这种情况可以顺利执行: total = 0 def run(): print(total) 这种情况会报错: total = 0 def run(): print(total) tot ...
随机推荐
- 题解-CTS2019 珍珠
题面 CTS2019 珍珠 有 \(n\) 个在 \([1,d]\) 内的整数,求使可以拿出 \(2m\) 个整数凑成 \(m\) 个相等的整数对的方案数. 数据范围:\(0\le m\le 10^9 ...
- 前端js实现九宫格模式抽奖(多宫格抽奖)
介绍: 前端九宫格是一种常见的抽奖方式,js实现如下,掌握其原理,不论多少宫格,都可以轻松应对.(代码可复制直接运行看效果). 该案例以四宫格入门,可扩展多宫格,奖品模块的布局可自由设置. <! ...
- Goldengate搭建
OGG进程 捕获进程(源端):捕获online redo log或者archived log中增量事务日志 传输进程(源端):把目标端落地的trail文件通过配置的路由信息传输到目标端 网络传输:tc ...
- Sql Server 数据把列根据指定的内容拆分数据
今天由于工作需要,需要把数据把列根据指定的内容拆分数据 其中一条数据实例 select id , XXXX FROM BIZ_PAPER where id ='4af210ec675927fa016 ...
- YT Downloader视频下载器
简介 YT Downloader视频下载器是一款非常知名的视频下载器,支持下载YouTube,Facebook,Dailymotion,Vimeo,Metacafe等数百个视频网站的视频 截图介绍 小 ...
- mini-web框架-WSGI-mini-web框架-多进程,面向对象的服务器(5.1.1)
@ 目录 1.说明 2.代码 关于作者 1.说明 使用多进程 积极主动python多进程是复制资源,线程是共享变量 所以这个的socket要关两次,因为复制文件的时候,是把文件的fd给复制过去(fil ...
- CTF-源码泄露-PHP备份文件的两种格式
参考大佬文章: https://www.cnblogs.com/yunqian2017/p/11515443.html https://blog.csdn.net/xy_sunny/article/d ...
- rocketMq 消息偏移量 Offset
消息偏移量 Offset queue0 offset 0 0-20 offset 4 20-40 纠错:每条消息的tag对应的HashCode. queue1 offset 1 0-20 ...
- java基础:进制详细介绍,进制快速转换,二维数组详解,循环嵌套应用,杨辉三角实现正倒直角正倒等腰三角,附练习案列
1.Debug模式 1.1 什么是Debug模式 是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序. 1.2 Debug介绍与操作流程 如何加断点 选择 ...
- C# 委托、事件、表达式树理解
1.什么是委托? 委托是一种动态调用方法的类型,属于引用型. 委托是对方法的抽象和封装.委托对象实质上代表了方法的引用(即内存地址) 所有的异步都是委托 委托就是函数当入参 委托被各种语法糖遮 ...