在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中复制这个function。

我应该指出,我认为我已经混淆了一些人。 我不想在Python中使用指针。 我只是想从那里的Python专家那里得到一个感觉,我应该生成什么样的Python来模拟上面显示的情况

我的Python不是最伟大的,但到目前为止我的探索还没有产生任何有希望的

我应该指出,我们正在寻求从我们的ihl转向更通用的语言,所以如果有人能够推荐另一种更适合的语言,我们并不是真正的与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 

您可能想要从C ++的angular度阅读Pythonvariables名的语义 。 底线: 所有variables都是引用

更重要的是,不要用variables来思考,而要用可以命名的对象。

如果你正在编译一个C语言,请说:

 func() { var a = 1; var *b = &a; *b = 2; assert(a == 2); } 

进入Python,那么所有的“Python中的所有东西都是一个参考”东西是一个用词不当。

确实,Python中的所有东西都是一个引用,但是很多情况下,许多核心types(int,string)都是不可变的。 没有直接的方法来在Python中实现上述。

现在,你可以间接地做:对于任何不可变的types,把它包装成一个可变types。 Ephemient的解决scheme的作品,但我经常这样做:

 a = [1] b = a b[0] = 2 assert a[0] == 2 

(我已经完成了这个工作来解决Python在2.xa中缺less“非本地”的问题。)

这意味着更多的开销:每个不可变的types(或者每个types,如果你不试图区分)突然创build一个列表(或另一个容器对象),所以你显着增加了variables的开销。 单独来说,这不是很多,但应用于整个代码库时会加起来。

你可以通过只包装不可变types来减less这个,但是你需要跟踪输出中的哪些variables被封装,哪些不是,所以你可以用“a”或者“a [0]”来访问这个值适当。 它可能会变得毛茸茸的。

至于这是不是一个好主意 – 这取决于你为什么这样做。 如果你只是想要运行虚拟机,我倾向于拒绝。 如果你想能够从Python调用你现有的语言,我build议你把你现有的虚拟机和创buildPython绑定,所以你可以从Python访问和调用它。

几乎完全像ephemient 答案 ,我投了,你可以使用Python的内置属性函数。 在ephemient的答案中,它会做类似于ref类的东西,现在除了被迫使用getset方法来访问一个ref实例外,你只需要调用你已经在属性中指定的属性类定义。 从Python文档(除了我改变CPTR ):

 class ptr(object): def __init__(self): self._x = None def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "I'm the 'x' property.") 

这两种方法都像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 

另一个完全疯狂的select是使用Python的ctypes 。 尝试这个:

 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的原始要求。 疯!

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] 

“解引用”是没有意义的,因为它全是引用。 没有其他的东西了,所以没有什么可以提及的。

正如其他人所说,所有的Pythonvariables实质上是指针。

从C的angular度理解这个关键是使用许多id()函数的未知。 它告诉你variables指向的地址。

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

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

 # 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 

但是没有指针算术等等,也不知道你会碰到什么其他的问题。

消极,没有指针。 你不应该用语言devise的方式来需要它们。 但是,我听到一个令人讨厌的传闻,你可以使用: ctypes模块来使用它们。 我没有用过它,但是它闻起来很乱。

 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 
 a = Pointer([1, 2]) b = a print a() # => [1, 2] print b() # => [1, 2] b(2) print a() # => 2 print b() # => 2 

我认为这个例子简短明了。

在这里,我们有隐式列表的类:

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

看着这个内存configuration文件(使用: from memory_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开始),所以如果我错了,请不要恨我。 它只是我的直觉,让我这样想,所以不要恨我!