我正在尝试在类中编写递归函数,但在使用对象var作为方法参数时遇到一些麻烦:
class nonsense(object):
def __init__(self, val):
self.val = val
def factorial(self, n=self.val):
if n<=1: return 1
return n*self.factorial(n=n-1)
上面的代码会产生以下错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in nonsense
NameError: name 'self' is not defined
但是如果我没有引用self.val,那么错误就会消失,尽管必须指定n是多余的:
class nonsense(object):
def __init__(self, val):
self.val = val
def factorial(self, n):
if n<=1: return 1
return n*self.factorial(n=n-1)
这样做的正确方法是什么?
答案 0 :(得分:6)
定义方法时会评估默认参数。因此,使用__init__
中定义的成员值基本上“为时已晚”。您应该做的是将默认值设置为None
并在函数体中对此进行测试:
class nonsense(object):
def __init__(self, val):
self.val = val
def factorial(self, n=None):
if n is None:
n = self.val
elif n <= 1:
return 1
return n*self.factorial(n-1)
答案 1 :(得分:3)
正如您所发现的那样,标题中不能有self.xxx
- 而是拥有无,然后在正文中更正:
def factorial(self, n=None):
if n is None: n = self.val
if n<=1: return 1
return n*self.factorial(n=n-1)
原因是当创建类对象时没有self
;除了globals()
之外,Python到达factorial
时定义的唯一名称是__module__
和__init__
。
作为向自己证明这一点的实验,试试这个:
class TestClassCreation(object):
print("Started creating class")
print("names so far: %s" % vars())
def __init__(self):
pass
print("now we have %s" % vars())
def noop(self, default=None):
print("this gets run when noop is called")
print("and now have %s" % vars())
print()
print("and now we'll fail...")
def failure(self, some_arg=self.noop):
pass
print("we never get here...")
答案 2 :(得分:1)
奇怪行为的原因是def
语句仅在定义函数时执行一次。因此,只有在没有self
引用时才会创建初始化值一次。
作为替代方案,试试这个:
class nonsense(object):
def __init__(self, val):
self.val = val
def factorial(self, n=None):
return self.factorial_aux(n if n is not None else self.val)
def factorial_aux(self, n):
if n <= 1:
return 1
return n * self.factorial(n-1)
如果n
参数具有默认值(None
),上述解决方案仅测试一次,之后,它返回调用factorial_aux
的结果(执行实际工作)用适当的论点。
答案 3 :(得分:0)
为什么不写这么简单呢?
class fact1():
def fact2(self, num):
if num==1:
return 1
ss=num*self.fact2(num-1)
return ss
exx=fact1()
print exx.fact2(5)
输出120