python系列4之装饰器
目录
- 递归算法解析
- 冒泡排序解析
- 装饰器解析
一. 递归
1. 递归的定义
递归(Recursion),又成为递回,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。递归一词还较长用于描述以自相似方法重复事物的过程。
斐波那契数列是典型的递归案例:
F0 = 0(初始值)
F1 = 1(初始值)
对所有大于1的整数n: F(n) = F(n - 1) + F(n - 2)(递归定义)
尽管有许多数学函数均可以递归表示,但在实际应用中,递归的开销过大,因此在不是必要的情况下最好不要用到递归。
2. 递归的原理
(1). 例题:
def recursion(defth, a1, a2):
if defth == 5:
return a1
a3 = a1 + a2
defth = defth + 1
print(a1)
a1 = recursion(defth, a2, a3)
return a1
ret = recursion(1, 0, 1)
print(ret)
以下这幅图为整个函数的执行过程,红色的代表一层一层的往里面嵌套,绿色的代表函数的返回值一层一层的外面返还。其实递归就是这个原理,通过一个函数的执行流在再次进入此函数,当通过一个条件返回一个值之后,一层一层的按照刚刚的执行流再次返回回去,最后得到返回值,但是递归的时候要注意两点:
1. 他的条件,必须要使他的递归在某个条件内可以返回一个值,否则就会一直递归,直到电脑资源耗尽(Python默认有递归的次数限制)
2. 返回值,在里面的递归函数一般要给予他一定的返回值,否则在最后一次返还递归的时候会得不到想要的值。
二. 冒泡排序
1. 冒泡排序原理
冒泡排序就是一种简单的排序算法。他重复的走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
冒泡排序算法的运作如下:
1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
3. 针对所有的元素重复以上的步骤,除了最后一个。
4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
交换数据的原理
借助一个外围的变量先保存原来的值,然后再去通过指向地址的转换来进行交换数据。注意:当temp指向了a, 然后a再指向b的时候,temp本身的指向是没有发生改变的,就如下图,a指向了b,但是temp依然指向的是a的地址,所以他还是66
a = 66
b = 88
temp = a
a = b
b = temp
冒泡排序的原理
2. 冒泡排序事例
# -*- coding:utf-8 -*-
# zhou
# 2017/6/17
list = [0, 88, 99, 33, 22, 11, 1]
for j in range(1, len(list)):
for i in range(len(list) - j):
# 如果第一个数据大, 则交换数据, 否则, 不做改变
if list[i] > list[i + 1]:
temp = list[i]
list[i] = list[i + 1]
list[i + 1] = temp
print(list)
三. 装饰器
1. 装饰器定义
装饰器是什么呢?简单来说就是在不改变源函数代码的基础上,对代码的一种微妙的扩展,以使得其功能进一步增强的函数。装饰器就是一个函数,一个加载在其他函数之上的函数,
以下我们先来了解几个概念:
<1>. 函数执行流
由以上面的可知,函数的执行流应该是从上到下的,也就是说,代码先把第一个test1加载到内存中,然后从新开辟一块内存来存放第二个test1。
这里应该是第一个test1的指向改到了890673481792这里。
def test1():
print('日本人.')
print(id(test1))
def test1():
print('中国人.')
print(id(test1))
test1() 执行结果:
890673481656
890673481792
中国人.
<2>. 函数作为变量
由以下结果可以看出来,函数名其实就是一个变量,可以用来传递的变量。
注意:函数作为变量的时候不能加括号,必须只是函数名
def test1():
print('我是.')
a = test1
print(a)
print(test1)
结果:
<function test1 at 0x000000E2D403C7B8>
<function test1 at 0x000000E2D403C7B8>
<3>. 函数嵌套
这里定义了三个函数,test1,test2,test3, 3里面嵌套了1, 1里面又嵌套了2,从他的结果中想必你也会看出来函数的执行流。
def test1():
print('我是',end='')
def test2():
print('中国人.')
test2() def test3():
test1()
print('Hello, China.')
test3() 结果:
我是中国人.
Hello, China.
2. 装饰器原理
(1). 装饰器的写法和使用
<1>. 装饰器也是一个函数
<2>. 使用装饰器的格式: 在一个函数前面加上:@装饰器的名字
(2). 装饰器的原理
<1>. 把test1函数当做一个变量传入outer中
func = test1
<2>. 把装饰器嵌套的一个函数inner赋值给test1
test1 = inner
<3>. 当执行test1函数的时候,就等于执行了inner函数,因此在最后的那个test1()命令其实执行的就是inner,因此先输出(你是哪国人)
<4>. 按照执行流执行到func函数的时候,其实执行的就是原来的test1函数,因此接着输出(我是中国人),并把它的返回值返回给了ret
<5>. 当原来的test1函数执行完了之后,继续执行inner里面的命令,因此输出了(Oh,hh, I love China.)
(3). 装饰器的总结
由上面的执行流可以看出来,其实装饰器把之前的函数当做参数传递进去,然后创建了另一个函数用来在原来的函数之前或者之后加上所需要的功能。
# -*- coding:utf-8 -*-
# zhou
# 2017/6/17
# 定义了一个装饰器outer
def outer(func):
def inner():
print('你是哪国人?')
ret = func()
print('Oh, hh, I love China.')
return inner
@outer
def test1():
print('我是中国人.')
test1()
3. 带参数的装饰器
为了装饰器的高可用,一般都会采用下面的方式,也就是无论所用的函数是多少个参数,这个装饰器都可以使用
Python内部会自动的分配他的参数。
# -*- coding:utf-8 -*-
# zhou
# 2017/6/17
def outer(func):
def inner(a, *args, **kwargs):
print('你是哪国人?')
ret = func(a, *args, **kwargs)
print('Oh, hh, I love China.')
return inner @outer
def test1(a, *args, **kwargs):
print('我是中国人.') test1(1)
3. 装饰器的嵌套
<1>. 第一层装饰器的简化(outer装饰器)
<2>. 第二层装饰器简化(outer0装饰器)
<3>. 装饰器嵌套攻击额,我们可以发现一层装饰器其实就是把原函数嵌套进另一个函数中间,因此我们只需要一层一层的剥开嵌套就可以了。
# -*- coding:utf-8 -*-
# zhou
# 2017/6/17
def outer0(func):
def inner():
print('Hello, Kitty.')
ret = func()
print('我是日本人.')
return inner def outer(func):
def inner():
print('你是哪国人?')
ret = func()
print('你呢?')
return inner
@outer0
@outer
def test1():
print('我是中国人.') test1() 结果Hello, Kitty.
你是哪国人?
我是中国人.
你呢?
我是日本人.
python系列4之装饰器的更多相关文章
- python设计模式之内置装饰器使用(四)
前言 python内部有许多内建装饰器,它们都有特别的功能,下面对其归纳一下. 系列文章 python设计模式之单例模式(一) python设计模式之常用创建模式总结(二) python设计模式之装饰 ...
- 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解
第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一. 引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
- 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 ...
- python 3.x 的装饰器笔记
今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找.虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python ...
- python 中多个装饰器的执行顺序
python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...
- Python函数编程——闭包和装饰器
Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...
- python基础-内置装饰器classmethod和staticmethod
面向对象编程之classmethod和staticmethod classmethod 和 staticmethod都是python内置的装饰器 classmethod 的作用:给在类内部定义的方法装 ...
随机推荐
- HTML的行内元素与块级元素的区别?
块级元素:独占一行,其宽度自动填满父元素的宽度,可以容纳行内元素和其他块级元素,可以设置margin和padding值. 行内元素:不会独占一行,与其他行内元素排成一行,直到其父元素拍不下,才会从新一 ...
- Linux 学习 二, 安装JDK
我是利用在window环境下载好JDK,然后传到VMware中linux中 下载JDK http://www.oracle.com/technetwork/java/javase/downloads/ ...
- u-boot分析(八)----串口初始化
u-boot分析(八) 上篇博文我们按照210的启动流程,分析到了内存初始化,今天我们继续按照u-boot的启动流程对串口的初始化进行分析. 今天我们会用到的文档: 1. 2440芯片手 ...
- [原创] Debian9上配置软件阵列
序言 软阵列是用软件实现的磁盘阵列. 准备工作 1. 更新系统 没啥,就他喵想用个最新的. apt update && apt upgrade 2. 安装mdadm 如果系统没有自带m ...
- Appium 滑动界面swipe用法
Appium 滑动API:Swipe(int start x,int start y,int end x,int y,duration) 解释:int start x-开始滑动的x坐标, int st ...
- centos7.4 系统安装指导
centos7 系统安装指导 安装前规划 下载安装文件 安装过程设置 安装后系统基本设置 安装前规划 CentOS 7.x系列只有64位系统,没有32位. 生产服务器建议安装CentOS-7-x86_ ...
- 如何在windows下安装配置pyspark notebook
第一步:安装anaconda anaconda自带一系列科学计算包 下载链接:http://pan.baidu.com/s/1b4jWlg 密码:fqq3 接着配置环境变量:如我安装在D盘下 试一 ...
- 笨办法学Python(二十二)
习题 22: 到现在你学到了哪些东西? 这节以及下一节的习题中不会有任何代码,所以也不会有习题答案或者加分习题.其实这节习题可以说是一个巨型的加分习题.我将让你完成一个表格,让你回顾你到现在学到的所有 ...
- 使用extentreports美化testng报告2,增加监听
有兴趣研究了extentreports报告美化插件,但是因为发现插件有很多内容不能自定义,所以放弃了这个插件,我扩充了官方代码的demo,在testng中增加了监听,并打印了一些测试用例,现在我把两个 ...
- 2月4号学习的一个SSM整合项目,第一课
本文引自:https://github.com/Sunybyjava/seckill 原作者:sunybyjava@gmail.com seckill 一个整合SSM框架的高并发和商品秒杀项目,学习 ...