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 的作用:给在类内部定义的方法装 ...
随机推荐
- Sublime Text Emmet插件 : 生成html,css 快捷键
(输入下面简写,按Tab键可触发效果,或者 ctrl + e) html缩写 输入 !后 按下 ctrl + e : 结果 <!DOCTYPE html><html lang=&qu ...
- Chrome浏览器安装vue-devtools插件
插件功能:方便在浏览器调试vue代码 插件git地址:https://github.com/vuejs/vue-devtools 因为chrome要FQ,打不开,所以不能直接进去安装拓展程序,只能选择 ...
- sass入门(一)
一].sass入门安装sass安装koala // sass中可以自定义变量 $fontStack: Microsoft Yahei; $primaryColor: #333; body { font ...
- Spark Job调度
Spark Job调度 1.概览 Spark有几种用于在计算之间调度资源的工具.首先,回想一下,如集群模式概述中所述,每个Spark应用程序(SparkContext的实例)都运行一组独立的execu ...
- 笨办法学Python(二十四)
习题 24: 更多练习 你离这本书第一部分的结尾已经不远了,你应该已经具备了足够的 Python 基础知识,可以继续学习一些编程的原理了,但你应该做更多的练习.这个练习的内容比较长,它的目的是锻炼你的 ...
- powershell远程连接
最近因为工作的需要看了看powershell相关的知识,个人总结了一点有关于powershell远程连接需要做的步骤,希望对别人有所帮助. 使用powershell远程连接,需要进行 设备的配置: 1 ...
- PHP:substr和mb_substr的区别
substr和mb_substr函数都是获取字符串中的某个部分 那么,它们的区别在哪儿呢? 区别: substr :全部是英语.数字就正常:但有一些的字元是占用多个位元的,substr()就得不到你预 ...
- SIEMENS Simotion 运动控制器设置Web service, HTTP, FTP访问密码
早期版本的web service, 访问密码是 用户名 : simotion 密码 : simotion 新版本,Firmware >= 4.4之后,考虑到安全性,控制器没有默认密码.设置密码方 ...
- Altium_Designer-PCB的覆铜步骤
1.覆铜的意义 覆铜,就是将PCB上闲置的空间作为基准面,然后用固体铜填充,这些铜区又称为灌铜.敷铜的意义在于,减小地线阻抗,提高抗干扰能力:降低压降,提高电源效率:还有,与地线相连,减小环路 ...
- 利用Js或Css滤镜实现IE6中PNG图片半透明效果 IE6PNG妥妥的
接下来介绍几种PNG图片在IE6中不透明的解决办法 1.用自己的PNG,让IE6一边去吧 首先制作PNG图片的时候,另存为一个GIF图片,因为IE6是支持GIF图片透明,然后在css定义 .pngte ...