【问题标题】:Ensure Memory Location of Variable hasn't Changed确保变量的内存位置没有改变
【发布时间】:2012-10-23 07:16:07
【问题描述】:

这是my previous question的跟进

我正在使用PyContract(不是PyContracts)为类方法编写一些约束。作为后置条件,我想确保某个对象的内存地址没有改变,即id(myObj) 在调用函数之前和之后应该是相同的。如何使用 PyContract 做到这一点?

这是我现在正在做的事情:

def foo(param1, param2)
    """
        # some other constraints
        post[param1, param2]:
            __old__.param1 is param1
            __old__.param2 is param2
    """

但是,后置条件失败。我只能想象这是因为__old__.param1 没有存储在与param1 相同的内存位置。这是有道理的,因为 PyContract 需要在执行foo 之前复制param1,以便在执行完foo 之后检查其值与param1 的值。

假设上面的分析是真的,它只是用来解释为什么id(__old__.param1)id(param1)不同。但是,它仍然没有回答我如何确保id(param1) 不会作为foo 的副作用而改变。我怎么能在 PyContract 中检查这个?

【问题讨论】:

  • 这并不能解释 PyContract 的行为,但是您希望通过该后置条件实现什么? Python 通过引用传递函数参数,因此函数将无法更改它们在外部引用的内容。如果函数改变了函数内部的那些名称,它也不会改变外部的绑定。
  • @JamesHenstridge:碰!我根本没有考虑过python的行为。我更专注于实际的合同。如果您将评论作为答案发表,我会接受 - 它完美地回答了我的问题

标签: python variables design-by-contract memory-address


【解决方案1】:

我不熟悉您正在使用的 PyContract 库,但您正在测试的实际合约在 Python 中没有多大意义,因为函数参数是通过引用传递的。如果你有如下代码:

x = a
y = b
foo(x, y)

然后该函数将在调用范围内接收对xy 命名的对象的引用。在函数调用中,您有两个单独的变量,它们使用对这些参数的引用进行了初始化。

所以函数内部对这些变量的更改不会影响xy在调用范围内的绑定。

【讨论】:

  • 您正确描述了 Python 的参数传递语义,但这不称为按引用传递。通过引用传递并不意味着传递了称为引用的东西,它意味着一个特定的东西(它和其他一些东西一样,被称为引用),它允许改变传入的变量等。所以f(x) 可以更改 x 所指的内容,如果您使用按引用传递。另见:effbot.org/zone/call-by-object.htm
  • @delnan:你的论点成立,但前提是x 是可变类型f(x)x 执行一些就地操作。如果f(x) 只是简单地将x 重新分配给其他东西(在执行其他任何操作之前,就地或其他方式),那么x 在函数调用之前和之后保持不变,当从外部观察时f(x)
  • @inspectorG4dget (1) 你误会了,我认为 Python 使用通过引用传递,f 因此 不能更改 x 所指的内容。
  • @inspectorG4dget (2) 可变性对以任何方式传递的参数绝对没有影响。规则完全相同: (a) 任何函数 f 都不能改变 x 引用的原因,无论引用的对象是否可变。 (b) 所有函数都会收到对x 所指对象的引用(并因此共享对象),无论它是否可变。只是像这样共享的不可变对象不能改变它们的值——根据定义,它们永远不能。但是人们仍然可以通过其他方式观察共享,例如id.
  • 我发现this post 很有趣。
猜你喜欢
  • 2015-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多