十三、递归及反射
递归原理:递归要慎用
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368
我们发现其规律为:后一个数等于它前面两个数之和
需求:
打印出如上所述序列:
def func(arg1,arg2):
if arg1 == 0:
print (arg1, arg2)
arg3 = arg1 + arg2
print (arg3)
func(arg2, arg3)
func(0,1)
递归的特点就是函数自己调用自己
典型的应用就是通过递归实现简单计算功能:
如下,需要计算这个的值
a = '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
def handle(a):
#获取只包含数字和+-*/
#1-2*((60-30+( #我把它截断成三段
#-40/5 = -8 #先把这个-40/5的值算出来
#)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) #第三段
#b = 新表达式
handle(b)
handle(a)
=========================================================================================
=========================================================================================
=========================================================================================
递归返回值:
def func(arg1,arg2):
if arg1 == 0:
print (arg1, arg2)
arg3 = arg1 + arg2
print (arg3)
if arg3 > 1000:
return arg3
func(arg2, arg3)
result = func(0,1)
print (result)
我们会发现,它的结果居然是None,正确写法应该是这样:
def func(arg1,arg2):
if arg1 == 0:
print (arg1, arg2)
arg3 = arg1 + arg2
print (arg3)
if arg3 > 1000:
return arg3
return func(arg2, arg3)
result = func(0,1)
print (result)
==========================================================================================
==========================================================================================
==========================================================================================
递归执行流程剖析:
def n5():
return 1500
def n4():
n5()
def n3():
n4()
def n2():
n3()
def n1():
n2()
result = n1()
print (result)
问:result的值是多少?答:None
因为n5的返回值是1500,但是是n4在调用n5,所以n4接收了1500这个值,但是n4接收了1500这个值不带表它返回了1500这个值,n4的返回值是None,类似往下走,一直到n1,返回值也是None
问:如果我要n1的返回值是1500应该怎么做?
答:
def n5():
return 1500
def n4():
return n5()
def n3():
return n4()
def n2():
return n3()
def n1():
return n2()
result = n1()
print (result)
这样就等同于所有的返回值n1=n2=n3=n4=n5=1500
对照递归的例子,是同理的
=============================================================================
=============================================================================
递归的另外两个经典:阶乘和幂
1.阶乘n*(n-1)*(n-2)......*1
普通算法:
def factorial(n):
result = n
for i in range(1,n):
result *= 1
return result
递归算法:
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
2.幂运算power(2,3),即2的3次幂,2*2*2=8
普通算法:
def power(x,n):
result = 1
for i in range(n):
result *= x
return result
递归算法:
def power(x,n):
if n == 0:
return 1
else:
return x * power(x,n-1)
============================================================================
=============================================================================
反射:
应用情景:假设我现在Myclass类下面有100个方法,我希望用户输入‘sayhi’我就调用sayhi方法,输入‘info’我就调用info方法,你如果通过if判断的话要写100个,而通过反射则简便的多,反射的应用相当广。
class Myclass(object):
def sayhi(self):
print ('everybody I am sayhi')
def info(self):
print ('everybody I am info')
def other(self):
print ('everybody I am other')
def run(): #注意这个run是和Myclass类处于同一级别
print "running outside the class"
m = Myclass() #实例化m这个对象
user_input = 'sayhi' #这个就是用户的输入
if hasattr(m,user_input): #意思是判断user_input是否在m里面,这里是‘sayhi’,在里面,往下走;如果是‘tt’,则会走 #else下面的语句user input not exitsts:
func = getattr(m,user_input) #getattr是获取m这个类里面user_input的内存地址,然后赋值给func,在func()就执行
func()
else:
print "user input not exitsts:",user_input
setattr(m,user_input,run) #既然你输入的内容如‘tt'不存在,我就给它设置一个方法,方法名就叫tt,对应的执行的方法就是run这个函数
f = getattr(m,user_input)
f()
print 'run test,but call run',m.tt()
delattr(m.tt) #删除m.tt的方法,注意不能删除类里面的方法,如sayhi,info,other