在Python中模拟指针

在Python中模拟指针,python,pointers,Python,Pointers,我正在尝试将内部语言(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

我正在尝试将内部语言(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了。

否定,没有指针。语言的设计方式不应该需要它们。然而,我听到一个恶毒的谣言,说您可以使用:模块使用它们。我没有用过,但闻起来很乱。

你可能想读一下。底线:所有变量都是引用


更重要的是,不要考虑变量,而要考虑可以命名的对象。

Python中的所有内容都已经是指针,但在Python中称为“引用”。这是代码到Python的转换:

a = [1,2]  // a has an array 
b = a     // b points to a
a = 2      // store 2 in a.
print(a)   // outputs 2
print(b)  // outputs [1,2]

“去引用”毫无意义,因为它都是引用。没有其他任何东西,所以没有什么可以去引用的。

正如其他人所说,所有Python变量本质上都是指针

从C角度理解这一点的关键是使用unknown by many id()函数,它告诉您变量指向的地址

>>> a = [1,2]
>>> id(a)
28354600

>>> b = a
>>> id(a)
28354600

>>> id(b)
28354600

这可以明确地完成

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

这是愚蠢的,但是一个想法

# Change operations like:
b = &a

# To:
b = "a"

# And change operations like:
*b = 2

# To:
locals()[b] = 2


>>> a = [1,2]
>>> b = "a"
>>> locals()[b] = 2
>>> print(a)
2
>>> print(locals()[b])
2

但是不会有指针算法之类的,也不会告诉您可能会遇到什么其他问题…

如果您正在编译一种类似C的语言,请说:

func()
{
    var a = 1;
    var *b = &a;
    *b = 2;
    assert(a == 2);
}
在Python中,所有“Python中的一切都是引用”的东西都是用词不当的

确实,Python中的所有内容都是引用,但许多核心类型(int、string)都是不可变的,这一事实在许多情况下都有效地消除了这一点

现在,您可以间接地执行此操作:对于任何不可变类型,将其包装为可变类型。Ephemient的解决方案很有效,但我通常只执行以下操作:

a = [1]
b = a
b[0] = 2
assert a[0] == 2
(我这样做是为了解决Python在2.x中缺少“非本地”的问题

这意味着更多的开销:每个不可变类型(或者每个类型,如果你不尝试区分的话)突然创建了一个列表(或者另一个容器对象),因此你显著增加了变量的开销。单独来说,这并不多,但当应用到整个代码库时,它会增加

您可以通过只包装不可变的类型来减少这种情况,但是您需要跟踪输出中哪些变量被包装,哪些没有包装,这样您就可以适当地使用“a”或“a[0]”来访问该值。这可能会有问题

至于这是否是一个好主意——这取决于你为什么这么做。如果你只是想运行一个VM,我倾向于说不。如果你想从Python调用你现有的语言,我建议你使用你现有的VM并为它创建Python绑定,这样你就可以从Python访问和调用它。

正如我投票赞成的那样,您可以使用Python的内置函数。它将执行类似于ephemient答案中的
ref
类的操作,除了现在,您不必被迫使用
get
set
方法来访问
ref
实例,只需调用您要调用的实例的属性即可e在类定义中指定为属性。从Python文档(除了我将C更改为ptr)中:

这两种方法的工作方式都类似于C指针,无需求助于
global

def do_stuff_with_pointer(pointer, property, value):
    setattr(pointer, property, value)
比如说

a_ref = ptr()      # make pointer
a_ref.x = [1, 2]   # a_ref pointer has an array [1, 2]
b_ref = a_ref      # b_ref points to a_ref
# pass ``ptr`` instance to function that changes its content
do_stuff_with_pointer(b_ref, 'x', 3)
print a_ref.x      # outputs 3
print b_ref.x      # outputs 3
另一个完全疯狂的选择是使用Python。试试这个:

from ctypes import *
a = py_object([1,2]) # a has an array 
b = a                # b points to a
b.value = 2          # derefernce b to store 2 in a
print a.value        # outputs 2
print b.value        # outputs 2
或者,如果你真的想变得漂亮

from ctypes import *
a = py_object([1,2])   # a has an array 
b = pointer(a)         # b points to a
b.contents.value = 2   # derefernce b to store 2 in a
print a.value          # outputs 2
print b.contents.value # outputs 2
这更像是OP最初的要求。疯狂

class Pointer(object):
    def __init__(self, target=None):
        self.target = target

    _noarg = object()

    def __call__(self, target=_noarg):
        if target is not self._noarg:
            self.target = target
        return self.target

我认为这个例子简短明了

这里我们有一个隐式列表类:

class A: 
   foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]
看着这个内存配置文件(使用:
from memory\u profiler import profile
),我的直觉告诉我,这可能会以某种方式模拟C中的指针:

Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
     7     31.2 MiB      0.0 MiB   @profile
     8                             def f():
     9     31.2 MiB      0.0 MiB       a, b = A(), A()
    10                                 #here memoery increase and is coupled
    11     50.3 MiB     19.1 MiB       a.foo.append(np.arange(5000000))
    12     73.2 MiB     22.9 MiB       b.foo.append(np.arange(6000000))
    13     73.2 MiB      0.0 MiB       return a,b


[array([      0,       1,       2, ..., 4999997, 4999998, 4999999]), array([      0,       1,       2, ..., 5999997, 5999998, 5999999])] [array([      0,       1,       2, ..., 4999997, 4999998, 4999999]), array([      0,       1,       2, ..., 5999997, 5999998, 5999999])]
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    14     73.4 MiB      0.0 MiB   @profile
    15                             def g():
    16                                 #clearing b.foo list clears a.foo
    17     31.5 MiB    -42.0 MiB       b.foo.clear()
    18     31.5 MiB      0.0 MiB       return a,b


[] []
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    19     31.5 MiB      0.0 MiB   @profile
    20                             def h():
    21                                 #and here mem. coupling is lost ;/
    22     69.6 MiB     38.1 MiB       b.foo=np.arange(10000000)
    23                                 #memory inc. when b.foo is replaced
    24    107.8 MiB     38.1 MiB       a.foo.append(np.arange(10000000))
    25                                 #so its seams that modyfing items of
    26                                 #existing object of variable a.foo,
    27                                 #changes automaticcly items of b.foo
    28                                 #and vice versa,but changing object
    29                                 #a.foo itself splits with b.foo
    30    107.8 MiB      0.0 MiB       return b,a


[array([      0,       1,       2, ..., 9999997, 9999998, 9999999])] [      0       1       2 ..., 9999997 9999998 9999999]
在这里,我们在课堂上有明确的自我:

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []

Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    44    107.8 MiB      0.0 MiB   @profile
    45                             def f():
    46    107.8 MiB      0.0 MiB       a, b = B(), B()
    47                                 #here some memory increase
    48                                 #and this mem. is not coupled
    49    126.8 MiB     19.1 MiB       a.foo.append(np.arange(5000000))
    50    149.7 MiB     22.9 MiB       b.foo.append(np.arange(6000000))
    51    149.7 MiB      0.0 MiB       return a,b


[array([      0,       1,       2, ..., 5999997, 5999998, 5999999])] [array([      0,       1,       2, ..., 4999997, 4999998, 4999999])]
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    52    111.6 MiB      0.0 MiB   @profile
    53                             def g():
    54                                 #clearing b.foo list
    55                                 #do not clear a.foo
    56     92.5 MiB    -19.1 MiB       b.foo.clear()
    57     92.5 MiB      0.0 MiB       return a,b


[] [array([      0,       1,       2, ..., 5999997, 5999998, 5999999])]
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    58     92.5 MiB      0.0 MiB   @profile
    59                             def h():
    60                                 #and here memory increse again ;/
    61    107.8 MiB     15.3 MiB       b.foo=np.arange(10000000)
    62                                 #memory inc. when b.foo is replaced
    63    145.9 MiB     38.1 MiB       a.foo.append(np.arange(10000000))
    64    145.9 MiB      0.0 MiB       return b,a


[array([      0,       1,       2, ..., 9999997, 9999998, 9999999])] [      0       1       2 ..., 9999997 9999998 9999999]

ps:我是自学编程(从Python开始),所以如果我错了,请不要恨我。这只是我的直觉,让我这么想,所以不要恨我!

我知道Python中没有指针:)我的目标是将我现有的语言交叉编译成Python,这样我就不必再支持运行时了。我将生成什么Python来模拟上面的示例?那么您正试图将一种相当低级的语言编译成一种相当高级的语言?您是否考虑过为您的虚拟机提供其他平台?将C编译成各种高级语言,但还没有Python后端。不过,看看它的执行情况会很有趣:)示例中的一个问题是使用整数,而在Python中整数是不可变的。也就是说,你不能改变它们。这再加上你有一个数组变量,你可以在你的C代码中用一个整数覆盖它(从C的角度来看这很可怕),这意味着你正在寻求一种方法来滥用Python,就像你滥用C一样。这根本没有任何意义。@Lennart Regbro。我所使用的语言不是C。我想我现在已经清楚地告诉你了:)使用大小为1的列表作为可变引用和非常量指针:
a=[smth]
b=[a]
b[0][0]=2
打印a[0]打印b[0][0]谢谢你的回答。我担心的是
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
     7     31.2 MiB      0.0 MiB   @profile
     8                             def f():
     9     31.2 MiB      0.0 MiB       a, b = A(), A()
    10                                 #here memoery increase and is coupled
    11     50.3 MiB     19.1 MiB       a.foo.append(np.arange(5000000))
    12     73.2 MiB     22.9 MiB       b.foo.append(np.arange(6000000))
    13     73.2 MiB      0.0 MiB       return a,b


[array([      0,       1,       2, ..., 4999997, 4999998, 4999999]), array([      0,       1,       2, ..., 5999997, 5999998, 5999999])] [array([      0,       1,       2, ..., 4999997, 4999998, 4999999]), array([      0,       1,       2, ..., 5999997, 5999998, 5999999])]
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    14     73.4 MiB      0.0 MiB   @profile
    15                             def g():
    16                                 #clearing b.foo list clears a.foo
    17     31.5 MiB    -42.0 MiB       b.foo.clear()
    18     31.5 MiB      0.0 MiB       return a,b


[] []
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    19     31.5 MiB      0.0 MiB   @profile
    20                             def h():
    21                                 #and here mem. coupling is lost ;/
    22     69.6 MiB     38.1 MiB       b.foo=np.arange(10000000)
    23                                 #memory inc. when b.foo is replaced
    24    107.8 MiB     38.1 MiB       a.foo.append(np.arange(10000000))
    25                                 #so its seams that modyfing items of
    26                                 #existing object of variable a.foo,
    27                                 #changes automaticcly items of b.foo
    28                                 #and vice versa,but changing object
    29                                 #a.foo itself splits with b.foo
    30    107.8 MiB      0.0 MiB       return b,a


[array([      0,       1,       2, ..., 9999997, 9999998, 9999999])] [      0       1       2 ..., 9999997 9999998 9999999]
class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []

Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    44    107.8 MiB      0.0 MiB   @profile
    45                             def f():
    46    107.8 MiB      0.0 MiB       a, b = B(), B()
    47                                 #here some memory increase
    48                                 #and this mem. is not coupled
    49    126.8 MiB     19.1 MiB       a.foo.append(np.arange(5000000))
    50    149.7 MiB     22.9 MiB       b.foo.append(np.arange(6000000))
    51    149.7 MiB      0.0 MiB       return a,b


[array([      0,       1,       2, ..., 5999997, 5999998, 5999999])] [array([      0,       1,       2, ..., 4999997, 4999998, 4999999])]
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    52    111.6 MiB      0.0 MiB   @profile
    53                             def g():
    54                                 #clearing b.foo list
    55                                 #do not clear a.foo
    56     92.5 MiB    -19.1 MiB       b.foo.clear()
    57     92.5 MiB      0.0 MiB       return a,b


[] [array([      0,       1,       2, ..., 5999997, 5999998, 5999999])]
Filename: F:/MegaSync/Desktop/python_simulate_pointer_with_class.py

Line #    Mem usage    Increment   Line Contents
================================================
    58     92.5 MiB      0.0 MiB   @profile
    59                             def h():
    60                                 #and here memory increse again ;/
    61    107.8 MiB     15.3 MiB       b.foo=np.arange(10000000)
    62                                 #memory inc. when b.foo is replaced
    63    145.9 MiB     38.1 MiB       a.foo.append(np.arange(10000000))
    64    145.9 MiB      0.0 MiB       return b,a


[array([      0,       1,       2, ..., 9999997, 9999998, 9999999])] [      0       1       2 ..., 9999997 9999998 9999999]