python之装饰器补充与递归函数与二分查找
多层装饰器
我们已经知道了语法糖的作用是将装饰对象自动装饰到装饰器中,一个语法糖的应用我们已经学会了,那么多个语法糖该怎么应用呢?
让我们来看一串代码:
# 装饰器outer1
def outer1(func1):
print('加载了outer1')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
# 装饰器outer2
def outer2(func2):
print('加载了outer2')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
# 装饰器outer3
def outer3(func3):
print('加载了outer3')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
# 连用三个语法糖
@outer1
@outer2
@outer3
def index():
print('from index')
当连用多个语法糖的时候,优先执行靠近装饰对象的语法糖,并且直到最远的语法糖才会赋值给装饰对象的函数名。
也就是说,在上述代码中,优先执行@outer3,将wrapper3装饰到index中,但此时不会赋值给index函数名,执行到@outer1时,这时就会执行赋值语句,也就是index = outer3(index)。
这三句语法糖总的来说:index = outer3(outer2(outer1(index))),就相当于执行力这段语句。
执行结果:

有参装饰器
我们都知道,装饰器里面只有一个形参,这个形参用于接收函数的名字,那么我们应该如何在给装饰器传一些额外参数进去呢?
需要一些额外参数的装饰器:
def outer(func_name):
def inner(*args, **kwargs):
"""此时这里需要一个参数用于决定处理数据的方式"""
if source_data == '1':
print('操作方式1')
elif source_data == '2':
print('操作方式1')
elif source_data == '3':
print('操作方式1')
else:
print('其他操作情况')
res = func_name(*args, **kwargs)
return res
return inner
@outer()
def index():
print('from index')
这个装饰器里的source_data应该在哪传进去呢?
很明显,装饰器outer括号里面是不能更改的,因为它要用于接收函数名,inner显然也是不能更改的,它要用于接收装饰对象的参数。

解决方法:在装饰器外层在套一个函数
# 最外层函数,可以接收参数给装饰器使用
def outer_outer(source_data):
# 装饰器
def outer(func_name):
def inner(*args, **kwargs):
if source_data == '1':
print('操作方式1')
elif source_data == '2':
print('操作方式1')
elif source_data == '3':
print('操作方式1')
else:
print('其他操作情况')
res = func_name(*args, **kwargs)
return res
return inner
# 这里返回装饰器的函数名
return outer
"""
这段语法糖会优先执行函数
因为outer_outer函数返回的是装饰器的名字
所以变成了@outer,又回到了最初的语法糖
"""
@outer_outer('3')
def index():
print('from index')
递归函数
在编程语言中,函数直接或间接调用函数自身,则该函数称为递归函数。
基本演示
# 直接调用自身
def index():
print(1)
# 在函数内部调用了自身
index()
index()
# 间接调用自身
def a():
print('a')
# a函数中调用b函数
b()
def b():
print('b')
# b函数中调用a函数
a()
a()
简单的来说,就是套娃,但是要注意,递归函数最好有个可以让它结束继续递归的条件,不然python解释器就会报错。

这段报错说明你的函数超过了最大递归深度,也可以说是最大递归次数,超过了这个次数就会报错
斐波那契数列
一个数列如果它的前2项数值为1,从第三项开始每一项等于前2项之和,那么这个数列称为斐波那契数列。

代码实现:
def f(a):
# 前2项为1
if a <= 2:
return 1
# 每一项等于前2项之和
res = f(a - 1) + f(a - 2)
return res
print(f(6)) # 结果:8
总结
- 递归就是函数直接或间接调用自身
- 递归一定要有可以结束的条件
- 递归过程中,每进行一次递归都要离结束近一点

小拓展
获取默认最大递归深度
import sys
print(sys.getrecursionlimit())
修改最大递归深度
sys.setrecursionlimit(2000)
算法之二分法
在了解二分法之前,我们得先了解什么是算法。
算法其实就是解决问题的有效方法,在大多数情况下,它可以让问题的解决更加的迅速。
简介
我们在查找列表中某一个值的所在位置的时候,除了使用index()函数外,在没有接触算法之前,最简单易懂是不是就是将列表中的元素遍历一遍,一个个比较过去?
这种方法只能作用在比较小的列表中,那如果遇到了有着几十万元素的列表的时候,我们就无法使用这种遍历的方法了,这时候就可以使用二分法了。

二分法:对一个已经排序好的数据集从1/2处开始查找。
如果是降序数据集:如果比1/2处的值大了,去掉右边的数据,去比对左边的1/2处;如果比1/2的值小了,去掉左边的数据,去比对右边的1/2处;直到找到为止。
如果是升序数据集:如果比1/2处的值大了,去掉左边的数据,去比对右边的1/2处;如果比1/2的值小了,去掉右边的数据,去比对左边的1/2处;直到找到为止。
举例
找到[1, 2, 3, 4, 5, 6, 7, 8, 9]中的3
"""普通二分法查找"""
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def get_target(l1, target_num):
i = 0
j = len(l1)
while i != j:
# 列表的1/2处
half_l1 = (i + j) // 2
if l1[half_l1] == target_num:
print('找到了!在第%s个' % (half_l1 + 1))
break
elif target_num > l1[half_l1]:
# 如果值比1/2处的大,查找范围变为[half_l1:j]
i = half_l1 + 1
else:
# 如果值比1/2处的小,查找范围变为[i:half_l1]
j = half_l1
else:
# 直到i == j了都没找到说明没有这个值
print('没找到!')
get_target(l, 3)
"""递归二分法查找"""
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
def get_target(l1, target_num):
if len(l1) == 0:
print('没找到!')
return
# 列表的1/2处
half_l1 = len(l1) // 2
if target_num == l1[half_l1]:
print('找到了!')
elif target_num > l1[half_l1]:
# 如果比1/2处的值大了,去掉左边的数据,去比对右边的1/2处
get_target(l1[half_l1 + 1:], target_num)
else:
# 如果比1/2处的值小了,去掉右边的数据,去比对左边的1/2处
get_target(l1[:half_l1], target_num)
get_target(l, 30)
总结
二分查找虽然在数据大的情况下查找更为迅速,但也有缺陷:
- 数据集必须为升序或降序
- 如果要查找的元素在数据的开头,二分查找更为复杂
python之装饰器补充与递归函数与二分查找的更多相关文章
- Python札记 -- 装饰器补充
本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...
- python day6 装饰器补充,正则表达式
目录 python day 6 1. 装饰器decorator 2. 正则表达式re 2.1 正则表达式概述 2.2 re模块常用方法 python day 6 2019/10/09 学习资料来自老男 ...
- python函数(4):递归函数及二分查找算法
人理解循环,神理解递归! 一.递归的定义 def story(): s = """ 从前有个山,山里有座庙,庙里老和尚讲故事, 讲的什么呢? ""& ...
- 13.Python略有小成(装饰器,递归函数)
Python(装饰器,递归函数) 一.开放封闭原则 软件面世时,不可能把所有的功能都设计好,再未来的一两年功能会陆续上线,定期更新迭代,软件之前所用的源代码,函数里面的代码以及函数的调用方式一般不 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
- 详解Python的装饰器
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
- Python的装饰器实例用法小结
这篇文章主要介绍了Python装饰器用法,结合实例形式总结分析了Python常用装饰器的概念.功能.使用方法及相关注意事项 一.装饰器是什么 python的装饰器本质上是一个Python函数,它可以让 ...
- 第五章 Python之装饰器
函数对象 函数是第一类对象:即函数可以当作数据传递 #可以被引用,可以被当作参数传递,返回值可以是函数,可以当作容器类型的元素 #引用 def func(x,y): print(x,y) f=func ...
- 我终于弄懂了Python的装饰器(四)
此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 四 ...
随机推荐
- 从CSS盒子模型说起
前言 总括: 对于盒子模型,BFC,IFC和外边距合并等概念和问题的总结 原文地址:从CSS盒子模型说起 知乎专栏:前端进击者 博主博客地址:Damonare的个人博客 为学之道,莫先于穷理:穷理之要 ...
- fetch,终于认识你
fetch和XMLHttpRequest 如果看网上的fetch教程,会首先对比XMLHttpRequest和fetch的优劣,然后引出一堆看了很快会忘记的内容(本人记性不好).因此,我写一篇关于fe ...
- Exchange 2013 清空邮箱
在某些应用场景中,需要清空用户邮箱的所有数据.如果使用Outlook web app或者Outlook 的邮件删除方式,对数以千计的邮件来说,实在不是一个好办法.exchange管理员可以使用&quo ...
- 在create-react-app使用less与antd按需加载
使用antd按需加载 使用react-app-rewired对 create-react-app 的默认配置进行自定义 yarn add react-app-rewired --dev /* pack ...
- python的数据库编程
数据库的基础知识 一.数据库的概念 数据库将大量数据按照一定的方式组织并存储起来,是相互关联的数据的集合.数据库中的数据不仅包括描述事物数据的本身,还包括相关数据之间的联系.数据库可以分为关系型数据库 ...
- 启动jar包的shell脚本
在jar包的同级目录新建文件例如:app_jar.sh 然后填写如下内容: #!/bin/bash #source /etc/profile # Auth:Liucx # Please change ...
- instanceof 和类型转换
instanceof 和类型转换 instanceof 判断a 和 B 类型是否相似 公式 System.out.println(a instanceof B); //true / false 编译是 ...
- 使用IDEA生产JavaDoc文档
源代码 package com.*****.base; //文档注解 /** * @Author intelliyu * @version 1.0 //版本 * since 1.8 //指明需要最早使 ...
- Python 交互式解释器的二三事
学 Python 不知道何时起成了一种风尚.这里,我也随便聊聊跟Python 的交互式解释器的几个有意思的小问题. 如何进入 Python 交互解释器? 当你安装好 Python 后,如何进入 Pyt ...
- 深入浅出聊Taier—大数据分布式可视化DAG任务调度系统
导读: 上周,袋鼠云数栈全新技术开源规划--DTMO(DTstack Meetup Online)的第一场直播圆满完成.袋鼠云数栈大数据开发专家.Taier项目主导人偷天为大家带来了<Taier ...