这更像是一种好奇心
说我有以下代码
>>> 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
) - 我认为答案是否定的?
非常感谢您的讨论!
答案 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对象实现的任何属性。