yield大法好

雖然不知道是誰(shuí)最早發(fā)明yield來(lái)表達(dá)協(xié)程的,不過(guò)最近終于解鎖這一技能了,讓我感受到了上帝般的快感。
比方說(shuō)我們要后序遍歷二叉樹(shù),好啦我知道ACMer閉著眼睛都能默寫(xiě)出來(lái)非遞歸版本,讓我們看看遞歸版本先:

class Node(object):
    def __init__(self, val, left, right):
        self.val = val
        self.left = left
        self.right = right

def visit_post(node):
    if node.left:
        yield from visit_post(node.left)
    if node.right:
        yield from visit_post(node.right)
    yield node.val

if __name__ == '__main__':
    node = Node(-1, None, None)
    for val in range(100):
        node = Node(val, None, node)
    print(list(visit_post(node)))

就是這么簡(jiǎn)單,yield from這么棒為什么你還在用Python2.x?
但是我們知道寫(xiě)成遞歸動(dòng)不動(dòng)就爆棧了,非遞歸才是正義。不過(guò)不要怕,理解yield協(xié)程之后我們?cè)僖膊槐厥謩?dòng)維護(hù)什么棧了,裝逼變得異常簡(jiǎn)單。

def visit_post(node):
    if node.left:
        yield node.left
    if node.right:
        yield node.right
    yield node.val

def visit(node, visit_method):
    stack = [visit_method(node)]
    while stack:
        last = stack[-1]
        try:
            yielded = next(last)
        except StopIteration:
            stack.pop()
        else:
            if isinstance(yielded, Node):
                stack.append(visit_method(yielded))
            elif isinstance(yielded, int):
                yield yielded

if __name__ == '__main__':
    node = Node(-1, None, None)
    for val in range(100):
        node = Node(val, None, node)
    visit_generator = visit(node, visit_method=visit_post) 
    print(list(visit_generator))

excellent!關(guān)鍵是很好理解對(duì)不對(duì),我以前一直認(rèn)為我不把LeetCode刷7遍是不可能完成遞歸轉(zhuǎn)非遞歸的白板編程的,現(xiàn)在根本不是問(wèn)題嘛。
話說(shuō)簡(jiǎn)書(shū)的代碼高亮能不能專(zhuān)業(yè)點(diǎn),__builtins__高亮很難?這根本就是態(tài)度問(wèn)題。


或者我們有遞歸搜索二叉樹(shù)最大值什么的:

def visit_maxvalue(node):
    if node.left and node.right:
        return max(node.val, visit_maxvalue(node.left), visit_maxvalue(node.right))
    elif node.left:
        return max(node.val, visit_maxvalue(node.left))
    elif node.right:
        return max(node.val, visit_maxvalue(node.right))
    else:
        return node.val

非遞歸版本也是非常平易近人:

def visit_max_maxvalue(node):
    if node.left and node.right:
        yield max(node.val, (yield node.left), (yield node.right))
    elif node.left:
        yield max(node.val, (yield node.left))
    elif node.right:
        yield max(node.val, (yield node.right))
    else:
        yield node.val

def visit(node, visit_method):
    stack = [visit_method(node)]
    current = None
    while stack:
        last = stack[-1]
        try:
            yielded = last.send(current)
        except StopIteration:
            stack.pop()
        else:
            if isinstance(yielded, Node):
                stack.append(visit_method(yielded))
                current = None
            elif isinstance(yielded, int):
                current = yielded
    return current

逼格飽滿有木有!
BTW,著名的Tornado就是用yield協(xié)程來(lái)實(shí)現(xiàn)異步,大愛(ài)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容