递归,二分法,面向对象,类
day26
递归
# 例子1:问年龄 def age(n): if n == 1: return 10 else: return age(n - 1) + 2 print(age(5)) # 结果为18 # 例子2: def func(n): if n == 10: return print("from func..") func(n - 1) func(10)
递归深度查看与设置:
import sys print(sys.getrecursionlimit()) # 获取到最大递归深度为 1000 sys.setrecursionlimit(10000) # 将递归深度设置设为1万,虽然调了但是如果内存不够的话也没什么用,执行深度太深的话会报错
递归特点:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用时通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
递归用途:递归用在不知道循环多少次的情况下
例子3:列表是从小到大有序排列的,传入数字18查询列表里是否存在
思路:如果列表值有10万个的时候,而要判断的值在列表靠后的位置,使用循环则需要循环9万多次才能找到,效率很低;
所以使用二分法+递归来实现,先和中间的值作比较,如果中间这个值小于传入的18就将列表进行切片和右边的一半进行比较,反之和左边的另一半进行比较。
data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 30, 32, 33, 35] # 传统方式: num = 18 i = 0 while True: if num == data[i]: print("---》 传统方式:find it.") break i += 1
# 递归方式 def search(num, data): print(data) # 打印每次data的值 lenth = len(data) if lenth > 1: # 当切片后的值大于1个时继续切片并判断 mid_index = int(lenth / 2) # 如果为小数会转为整数 mid_value = data[mid_index] if num > mid_value: # 进入右边开始切 data = data[mid_index:] search(num, data) elif num < mid_value: # 进入左边开始切 data = data[:mid_index] search(num, data) else: print("--》递归方式:find it") return else: # 当切片后的值只有1个时,单独判断值是否一致 if data[0] == num: print("--》递归方式:find it") else: print("--》递归方式:不存在") search(16, data)
输出结果:
[1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 30, 32, 33, 35] [1, 3, 6, 7, 9, 12, 14, 16, 17] [9, 12, 14, 16, 17] [14, 16, 17] --》递归方式:find it
函数式编程
不会改变外部值的状态
代码精简,但可读性差
python不是一种严格意义上的函数式编程语言编程方式不适合python,但也提供了一些相关的东西,如lambda,filter,map,reduce
面向对象的程序设计
参考博客:http://www.cnblogs.com/linhaifeng/articles/6182264.html
优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如游戏中一个任务参数的特征和技能修改都很容易。
缺点:可控性差。
类
class Garen: camp = "Demacia" # 在类里声明一个变量 def attack(self): # print("attack")
如何实使用类:
一:实例化
obj = Garen() # 实例化,obj为对象 print(obj) # 结果为:<__main__.Garen object at 0x000001EF65838EF0> print(obj.attack()) # 得到结果 attack
二:引用类的特征(类的变量)和技能(类的函数)
print(Garen.camp) # 结果得到camp的值 Demacia print(Garen.attack) # 结果得到 <function Garen.attack at 0x000001EF658398C8> print(Garen.attack(123123)) # 得到结果 attack
说明:
通过类名调用类里面的attack(),此时attack(self)为一个函数,里面的位置参数self需要按照函数的规范进行传递。
实例化后的对象调调里面的attack(),此时的attack(self)为一个方法,在调用时,里面的self就是对象名,会自动传递即obj.attack(obj),所以不用加参数.
例子2:
__init__()方法与参数
class Garen: camp = "Demacia" def __init__(self, nickname): self.nick = nickname # 相当于 g1.nick = "草丛伦" def attack(self, enemy): print("%s attack %s" % (self.nick, enemy)) g1 = Garen("草丛伦") # 实例化会自动触发类里面 __init__() 的运行,而__init__()有一个nickname参数也需要传递 g1.attack("alex") # 方法有一个新的位置参数enemy,调用时需要传递,结果为:草丛伦 attack alex g2 = Garen("贱人") g2.attack("张三") # 结果为:贱人 attack 张三
总结:
类: 一:实例化, 二:引用名字(类名.变量名,类名.函数名)
实例:引用名字(实例名.类的变量,实例名.绑定方法,实例名.实例自己的变量名)
增删改查:
# 查 print(Garen.camp) # 改 Garen.camp = "aaaa" print(Garen.camp) # 删 del Garen.camp # 增 Garen.x = 1 print(Garen.x)
# 查 g1 = Garen("alex") print(g1.nick) # 改 g1.nick = "asb" print(g1.nick) # 删 del g1.nick print(g1.nick) # 增 g1.sex = "female" print(g1.sex)
复习:
面向对象的程序设计(OOD)
找对象-----> 找类(归纳对象共同的特征与技能,还有每个对象独有的特征)
面向对象的编程(OOP)
先定义类-------> 再实例化出对象
# OOD: 定义学生类
特征:共同国籍“China”
技能:查看成绩
独有的特征:ID、名字、性别、省
# OOP:
class Student: country = "China" def __init__(self, ID,NAME,SEX,PROVINCE ): self.id = ID self.name = NAME self.sex = SEX self.province = PROVINCE def search_score(self): print("tell score") def study(self): print("study") # 实例化 s1 = Student("124345463243223", "cobila", "female", "sahngxi") # 上面实例化就相当于以下,会触发__init__()方法: Student.__init__(s1, "124345463243223", "cobila", "female", "sahngxi") s2 = Student("124345463223511", "goudan", "female", "zhejiang") # 对象可以使用类里的特征和技能了: s1.search_score() s1.study() s2.study()
共有 0 条评论