Python:模拟C风格的变量传递

时间:2013-11-17 11:26:55

标签: python c reference

我有一个类似C语言的框架。现在我正在重写该框架,并且该语言正在被Python取代。

我需要为以下代码构造找到合适的Python替代品:

SomeFunction(&arg1)

这样做的是C风格的传递引用,因此可以在函数调用中更改变量。

我的想法:

  1. 只返回v = SomeFunction(arg1)

    之类的值

    不太好,因为我的泛型函数可以包含很多参数,例如SomeFunction(1,2,'qqq','vvv',.... and many more) 我想让用户有能力获得她想要的价值。

  2. 返回所有参数的集合,无论它们是否已更改,例如:resulting_list = SomeFunction(1,2,'qqq','vvv',.... and many more) interesting_value = resulting_list[3]

    这可以通过为值赋予名称并返回字典interesting_value = resulting_list['magic_value1']

    来改进

    这不好,因为我们有像

    这样的结构
    DoALotOfStaff( [SomeFunction1(1,2,3,&arg1,'qq',val2),
                    SomeFunction2(1,&arg2,v1),
                    AnotherFunction(),
                    ...
                   ], flags1, my_var,... )
    

    而且我不想加载用户的变量列表列表,其中包含她(用户)应该知道的名称或索引。这种引用在这里非常有用......

  3. 最终回复

    我用我自己的想法汇编了所有答案,并且能够产生解决方案。它有效。

    1. 用法

      SomeFunction(1,12, get.interesting_value)
      AnotherFunction(1, get.the_val, 'qq')
      
    2. 解释

      get.前面的任何内容都是一种引用,其值将由函数填充。之前定义的值没有必要。

      限制 - 目前我只支持数字和字符串,但这些足以构成我的用例。

    3. 实施

      • 编写了一个Getter类,它覆盖 getattribute 并按需生成任何变量

      • 所有新创建的变量都有指向其容器的指针Getter和支持方法集(self,value)

      • 当调用set()时,它会检查值是int还是string,并创建从int或str继承的对象,但添加了相同的set()方法。使用这个新对象,我们将在Getter容器中替换我们的实例
    4. 谢谢大家。我将标记为“回答”导致我前进的回应,但是你们所有人都以某种方式帮助了我。

4 个答案:

答案 0 :(得分:4)

我想说你最好,最干净的赌注是构建一个包含要传递和/或修改的值的对象 - 这个单个对象可以传递,(并将自动通过引用传递),作为可以修改单个参数和成员以返回新值。

这将极大地简化代码,您可以干净利落地处理可选参数,默认值等。

>>> class C:
...    def __init__(self):
...        self.a = 1
...        self.b = 2
... 
>>> c=C
>>> def f(o):
...    o.a = 23
... 
>>> f(c)
>>> c
<class __main__.C at 0x7f6952c013f8>
>>> c.a
23
>>> 

注意

我确信你可以扩展这个想法,让一个带有固定成员名称的带有不可变和可变数据的参数进入你的函数,并在返回映射中存储实际传递的参数的名称,将可变值返回到调用者参数名称。然后可以将此技术包装到装饰器中。

我不得不说,与将现有代码重新分解为更加面向对象的设计相比,这听起来像是很多工作。

答案 1 :(得分:2)

这就是Python的工作原理:

def func(arg):
  arg += ['bar']

arg = ['foo']
func(arg)
print arg

此处,对arg的更改会自动传播回调用方。

为了使其正常工作,您必须小心修改参数,而不是重新绑定到新对象。请考虑以下事项:

def func(arg):
  arg = arg + ['bar']

arg = ['foo']
func(arg)
print arg

此处,func重新绑定arg以引用全新列表,并且来电者的arg保持不变。

答案 2 :(得分:1)

Python没有内置这种东西。你可以创建自己的类来提供这种行为,但它只支持稍微更笨拙的语法,其中调用者将构造该类的实例(相当于在调用函数之前,C)中的指针。这可能不值得。我会返回一个“named tuple”(相反) - 我不确定其他方法是否真的更好,其中一些方法更复杂。

答案 3 :(得分:1)

这里存在严重的不一致。您针对建议的解决方案描述的缺点与良好设计的细微规则有关,您的问题将变得无效。整个问题在于你的函数违反了Single Responsibility Principle以及与之相关的其他指南(函数不应超过2-3个参数等)。这里真的没有明智的妥协:

  • 要么接受一个建议的解决方案(即Steve Barnes's answer关于你自己的包装器,要么John Zwinck's answer关于命名元组的使用)并且不要关注好的设计细微之处(作为你的整个设计)目前还不好)

  • 或者您修复了设计。那么你当前的问题就会消失,因为你将不再使用God Objects/Functions(你的例子中的函数名称 - DoALotOfStuff真正说明自己)来处理。