在Python中模拟指针
我正在尝试把我们内部使用的语言(ihl)转换成Python。
这个ihl语言有一个特性,就是指针和引用的行为和C或C++中的一样。
比如你可以这样做:
a = [1,2]; // a has an array
b = &a; // b points to a
*b = 2; // derefernce b to store 2 in a
print(a); // outputs 2
print(*b); // outputs 2
有没有办法在Python中复制这种功能呢?
我得说明一下,我觉得我让一些人困惑了。我并不想在Python中使用指针。我只是想了解一下,Python专家们认为我应该生成什么样的Python代码来模拟我上面展示的情况。
我的Python水平不是很好,但到目前为止我的探索没有什么好结果:(
我还想说,我们希望从ihl转向一种更常见的语言,所以如果有人能推荐其他更合适的语言,我们并不一定非要用Python。
11 个回答
如果你在编译一种类似C语言的语言,比如:
func()
{
var a = 1;
var *b = &a;
*b = 2;
assert(a == 2);
}
转成Python,那么“Python中的一切都是引用”这个说法其实不太准确。
确实,Python中的一切都是引用,但很多核心类型(比如整数和字符串)是不可变的,这就让这个说法在很多情况下不成立。实际上,没有什么直接的方法可以在Python中实现上面的内容。
不过,你可以间接实现:对于任何不可变类型,把它包裹在一个可变类型中。Ephemient的解决方案是可行的,但我通常会这样做:
a = [1]
b = a
b[0] = 2
assert a[0] == 2
(我曾经为了绕过Python 2.x中缺少“nonlocal”这个功能,做过几次这样的处理。)
这样做会增加很多额外的开销:每个不可变类型(或者说每个类型,如果你不想区分的话)都会突然创建一个列表(或者其他容器对象),这就大大增加了变量的开销。单独来看,这并不算多,但如果应用到整个代码库上,就会累积成一笔不小的开销。
你可以通过只包裹不可变类型来减少这个开销,但这样你就需要记住输出中哪些变量是被包裹的,哪些不是,这样才能正确地用“a”或“a[0]”来访问值。这可能会变得很复杂。
至于这样做是否是个好主意——这要看你为什么要这么做。如果你只是想让某个东西能运行虚拟机,我会倾向于说不。如果你想从Python中调用你现有的语言,我建议你拿现有的虚拟机,给它创建Python的绑定,这样你就可以从Python中访问和调用它。
你可能想看看这篇文章:从C++的角度看Python变量名的语义。简单来说,所有变量都是引用。
更重要的是,不要把注意力放在变量上,而是要关注那些可以被命名的对象。
这可以明确地做到。
class ref:
def __init__(self, obj): self.obj = obj
def get(self): return self.obj
def set(self, obj): self.obj = obj
a = ref([1, 2])
b = a
print(a.get()) # => [1, 2]
print(b.get()) # => [1, 2]
b.set(2)
print(a.get()) # => 2
print(b.get()) # => 2