一、代码出错了,错在self
在做LeetCode中的爬楼梯问题时,使用递归试了一下,发现总是报错,代码如下
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n == 1:
return 1
elif n == 2:
return 2
else:
return climbStairs(n-1) + climbStairs(n-2)
错误原因:NameError: name 'climbStairs' is not defined.
查了资料以后,说是在前面加上self,修改一下就好了,只改变最后一行
return self.climbStairs(n-1) + self.climbStairs(n-2)
二、self的作用
为了理解为什么这样修改是有效的,于是查了Python的类中self参数是什么意思。
文章中比较重要的一句话:
在Python的解释器内部,当我们调用t.prt()时,实际上Python解释Test.prt(t),也就是说把self替换成类的实例。
也就是说,在我们调用类方法时,类中的self会替换成类的实例。
在参考的文章中,Test类 的 prt方法 的作用就是输出self。而在产生实例 t 以后,t.prt()的效果就是先把self替换成 t,然后按照方法的功能输出 t 。
三、出错代码加了self以后的效果
首先我们产生一个实例,然后调用实例方法。
Fn = Solution()
Fn.climbStairss(n)
然后根据上述所说,在调用方法Fn.climbStairss(n)时,Python会把类中的self替换成实例 Fn。于是在下面这行修改后的代码我们可以看到效果
return self.climbStairs(n-1) + self.climbStairs(n-2)
这行代码其实就是返回 Fn.climbStairs(n-1) + Fn.climbStairs(n-2)
调用实例Fn中的方法climbStairs。
这才是比较正确的类实例的方法调用。
如果前面没有self,也就是修改前的代码:
return climbStairs(n-1) + climbStairs(n-2)
那么代码返回的是 climbStairs(n-1) + climbStairs(n-2)。类方法总是要在一个实例进行调用,(当然可以直接用类传入实例调用,但不用在意这个),这里直接调用一个方法,单单只是调用一个方法,显然是不合理的,因为在当前域中,是只有Fn跟Solution的name的,没有别的name。所以会显示错误:NameError: name 'climbStairs' is not defined.
综上所述,在调用类方法中,要注意self的运用。不只是递归,在应用到类时,都需要考虑在方法前面加上self。
另外根据参考的文章,可以知道,一旦产生了一个实例,那么self就会一直是传入的那个实例。这样也保证了即使生成多个新的实例,也不会把原来的实例和新的实例弄乱了。这也是 self 的一个好处吧。
另外,LeetCode这道题用应该用动态规划求解,递归会超时。