在Python中模拟指针

58 投票
11 回答
97549 浏览
提问于 2025-04-15 12:59

我正在尝试把我们内部使用的语言(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 个回答

14

如果你在编译一种类似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中访问和调用它。

24

你可能想看看这篇文章:从C++的角度看Python变量名的语义。简单来说,所有变量都是引用

更重要的是,不要把注意力放在变量上,而是要关注那些可以被命名的对象。

86

这可以明确地做到。

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

撰写回答