Python 对不可变对象的引用集合
Python collection of references to immutables
python 中有没有办法获取参考文献列表?意思是,当我改变其中一个内部事物时,一组事物会自动改变,而不需要引用集合本身。
允许我在示例中显示的东西
# What happens
a = 1
b = 2
L = [a, b]
print(L) # [1, 2]
b = 3
print(L) # [1, 2]
# I would like to have something like
a = 1
b = 2
ra = ref(a)
rb = ref(b)
L = [ra, rb]
print(L) # [1, 2]
b = 3
print(L) # [1, 3]
编辑
如果数字在 python 中可变,我的第一个示例 将 起作用。 IE。如果重新分配(例如:b = 3
)将意味着 "mutate the memory of the object which we are referring to via the label 'b'".
我的第一个示例使用列表的可变元素(例如,如果我构建一个列表列表,并改变 - 无需重新分配! - 内部列表)。
因此,更具体地说,我的问题是:当集合包含不可变元素时,我们是否有机会发生这种行为?
(我尤其对可调用列表感兴趣)。
在打印L的新值之前,在L中再次存储值b,请看下面的代码:
a = 1
b = 2
L = [a, b]
print(L) # [1, 2]
b = 3
L=[a, b]
print(L) # [1, 3]
但是这种方法效率不高。更新List item的方式只有index.As如下:
a = 1
b = 2
L = [a, b]
print(L) # [1, 2]
b = 3
L[1]=b
print(L) # [1, 3]
我们无法通过您尝试使用 Python 中的引用的方式来做到这一点。
当您将一个整数放入列表中时,该列表会保存该整数的副本。整数最初是变量、文字值、函数调用的结果还是其他什么都无关紧要;当列表看到它时,它只是一个整数值。
好的,找到方法了。我只是用可变包装器包装不可变对象。
例如,如果我们想要可变整数:
class mut_int:
def __init__(self, data):
self.data = data
def mutate(self, new_data):
self.data = new_data
def __repr__(self):
return repr(self.data)
a = mut_int(1)
L = [a, a]
print(L) # [1, 1]
# from now on, we assume we don't have access to L anymore
a.mutate(2) # simulating the mutable a = 2
print(L) # [2, 2] # we changed L without accessing it directly, nice!
对于可变的可调用对象,类似地:
class mut_callable:
def __init__(self, func):
self.func = func
def mutate(self, new_func):
self.func = new_func
def __repr__(self):
return repr(self.func)
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
f = mut_callable(lambda x: x)
L = [f, lambda x: f(x) + f(x), lambda x: f(f(x))]
print([g(2) for g in L])
# Out: [2, 4, 2]
# i.e. [identity(2), 2+2, identity(identity(2))]
# from now on, we assume we don't have access to L anymore
f.mutate(lambda x: x**2)
print([g(2) for g in L])
# Out: [4, 8, 16]
# i.e. [square(2), 2+2, square(square(2))]
不幸的是,由于 python 的动态特性和不可能重载赋值 (a = 3
) 运算符,这有点脆弱。一旦对可变包装器使用通常的赋值,包装器就会丢失,我们回到原点。
a = mut_int(1)
L = [a, a]
print(L) # [1, 1]
a.mutate(2)
print(L) # [2, 2] good so far
a = 3 # !ACHTUNG! We did not stick to the api, and a is no more a mut_int!
print(L) # still [2, 2] :(
a.mutate(4) # AttributeError
如果有人找到更优雅的and/or符合人体工程学的and/or稳健的解决方案,我仍然很期待!
python 中有没有办法获取参考文献列表?意思是,当我改变其中一个内部事物时,一组事物会自动改变,而不需要引用集合本身。
允许我在示例中显示的东西
# What happens
a = 1
b = 2
L = [a, b]
print(L) # [1, 2]
b = 3
print(L) # [1, 2]
# I would like to have something like
a = 1
b = 2
ra = ref(a)
rb = ref(b)
L = [ra, rb]
print(L) # [1, 2]
b = 3
print(L) # [1, 3]
编辑
如果数字在 python 中可变,我的第一个示例 将 起作用。 IE。如果重新分配(例如:b = 3
)将意味着 "mutate the memory of the object which we are referring to via the label 'b'".
我的第一个示例使用列表的可变元素(例如,如果我构建一个列表列表,并改变 - 无需重新分配! - 内部列表)。
因此,更具体地说,我的问题是:当集合包含不可变元素时,我们是否有机会发生这种行为?
(我尤其对可调用列表感兴趣)。
在打印L的新值之前,在L中再次存储值b,请看下面的代码:
a = 1
b = 2
L = [a, b]
print(L) # [1, 2]
b = 3
L=[a, b]
print(L) # [1, 3]
但是这种方法效率不高。更新List item的方式只有index.As如下:
a = 1
b = 2
L = [a, b]
print(L) # [1, 2]
b = 3
L[1]=b
print(L) # [1, 3]
我们无法通过您尝试使用 Python 中的引用的方式来做到这一点。 当您将一个整数放入列表中时,该列表会保存该整数的副本。整数最初是变量、文字值、函数调用的结果还是其他什么都无关紧要;当列表看到它时,它只是一个整数值。
好的,找到方法了。我只是用可变包装器包装不可变对象。
例如,如果我们想要可变整数:
class mut_int:
def __init__(self, data):
self.data = data
def mutate(self, new_data):
self.data = new_data
def __repr__(self):
return repr(self.data)
a = mut_int(1)
L = [a, a]
print(L) # [1, 1]
# from now on, we assume we don't have access to L anymore
a.mutate(2) # simulating the mutable a = 2
print(L) # [2, 2] # we changed L without accessing it directly, nice!
对于可变的可调用对象,类似地:
class mut_callable:
def __init__(self, func):
self.func = func
def mutate(self, new_func):
self.func = new_func
def __repr__(self):
return repr(self.func)
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
f = mut_callable(lambda x: x)
L = [f, lambda x: f(x) + f(x), lambda x: f(f(x))]
print([g(2) for g in L])
# Out: [2, 4, 2]
# i.e. [identity(2), 2+2, identity(identity(2))]
# from now on, we assume we don't have access to L anymore
f.mutate(lambda x: x**2)
print([g(2) for g in L])
# Out: [4, 8, 16]
# i.e. [square(2), 2+2, square(square(2))]
不幸的是,由于 python 的动态特性和不可能重载赋值 (a = 3
) 运算符,这有点脆弱。一旦对可变包装器使用通常的赋值,包装器就会丢失,我们回到原点。
a = mut_int(1)
L = [a, a]
print(L) # [1, 1]
a.mutate(2)
print(L) # [2, 2] good so far
a = 3 # !ACHTUNG! We did not stick to the api, and a is no more a mut_int!
print(L) # still [2, 2] :(
a.mutate(4) # AttributeError
如果有人找到更优雅的and/or符合人体工程学的and/or稳健的解决方案,我仍然很期待!