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))
...否则说,我的另一个选择是从调用者那里克隆对象......我非常肯定这不是正确的方法。
答案 0 :(得分:3)
我希望我理解正确。
很快,没有一个。有两件事你不经常在python中来过。 const
和复制构造函数。
这是一个设计决策,python是一种不同的语言。参数总是通过引用传递。
const
正确性用户不要弄乱对象,我认为它不会经常发生。我个人喜欢c ++中的const正确性,但我从来没有发现自己在python中错过了它。它是一种动态的脚本语言,所以在查看可以在参数constness断言下完成的微优化时没有意义。
...你不能在python中做太多。在我看来,设计决定将内存管理卸载到用户身上,因为很难以良好的标准方式来实现,例如浅拷贝与深拷贝。我想如果你假设,你不需要它那么多,没有必要为每个对象提供一种方法(比如c ++那样),但仅限于那些需要它的人。
因此,没有统一的pythonic方式。标准中至少有几种方法可以做到:
copied = original[:]
。copy
方法,例如dict
。dict
和list
这样做,因此您可以编写copied = list(original)
。copy
,您可以为其提供自定义方法__copy__
和__deepcopy__
。它还有一个优点,即另一个标准库可以使用它 - pickle
进行序列化。最类似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
拥有该位置的私有副本。例如,如果position
是Point2D
,则self.position = Point2D(position)
或self.position = Point2D( position.x, position.y )
可能会有效。
顺便说一下,你的C ++代码可能不如你想象的那么安全。如果m_position
是QPoint&
,那么在您的函数返回后,您仍然容易受到外部世界某人修改传入的QPoint
的影响。 (将参数作为const传递并不能保证从调用者的角度来看引用的对象是const。)