[英]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.