在适当的位置修改int

时间:2018-03-20 21:59:46

标签: python

这更像是一种好奇心

说我有以下代码

>>> my_immutable = (1, 2)
>>> my_immutable[0] += 1

TypeError: 'tuple' object does not support item assignment

这是预期的,因为与C不同,Python不会修改底层的int,而是创建一个新的(在下面的代码中观察到)

>>> x = 1
>>> id(x)
33156200
>>> x += 1
>>> id(x)
33156176

如果我想修改元组中的基础整数,我可以骇客做一些像

这样的事情
>>> hacked_immutable = ([1], [2])
>>> hacked_immutable[0][0] += 1
>>> hacked_immutable
([2], [2])

我的问题是:有没有更好的方法(理想情况下,性能已经在标准库中)?可能在int周围有一些包装类吗?

编辑: 我没有必须坚持这个的特定软件。这更像是为什么这样的事情的思考练习。我认为我遇到的三个问题是:

  • 为什么int是不可变的? (仍然不确定)

  • 有没有办法强制它们变得可变? (wim的回答)

  • 有没有一种很好的方法可以强制它们变得可变(比如Java中的Integer vs int) - 我认为答案是否定的?

非常感谢您的讨论!

2 个答案:

答案 0 :(得分:2)

使用列表而不是元组:

my_container = [1, 2]

tuple是不可变的 - 您无法修改它们。

int是不可变的 - 您无法修改它们。

您最接近的是使用ctypes对该值进行monkeypatch。但这不是很好的"无论想象力如何,如果其他任何事情恰好使用该整数,您可能会对Python运行时进行分段。

>>> t = (42, 43)
>>> import ctypes
>>> ctypes.cast(id(42), ctypes.POINTER(ctypes.c_int))[6] = 666
>>> t
(666, 43)

答案 1 :(得分:2)

以下是小整数的样子:

>>> hacked_immutable = ([1], [2])
>>> hacked_immutable
([1], [2])
>>> id(hacked_immutable)
139813228968072
>>> id(hacked_immutable[0])
139813228055688
>>> id(hacked_immutable[0][0])
139813227530592
>>> id(hacked_immutable[1])
139813228056008
>>> id(hacked_immutable[1][0])
139813227530624
>>> 
>>> 
>>> hacked_immutable[0][0] += 1
>>> hacked_immutable
([2], [2])
>>> id(hacked_immutable)
139813228968072
>>> id(hacked_immutable[0])
139813228055688
>>> id(hacked_immutable[0][0])
139813227530624
>>> id(hacked_immutable[1])
139813228056008
>>> id(hacked_immutable[1][0])
139813227530624

请注意,只有一个单2个对象。但是,让我们看看非小整数:

>>> hacked_immutable = ([314159], [314160])
>>> id(hacked_immutable)
139813228056200
>>> id(hacked_immutable[0])
139813228055688
>>> id(hacked_immutable[0][0])
139813228644176
>>> id(hacked_immutable[1])
139813228056008
>>> id(hacked_immutable[1][0])
139813228644528
>>> 
>>> 
>>> hacked_immutable[0][0] += 1
>>> hacked_immutable
([314160], [314160])
>>> id(hacked_immutable[0])
139813228055688
>>> id(hacked_immutable[0][0])
139813229186864
>>> id(hacked_immutable[1])
139813228056008
>>> id(hacked_immutable[1][0])
139813228644528

Python运行时系统仍然为第一个元素创建一个新的整数对象。 314160存在于两个地方。这是来自缓存小整数,而不是来自im / mutable对象实现的任何属性。