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的装饰器(四) 四 ...
随机推荐
- snippet,让你编码效率翻倍
为什么谈到Snippet 今天下午在用vscode做小程序的时候,发现很不方便,因为商店里提供的代码片段极为有限,而且平时几乎每天都需要用到代码片段,所以就在思考他们是怎么做到给别人提供代码的,我可以 ...
- python爬虫---爬取王者荣耀全部皮肤图片
代码: import requests json_headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win ...
- Python pip下载慢的解决方法
国外的源下载速度实在是太慢了 可以使用国内的一些镜像网站安装 使用cmd命令 格式:pip install -i 网站 库 例如: 国内的一些镜像网站 清华大学:https://pypi.tuna.t ...
- 彻底理解synchronized
1. synchronized简介 在学习知识前,我们先来看一个现象: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public ...
- 《头号玩家》AI电影调研报告(二)
四. 涉及前沿技术及与现实的交互 1.VR技术 在影片中,斯皮尔伯格用他认为未来的VR虚拟技术为我们创造了众多精彩的画面,令人佩服其对科技的预见性.其中好多的装备特别引人注目,部分也在现实中存在:VR ...
- 学习Java必用的9个网站,最后一个最好用!
Java语言已经成为IT编程界中一种持久的语言,从主要开放源码网站中统计的每月编程语言排名来看,Java一直位居榜首.因此,我们的程序员不能放弃学习Java呀!今日小编为大家整理了几个关于Java学习 ...
- SpringMVC获取请求参数-POJO类型参数
1.Controller中的业务方法的POJO参数的属性名与请求参数一致,参数值会自动映射匹配 1.创建POJO类 public class User { private String usernam ...
- LC-977
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序. 示例 1: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,1 ...
- String_StringBuilder_StringBuffer 区别
1.String: String类是final修饰的,属于不可变(immutable)类,每次对原对象操作都会产生新的String对象. 源码中String类的定义:private final cha ...
- 1903021116—吉琛—Java第六周作业—类的定义
项目 内容 课程班级博客链接 19信计班 这个作业要求链接 第六周作业链接 java面向对象的概念和定义 博客名称 学号-姓名-Java第六周作业-题目自拟 要求 每道题要有题目,代码(使用插入代码, ...