php yield 递归,day_4:计时,递归深度,yield,定制类,Method xxx may be 'static'

斐波那契数列的具体实现方式并不难,但是利用python的诸多特性它会有许多便利的实现;便利一方面是对于大规模计算时候的运行时间短,一方面是占用内存少。同时我在实现过程中遇到的一些小问题。

计时

为了计算代码递归运行的时间,所以顺便介绍一下

我选择使用time.process_time()方法

该方法能够返回系统和CPU运行当前进程的时间,不过有个问题就是所返回时间的参考点(大概是指类似计时开始的时间)是未知的,因此返回的时间并不能作为一个真正的参考依据,只有两个不同进程的process_time()返回值之间的差值,才是有意义的。

差值是有意义的,那么对于我的使用已经足以了。

import time

t = time.process_time()

递归深度

以下是我自己写的两种方式获得斐波那契数列的某个值,肯定不会是最优的,但已经能够反映迭代与递归之间的区别了。

import time

class Fibo:

def get_certain_rec(self, n): # 递归获取斐波那契数列第n+1个值

if n == 0:

return 0

elif n == 1:

return 1

else:

return self.get_certain_rec(n - 1) + self.get_certain_rec(n - 2)

@staticmethod

def get_certain(n): # 迭代方式

fibo_0 = 0

fibo_1 = 1

if n == 0:

return 0

elif n == 1:

return 1

else:

for i in range(2, n+1):

fibo_n = fibo_0 + fibo_1

fibo_0, fibo_1 = fibo_1, fibo_n

return fibo_n

t = time.process_time()

f = Fibo()

f.get_certain(1000)

print(t)

>>>0.0625

t = time.process_time()

f = Fibo()

f.get_certain_rec(1000)

print(t)

>>>RecursionError: maximum recursion depth exceeded in comparison

面对大规模问题的时候,递归方法直接被抛出递归深度达到最大,或许能够通过改变默认递归深度解决该问题,但远不如使用迭代方法来处理。

并且,我们要知道,凡是能够写成递归的方法,就一定也有迭代的解决方法。

t = time.process_time()

f = Fibo()

f.get_certain(100)

print(t)

>>>0.046875

t = time.process_time()

f = Fibo()

f.get_certain_rec(100)

print(t)

>>>

# 虽然没出问题。。。。不过跑了很久都还没出结果

规模还没有特别大,递归就已经跑不动了;而迭代法的时间几乎没有变化,可能是常数级的运行时间。

个人认为,用递归的思想思考如何解决问题,用迭代的方法来实际解决问题。

修改递归深度

import sys

sys.setrecursionlimit(1000000000)

yield

直接print一个生成器返回的是 at 0x00000255F11DA200>,它在内存中的位置。

需要使用next()方法才能够获取生成器的值;

生成器generator也是一个可迭代对象,可以被for循环调用;

yield只能在函数中使用;

yield是定义生成器的方法之一;定义的函数中若有yield语句,那么它就是一个generator;

调用yield b会使得函数中断并返回b;循环的话则会在yield处中断并返回一个值,再次执行时从上次调用yield的地方继续进程。

定制类

来看看廖老师对于斐波那契数列的写法

廖雪峰的教程,关于定制类

class Fib(object):

def __init__(self):

self.a, self.b = 0, 1 # 初始化两个计数器a,b

def __iter__(self):

return self # 实例本身就是迭代对象,故返回自己

def __next__(self):

self.a, self.b = self.b, self.a + self.b # 计算下一个值

if self.a > 100000: # 退出循环的条件

raise StopIteration()

return self.a # 返回下一个值

# 使用了诸如__iter__、__next__等实现了类似iterable的方法

这些以双下划线开头和结尾的特殊类方法,是会被python的函数调用的,因此定义这些特殊方法,可以实现我们对于一些方法的定制,比如为print函数输出的内容添加一种固定格式。

Method xxx may be 'static'

这是用pycharm写代码时候它提示的一个小问题,认为该方法是个静态方法。

当你在类中定义一个与类的属性无关的方法的时候,便可以认为是在定义一个静态方法。

@staticmethod

def```

# 这就定义了一个静态方法

除此之外还有一个类定义@classmethod

其作用在于使得该方法能够直接被方法调用而无需创建一个实例,不过不经常被使用。

最后附上自己写的斐波那契数列的获得方法

class Fibo:

@staticmethod

def get_all(n): # 用于获取斐波那契数列前n+1个值,也可以通过列表获取任意值

seq = list()

for i in range(n+1):

if len(seq) == 0:

seq.append(0)

elif len(seq) == 1:

seq.append(1)

else:

seq.append(seq[i-1] + seq[i-2])

return seq

def get_certain_rec(self, n): # 递归获取斐波那契数列第n+1个值

if n == 0:

return 0

elif n == 1:

return 1

else:

return self.get_certain_rec(n - 1) + self.get_certain_rec(n - 2)

@staticmethod

def get_certain(n): # 迭代方式

fibo_0 = 0

fibo_1 = 1

if n == 0:

return 0

elif n == 1:

return 1

else:

for i in range(2, n+1):

fibo_n = fibo_0 + fibo_1

fibo_0, fibo_1 = fibo_1, fibo_n

return fibo_n

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值