是否可以依靠自动传递引用来改变对象?

时间:2011-05-28 06:15:01

标签: 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)

new_dict将是some_dict的修改版本,但some_dict 将被修改。

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

这些函数中的destination(有几个,它不仅仅是我的例子中的实用函数)总是可变的,但我喜欢显式:函数的返回值表示结果对传入的参数进行确定性计算。我不喜欢使用参数,但在将可变结构传递给函数时,Python中并没有真正解决这个问题的方法。我仔细研究了几个选项:

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

      

    我必须在我变异的每个函数中复制参数,这看起来很麻烦,而且我只是复制很多。另外我不认为我实际上需要原始版本,返回对我已经拥有的变异对象的引用似乎很麻烦。

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

    即可
      

    我不喜欢这个,这个功能正在做什么并不是很明显,我认为这很难看。

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

      

    似乎有点矫枉过正

那我正在做什么好吗?我觉得我隐藏了一些东西,未来的程序员可能会认为原始对象是基于我调用函数的方式保留的(抓住它的结果而不是依赖于它改变原始的事实)。但我也觉得任何替代方案都会很混乱。有更优选的方式吗?请注意,由于软件的工作方式,将mutator样式方法添加到表示抽象数据的类中并不是一个真正的选项(我必须添加一个方法将该数据结构转换为的相应SOAP结构每个服务我们也会发送这些数据 - 目前翻译逻辑位于每个服务的单独包中)

1 个答案:

答案 0 :(得分:1)

如果你有很多这样的功能,我认为最好的办法就是写一个包含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

通常需要修改自身的对象并且读取效果很好。