首页 > 编程知识 正文

python如何打印指针的内容,python如何实现类似指针概念

时间:2023-05-06 13:19:55 阅读:162571 作者:790

最近在学习C,打印问题时遇到了有关引用、指针的问题。 重申相关知识后,发现C中的引用与python中的引用有很大的不同。 我认为这是C比python效率高得多的原因之一。 在两篇文章中,我想整理python和c在引用上的差异,以及c在引用和指针上的差异。

引用Python

python中的引用是引用赋值,与浅副本相同。 举个例子:

In [13]: a=1

In [14]: b=a

in[15]:id(a ) )

Out[15]: 4553065616

in[16]:id(b ) )

Out[16]: 4553065616

In [20]: b is a

out [ 20 ] :真

In [21]: b==a

out [ 21 ] :真

在上面的代码中,不需要声明变量类型,因此首先初始化了值为1且名称为a的变量。 实际上,python没有变量。 正确的是标签。 然后,变量b引用标签a。 此时,标签b的值等于标签a的值,存储器地址也相同。

但是,在python中引用还有另一个特性。 可以更改APP应用程序

In [23]: b=2

in[24]:id(b ) )

Out[24]: 4553065648

In [25]: a

Out[25]: 1

in[26]:id(a ) )

Out[26]: 4553065616

----------------

In [24]: b=b 1

In [25]: b

Out[25]: 2

In [26]: a

Out[26]: 1

in[27]:id(a ) )

Out[27]: 4369581200

in[28]:id(b ) )

Out[28]: 4369581232

此时,变量b不引用变量a,而是引用名为2的int数据,存储器地址也不再与a相同。 回到a一看,发现a没有受到b的影响。 更详细地说,这是因为在python中,int数据类型是不可变的数据类型,因此在变量b被引用后没有更改a的值或内存,也就是说int是线程安全的数据类型。

销售点

python引用与c的最大区别在于,c的引用一经赋值就不能更改引用对象,后续赋值操作只能修改引用对象本身。

另一方面,python不一样。 没有这个概念,代入引用后,会将标签附加到最新的对象上。

可变类型数据

接下来,让我们看一下python中对可变类型数据的引用

in [1] : a=[ 1,2,3 ]

In [2]: b=a

in[4]:b.append(4) )。

In [5]: b

out [5] : [ 1,2,3,4 ]

in[6]:id(b ) )

Out[6]: 4415640192

in[7]:id(a ) )

Out[7]: 4415640192

In [8]: a

out [8] : [ 1,2,3,4 ]

对于可变类型数据,标签b首先参考标签a引用的对象。 此时,如果操作标签b更改数据,则可以看到标签a所参照的对象也发生了更改。

对可变类型的数据执行变更操作时,该操作本身将成为参考对象。 因此,无论a还是b进行更改操作,都会影响该对象的其他引用。

当对可变类型数据进行重新赋值操作时

in [ 12 ] : a=[ 1,2,3 ]

In [13]: b=a

in [ 14 ] : b=[ 2,3,4 ]

In [15]: a

out [ 15 ] : [ 1,2,3 ]

in[16]:id(a ) )

Out[16]: 4406584576

in[17]:id(b ) )

Out[17]: 4406530608

这时又回到了和不变类型一样的情况,标签b去重新引用新的对象,和a说了拜拜。

让我们看看更典型的例子

发生这种情况是因为更改可变数据的操作实际上是更改引用

in [ 37 ] 3360 a=[ 1,2,3 ]

In [38]: a[1]=a

In [39]: a

Out[39]: [1,[.],3]

我进行了变更操作,使a[1]指向标签a所参照的对象。 原以为结果为[1,[1,2,3],3 ],但变更操作只会修改参照对象本身,列表[ 1, 3 )的? A指着自己引起了循环

为了避免这种情况,可以通过复印解决这个问题。

in [ 41 ] : a=[ 1,2,3 ]

In [42]: a[1]=copy.copy(a (

In [43]: a

Out[43]: [1,[ 1,2,3],3 ]

浅拷贝

对于不可变类型,写副本与赋值相同

In [49]: a=1

in[50]:b=copy.copy(a ) )

In [51]: b

Out[51]: 1

in[52]3360id(a ) )

Out[52]: 4369581200

in[53]3360id(b ) )。

Out[53]: 4369581200

标签b和标签a都指的是这个数据。

看看导致上面循环的问题吧。 在这里可以用复印解决。

in [1] : a=[ 1,2,3 ]

In [2]: a[1]=a[:]

In [3]: a

Out[3]: [1,[ 1,2,3],3 ]

在本例中,您将使用切片作为复制操作,并将a引用的对象的第二个元素指向复制的新对象。

浅析复印缺陷

有一天,不小心发现了薄薄的复印的缺点,很有趣。

In [31]: a=[1,[ 2,3 ],4]

In [32]: b=a[:]

in[33]3360id(a[1] )

Out[33]: 4436979376

in[34]:id(b[1] )

Out[34]: 4436979376

In [40]: a[1][1]=2

In [41]: a

Out[41]: [1,[ 2,2 ],4]

In [42]: b

Out[42]: [1,[ 2,2 ],4]

首先,如果浅复制可变数据,编译器将总结为保存新对象而重新打开内存。 也就是说,复制了可变数据的新对象与原始对象不同。 但是,在上述示例中,如果不变数据作为不变数据对象的元素存在,则副本将其作为不变对象处理,因此可以看出上述a[1]和b[1]的存储器地址相同。

解决这个问题必须使用深度拷贝

深度复制

In [43]: a=[1,[ 2,3 ],4]

in[44]:b=copy.deepcopy(a ) )

In [45]: a[1][1]=2

In [46]: a

Out[46]: [1,[ 2,2 ],4]

In [47]: b

Out[47]: [1,[ 2,3 ],4]

为通过深度复制嵌套的元素创建新的内存。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。