【问题标题】:What is the python equivalent of c++ const-reference copy-constructor arguments什么是 c++ const-reference copy-constructor arguments 的 python 等价物
【发布时间】:2023-03-18 00:56:01
【问题描述】:

C++ 的一大优点是使用const-reference 参数——使用这些类型的参数,您几乎可以保证对象不会被意外修改,也不会产生副作用。

问题是,与这些参数等效的 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))

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

【问题讨论】:

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


    【解决方案1】:

    希望我理解正确。

    简而言之,没有一个。有两件事是你在 python 中不经常遇到的。 consts 和复制构造函数。

    这是一个设计决定,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 用于序列化。

    最类似于 c++ 的方式是选项 3。 - 实现构造函数,以便它接受返回其参数副本的调用(当参数属于相同类型时)。但它可能需要稍微巧妙地实现 ctor,因为你不能进行类型重载。

    选项 2. 相同,但重构为一个函数。

    所以最好的方法可能是提供显式的__copy__/copy 方法,如果你很好支持ctor调用,它将调用它。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-04-02
            • 2014-05-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多