[英]Not sure why I'm stuck in a Python stuck recursion loop
这里的 add 和 mul 定义是无意义的,因为它们依赖于返回 self,导致无限循环。 如果他们使用 lambdas 创建一个新的发行版,那么它可以正常工作,如下面我自己的回答所示。
我只是在玩类并试图构建一个小型统计工具。 但是,当我运行此代码时,我陷入了n1.pdf
调用中的递归循环,该调用在__mul__
调用中运行,我无法弄清楚原因。 I think it has something to do with Python lazily executing the __mul__
instead of doing what I kind of 'wanted' (let's say in the language of CS) which was to create a new pointer to the old function call for pdf that is owned by将新指针指向 pdf,然后将旧指针(main.pdf 指针)设置为新的 function。
我认为这措辞很糟糕,因此如果您理解我的要求,则非常欢迎进行编辑。
import math
import random
class Distribution:
def __init__(self, pdf, cdf):
self.pdf = pdf
self.cdf = cdf
def pdf(self, x):
return self.pdf(x)
def cdf(self, x):
return self.cdf(x)
def __mul__(self, other):
if isinstance(other, float) or isinstance(other, int):
newpdf = lambda x : self.pdf(x) * other
self.pdf = newpdf
newcdf = lambda x : self.cdf(x) * other
self.cdf = newcdf
return self
else:
return NotImplemented
def __add__(self, other):
self.pdf = lambda x : self.pdf(x) + other.pdf(x)
self.cdf = lambda x : self.cdf(x) + other.cdf(x)
return Distribution(self.pdf, self.cdf)
class Normal(Distribution):
def __init__(self, mean, stdev):
self.mean = mean
self.stdev = stdev
def pdf(self, x):
return (1.0 / math.sqrt(2 * math.pi * self.stdev ** 2)) * math.exp(-0.5 * (x - self.mean) ** 2 / self.stdev ** 2)
def cdf(self, x):
return (1 + math.erf((x - self.mean) / math.sqrt(2) / self.stdev)) / 2
def sample(self):
return self.mean + self.stdev * math.sqrt(2) * math.cos(2 * math.pi * random.random())
if __name__ == "__main__":
n1 = Normal(1,2)
n1half = n1 * 0.5
x = n1.pdf(1)
print(x)
ps 我知道乘以0.5后不再是pdf,这不是问题。
class Distribution:
...
def pdf(self, x):
return self.pdf(x)
pdf()
调用自己,调用自己,调用自己......无限。
与cdf()
相同。
def pdf(self, x):
return self.pdf(x)
def cdf(self, x):
return self.cdf(x)
我假设您的意图是委托给属性。 由于它们总是被分配,它们将被找到(假设您在实例上进行查找)而不是 class 方法(如果没有这些属性,这将直接是无限递归); 但这反过来又意味着这些 class 方法只是无用的。 x.cdf(y)
,其中cdf
是可调用的实例属性,可以正常工作; 也不需要提供方法。
newpdf = lambda x : self.pdf(x) * other
self.pdf = newpdf
我假设您的意图是创建一个新的 function ,它依赖于self.pdf
的现有值。 不幸的是,它不是那样工作的。 问题是 lambda 是后期绑定。 当它执行时,它会查找self.pdf
... 并找到它自己。
这里有一个单独的问题,因为您正在编写__mul__
和__add__
实现 - 即*
和+
运算符,它们应该返回一个新 value ,而不是改变任何一个操作数。 (如果你写a = 3
和b = 4
然后c = a * b
,如果a
或b
的值发生变化,你会非常惊讶,是吗?)
我们可以一次解决这两个问题,只需使用计算的pdf
和cdf
创建一个新实例(无论如何我们都需要):
def __mul__(self, other):
if isinstance(other, float) or isinstance(other, int):
newpdf = lambda x : self.pdf(x) * other
newcdf = lambda x : self.cdf(x) * other
return Distribution(newpdf, newcdf)
else:
return NotImplemented
同样, __add__
应该使用局部变量,而不是修改self
:
def __add__(self, other):
newpdf = lambda x : self.pdf(x) + other.pdf(x)
newcdf = lambda x : self.cdf(x) + other.cdf(x)
return Distribution(newpdf, newcdf)
请注意,实现这些方法还为您提供了增强的赋值运算符*=
和+=
(尽管通过创建新的 object 并重新绑定名称)。
让我们测试一下:
if __name__ == "__main__":
n1 = Normal(1,2)
n1half = n1 * 0.5
print(n1.pdf(1))
print(n1half.pdf(1))
n1 += n1
print(n1.pdf(1))
我得到:
>py test.py
0.19947114020071635
0.09973557010035818
0.3989422804014327
感谢@John 和@Tom 和@bbbbbb 的帮助......问题是试图返回自我而不是创建一个新的发行版。 如果我将mul的 def'n 更改为
def __mul__(self, other):
if isinstance(other, float) or isinstance(other, int):
def newpdf(x):
return self.pdf(x) * other
def newcdf(x):
return self.cdf(x) * other
return Distribution(newpdf, newcdf)
else:
return NotImplemented
那么这就解决了这个问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.