這里的 add 和 mul 定義是無意義的,因為它們依賴于回傳 self ,導致無限回圈。如果他們使用 lambdas 創建一個新的發行版,那么它就可以正常作業,如下面我自己的答案。
我只是在玩類和覆寫嘗試構建一個小型統計工具。但是,當我運行此代碼時,我陷入了__mul__呼叫中正在運行的n1.pdf呼叫中的遞回回圈中,我無法弄清楚原因。我認為這與 Python 懶惰地執行__mul__而不是做我“想要”的事情(讓我們用 CS 語言說)創建一個新的指標,該指標指向 pdf 擁有的舊函式呼叫指向 pdf 的新指標,然后將舊指標(主 .pdf 指標)設定為新函式。
我認為這措辭很糟糕,因此如果您理解我的要求,非常歡迎編輯。
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了,這不是問題。
uj5u.com熱心網友回復:
class Distribution:
...
def pdf(self, x):
return self.pdf(x)
pdf() 呼喚自己,呼喚自己,呼喚自己……無限地。
與cdf().
uj5u.com熱心網友回復:
def pdf(self, x):
return self.pdf(x)
def cdf(self, x):
return self.cdf(x)
我假設您的意圖是委托給屬性。因為它們總是被賦值,所以它們會被找到(假設你在一個實體上查找)而不是類方法(如果沒有這些屬性,這將直接是無限遞回);但這反過來意味著這些類方法毫無用處。x.cdf(y), 哪里cdf是一個可呼叫的實體屬性,只是有效;也不需要提供方法。
newpdf = lambda x : self.pdf(x) * other
self.pdf = newpdf
我假設您的意圖是創建一個依賴于self.pdf. 不幸的是,它不能那樣作業。問題是 lambda 是后期系結。當它執行時,就是它查找self.pdf……并找到自己的時間。
這里有一個單獨的問題,因為您正在撰寫__mul__和__add__實作 - 即*和 運算子,它們應該回傳一個新值,而不是改變任何一個運算元。(如果你寫了a = 3andb = 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)
請注意,實作這些方法還為您提供了增強的賦值運算子*=和 =(盡管通過創建新物件并重新系結名稱)。
讓我們測驗一下:
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
uj5u.com熱心網友回復:
感謝@John 和@Tom 和@bbbbbb 的幫助...問題是試圖回傳 self 而不是創建一個新的發行版。如果我將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
那么這解決了這個問題
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/394348.html
上一篇:資料框特定行值選擇
下一篇:嘗試將多個影像黑白,Python
