Language agnostic 依靠自动按引用传递来变异对象可以吗?

Language agnostic 依靠自动按引用传递来变异对象可以吗?,language-agnostic,pass-by-reference,semantics,pass-by-name,Language Agnostic,Pass By Reference,Semantics,Pass By Name,我在这里使用的是Python(我认为这实际上是按名称传递),但只要方法参数的行为类似,这种想法就与语言无关: 如果我有这样一个函数: def changefoo(source, destination): destination["foo"] = source return destination 这样说吧 some_dict = {"foo": "bar"} some_var = "a" new_dict = changefoo(some_var, some_dict)

我在这里使用的是Python(我认为这实际上是按名称传递),但只要方法参数的行为类似,这种想法就与语言无关:

如果我有这样一个函数:

def changefoo(source, destination):
    destination["foo"] = source
    return destination
这样说吧

some_dict = {"foo": "bar"}
some_var = "a"

new_dict = changefoo(some_var, some_dict)
new_dict
将是
some_dict
的修改版本,但
some_dict
也将被修改

假设像我示例中的dict这样的可变结构几乎总是类似的小,并且性能不是问题(在应用程序中,我使用抽象对象并将其转换为不同服务的SOAP请求,其中SOAP请求将比为每个服务重新格式化数据要长一个数量级),这样行吗

这些函数中的
destination
(有几个函数,它不只是我示例中的实用函数)始终是可变的,但我喜欢明确表示:函数的返回值表示对传入的参数进行确定性计算的结果。我不喜欢使用out参数,但在Python中将可变结构传递给函数时,并没有真正的解决方法。我考虑过的几个选项:

  • 复制将要变异的参数,以保留原始参数

    我必须复制每个函数中的参数,在那里我对它们进行了变异,这看起来很麻烦,好像我只是复制了很多。另外,我不认为我真的需要原始的,只是返回一个对我已经拥有的变异对象的引用看起来很混乱

  • 只需将其用作输入/输出参数

    我不喜欢这个,它不是很明显的函数在做什么,我认为它很难看

  • 创建一个装饰器,它将自动复制参数

    看起来太过分了


那么我现在做的还好吗?我觉得我在隐藏一些东西,未来的程序员可能会认为原始对象是根据我调用函数的方式保留的(获取其结果,而不是依赖于它对原始对象进行变异的事实)。但我也觉得任何一种选择都会很混乱。有没有更可取的方法?请注意,由于软件的工作方式,向表示抽象数据的类添加mutator样式的方法实际上不是一个选项(对于我们发送数据的每个服务,我必须添加一个方法将该数据结构转换为相应的SOAP结构——目前,每个服务的转换逻辑都在一个单独的包中)

如果您有很多这样的函数,我认为最好的办法是编写一个小类来包装dict并在适当的位置对其进行修改:

class DictMunger(object):
    def __init__(self, original_dict):
        self.original_dict = original_dict

    def changefoo(source)
        self.original_dict['foo'] = source

some_dict = {"foo": "bar"}
some_var = "a"

munger = DictMunger(some_dict)
munger.changefoo(some_var)
# ...
new_dict = munger.original_dict

对象自身的修改通常是可以预期的,并且可读性很好。

您可以在函数中就地修改对象,但您在这里所做的只是在函数中重新指定名称
目的地
;它根本不会影响
某些dict
。Python传递对象。它没有相同的按引用传递语义S,比如说,C++,嗯,奇怪的是,如果我把整个DICT传递给函数,它就改变它,但是如果我从它传递一个值,它就不会。LMME改变问题;分配给一个键改变DICT,但是分配给一个名称,而不用触摸原来的值。实际上,它是一个很大的soap对象,里面充满了soap对象,而且它们都是可变的——我将每个soap对象都传递给这些格式化函数,它们确实会结束mutated@Eevee真正地我认为它更多地与你传入的任何东西的易变性有关:如果我将
foo[“bar”]
传递到一个将对其进行变异的函数中,并且
foo[“bar”]
指向一个列表,那么更改后的列表将显示在原始dict中,不是吗?