什么是python等价的c ++ const-reference copy-constructor arguments

时间:2016-09-21 01:53:19

标签: python c++ language-lawyer copy-constructor const-correctness

C ++的一大优点是使用const - 引用参数 - 使用这些类型的参数,你几乎可以保证对象不会被意外修改,并且不会有边的效果。

问题是,Python与这些参数等价的是什么?

例如,假设你有这个C ++方法:

void Foo::setPosition(const QPoint &position) {
    m_position = position;
}

你想把它“翻译”成这样的Python:

def set_position(self, position):
    self.position = position

这样做可能会带来很多麻烦,并且还会出现许多微妙的错误。问题是,使用const引用参数(复制构造函数)的C ++方法的“Python等效”方法是什么?

上次我发现了一个错误,因为我有一个糟糕的“C ++ - > Python翻译“;我用以下内容解决了这个问题:

my_python_instance.set_position(QPoint(pos))

...否则说,我的另一个选择是从调用者那里克隆对象......我非常肯定这不是正确的方法。

4 个答案:

答案 0 :(得分:3)

我希望我理解正确。

很快,没有一个。有两件事你不经常在python中来过。 const和复制构造函数。

这是一个设计决策,python是一种不同的语言。参数总是通过引用传递。

const正确性

用户不要弄乱对象,我认为它不会经常发生。我个人喜欢c ++中的const正确性,但我从来没有发现自己在python中错过了它。它是一种动态的脚本语言,所以在查看可以在参数constness断言下完成的微优化时没有意义。

复制对象

...你不能在python中做太多。在我看来,设计决定将内存管理卸载到用户身上,因为很难以良好的标准方式来实现,例如浅拷贝与深拷贝。我想如果你假设,你不需要它那么多,没有必要为每个对象提供一种方法(比如c ++那样),但仅限于那些需要它的人。

因此,没有统一的pythonic方式。标准中至少有几种方法可以做到:

  1. 列出copied = original[:]
  2. 某些对象提供copy方法,例如dict
  3. 某些对象显式提供构造函数(如c ++),dictlist这样做,因此您可以编写copied = list(original)
  4. 有一个模块copy,您可以为其提供自定义方法__copy____deepcopy__。它还有一个优点,即另一个标准库可以使用它 - pickle进行序列化。
  5. 最类似c ++的方法是选项3. - 实现构造函数,以便它接受调用,该调用返回其参数的副本(当参数类型相同时)。但它可能需要一些狡猾的ctor实现,因为你不能进行类型重载。

    选项2.是相同的,但重构为函数。

    所以可能最好的方法是提供明确的__copy__ / copy方法,如果您支持ctor调用,那将会调用它。

    然后,您作为对象的开发人员可以确保const正确性,并为用户提供一种简单明确的方式来请求副本。

答案 1 :(得分:1)

没有直接的等价物。最接近的是使用copy module并在您的课程中定义__copy__()和/或__deepcopy__()方法。

答案 2 :(得分:0)

在函数上写一个装饰器。让它在进入时序列化数据,在出路时序列化,并确认两者相等。如果不是,则生成错误。

Python类型检查主要是运行时检查,参数满足某些谓词。 C ++中的const是对函数行为的类型检查:因此您必须对函数的行为进行运行时检查以使其等效。

您也可以在进行单元测试或调试构建时进行此类检查,"证明"它是正确的,然后删除检查"发布"模式。

或者,您可以编写一个静态分析器,使用inspect模块检查const违规,并设计您缺少源的参数的不变性,我想。编写支持const的语言变体可能同样容易。几乎不可能。

答案 3 :(得分:0)

position是什么类型的对象?很可能有一种方法可以复制它,以便self拥有该位置的私有副本。例如,如果positionPoint2D,则self.position = Point2D(position)self.position = Point2D( position.x, position.y )可能会有效。

顺便说一下,你的C ++代码可能不如你想象的那么安全。如果m_positionQPoint&,那么在您的函数返回后,您仍然容易受到外部世界某人修改传入的QPoint的影响。 (将参数作为const传递并不能保证从调用者的角度来看引用的对象是const。)