簡體   English   中英

使用包裝程序在Python / Javascript中模仿按引用傳遞-良好做法?

[英]Mimicking Pass-By-Reference in Python/Javascript Using Wrappers - Good Practice?

假設我要在函數內部修改數字或其他原始類型。 例如,如下所示(注意:偽代碼):

// apply fn to every value in a tree, in-order traversal
function treeReduce (tree, fn, result):
    if (tree == undefined) return
    treeReduce(tree.left, fn, result)
    result = fn(result, tree.value)
    treeReduce(tree.right, fn, result)

sum = 0
treeReduce(myTree, +, sum)

顯然,這是行不通的,因為只是重新分配了result ,並且傳入的sum將看不到修改。 因此,我解決此問題的通用方法(在任何傳遞值的語言(如Python或Javascript)中都使用包裝器:

// apply fn to every value in a tree, in-order traversal
function treeReduce (tree, fn, result):
    if (tree == undefined) return
    treeReduce(tree.left, fn, result)
    result[0] = fn(result[0], tree.value)
    treeReduce(tree.right, fn, result)

sumWrapper = [0]
treeReduce(myTree, +, sumWrapper)

但是,我最近在互聯網上搜索了這是否是一種常見模式,並且找不到太多有關此模式的信息。 具體來說,我想知道三件事:

  1. 這是常見的模式嗎?
  2. 這是好習慣嗎?
  3. 如果沒有,還有其他選擇嗎?

可以這樣做,但是會增加函數的“副作用” ,大多數編碼人員建議盡量減少這些副作用 相反,您可以為其使用函數的返回值。 然后,您的代碼仍將傳遞“ previous”(或“ start”)值作為原語,但返回結果。

這是在JS中的外觀(我花了一些不小的瑣碎的fn來演示它執行了有序執行):

 // apply fn to every value in a tree, in-order traversal function treeReduce (tree, fn, start) { if (tree === undefined) return start let result = treeReduce(tree.left, fn, start) result = fn(result, tree.value) result = treeReduce(tree.right, fn, result) return result } let myTree = { value: 1, left: { value: 2 }, right: { value: 3 } } let result = treeReduce(myTree, (a,b) => a*a+b, 0) console.log(result) 

請注意,以上內容現在可以更簡潔地編寫:

 // apply fn to every value in a tree, in-order traversal function treeReduce (tree, fn, start) { return !tree ? start : treeReduce(tree.right, fn, fn(treeReduce(tree.left, fn, start), tree.value)) } let myTree = { value: 1, left: { value: 2 }, right: { value: 3 } } let result = treeReduce(myTree, (a,b) => a*a+b, 0) console.log(result) 

在Python中:

import collections
Tree = collections.namedtuple('Tree', ['value', 'left', 'right'])

# apply fn to every value in a tree, in-order traversal
def treeReduce (tree, fn, start):
    return start if not tree else ( 
        treeReduce(tree.right, fn, fn(treeReduce(tree.left, fn, start), tree.value))
    )

myTree = Tree(1, Tree(2,None,None), Tree(3,None,None))

result = treeReduce(myTree, lambda a,b: a*a+b, 0)

print(result)

JS和Python都允許將其擴展到需要設置多個原始值的情況:函數可以返回數組/列表/元組/對象,然后可以通過將它們解壓縮/分解為單獨的變量來進行賦值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM