[英]How to create a generator with recursion?
一個簡單的希爾伯特曲線類。
class Hilbert():
def __init__(self,order=1):
self.x = -1
self.y = 0
self._step(0)
self._hil(0, 1, order)
def _hil(self, dirs, rot, order):
if (order == 0):
return
dirs += rot
self._hil(dirs, -rot, (order-1))
self._step(dirs)
dirs -= rot
self._hil(dirs, rot, (order-1))
self._step(dirs)
self._hil(dirs, rot, (order-1))
dirs -= rot
self._step(dirs)
self._hil(dirs, -rot, (order-1))
def _step(self, dirs):
dirs %= 4
if dirs == 0:
self.x += 1
elif dirs == 1:
self.y += 1
elif dirs == 2:
self.x -= 1
else:
self.y -= 1
#prints all points
#print(self.x,self.y)
#Could I "iterate" from here.
所以我想要的是每次調用next()都給出(x,y)的東西。 我自己嘗試過執行此操作,但無法使其正常工作,因此將不勝感激。 我必須重寫此代碼才能使用生成器嗎? 資源
我想你想做些什么,至少部分是把_hil
變成發電機的功能,其產生x, y
對每次通話后_step
? 如果是這樣,那很容易。
困難的部分是那些遞歸調用。 但這一點都不難。 這正是yield from
目的:*進行一些迭代器(例如對生成器函數的遞歸調用)並產生其每個值。**
然后是簡單的部分,每次調用_step
之后, x, y
對的非遞歸產生。 您可以在每次調用后使用明確的yield self.x, self.y
來實現。 或者,您可以更改_step
來添加return self.x, self.y
,因此只需yield self._step(dirs)
。 但是,您也可以將_step
更改為僅迭代一個值的迭代器,然后也可以從中進行yield from
。 (這里並沒有真正的優勢,但是我認為值得展示,因此您可以仔細考慮它的工作方式-特別是因為您在_step
詢問了“我可以從這里進行迭代嗎?”。)
def _hil(self, dirs, rot, order):
if (order == 0):
return
dirs += rot
yield from self._hil(dirs, -rot, (order-1))
yield from self._step(dirs)
dirs -= rot
yield from self._hil(dirs, rot, (order-1))
yield from self._step(dirs)
yield from self._hil(dirs, rot, (order-1))
dirs -= rot
yield from self._step(dirs)
yield from self._hil(dirs, -rot, (order-1))
def _step(self, dirs):
# existing code
yield self.x, self.y
但是現在您有了__init__
, _hil
調用_hil
而對結果不執行任何操作。 那不是很有用。 也許您正在嘗試將Hilbert
類本身變成迭代器類?
在這種情況下,最簡單的方法是存儲生成器迭代器並將其委托給它:
def __init__(self, order=1):
self.x = -1
self.y = 0
self._step(0)
self.iter = self._hil(0, 1, order)
def __iter__(self):
return self
def __next__(self):
return next(self.iter)
但是,在這一點上,我不確定為什么您需要將它作為一堂課。 在x
和y
是不是真的對象的狀態的一部分,他們是發電機狀態,它是由Python將采取的神奇護理的一部分,如果你只是用在局部變量_hil
(和正常的參數和返回傳遞_step
) 。 而唯一的其他狀態是self.iter
,這僅是必需的,因為您是在編寫類而不是函數。
*實際上,正如格雷格·尤因 ( Greg Ewing)驚人地描述的那樣,事實證明,它所帶來的好處遠不止這些; 沒有它,我們將不會有asyncio
。 但是將其添加到語言的最初原因是“委派給子生成器的語法”。
**請注意,這僅在您yield from
– 3.3或更高版本的Python中獲得 yield from
時才有效。 如果您仍在使用Python 2.x,並且yield from
不足以使您升級,則可以通過將每種yield from eggs
轉換for egg in eggs: yield egg
來模擬它的某些用途(包括此用途) for egg in eggs: yield egg
。 它不會像以前那樣可讀,而且速度會慢得多,但是會起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.