就地覆盖整个对象
x = something_mutable
y = x
z = x
# sometime later make z reference something else, e.g. a list
my_list = [1, 2, 3]
# how to make x, y, z to reference my_list without using x and y explicitly
???
这可能吗?其实我不打算用它,只是好奇。
相关问题。怎么把整个列表或字典的内容清空,然后把另一个列表或字典的所有内容复制过来。我知道怎么做,但就是想看看高手们是怎么做的。我刚开始学Python(努力不把Python当成C语言来写 :))。
谢谢。
3 个回答
记住,Python 中有对象,这些对象就是一些存储数据的地方;还有名称,它们用来指代这些对象。并不是所有的对象都有直接的名称指向它们;比如说,如果你有一个里面装满了其他列表、字符串、数字等的列表,通常只有最外层的那个列表会有名称指向它;而里面的对象则是通过对这个列表进行操作来访问的。
理解这一点很重要,因为它能让你明白在你执行操作时,背后发生了什么。如果你执行 del x
,这并不会删除 x
指向的对象;它只是删除了名称 x
。如果 y
仍然指向那个对象,那么它不会受到影响。我认为没有办法直接删除一个对象;你能做的就是移除所有指向它的引用,然后让垃圾回收器来处理它。
同样的,如果 x
指向某个东西,然后你重新赋值,你只是告诉解释器:“好吧,现在我想让 x
指向另一个对象。”之前 x
指向的对象不会受到影响(除了可能会被垃圾回收)。
考虑这个例子:
def f(x, foo=[]):
foo.append(x)
return foo
每次你调用 f()
时,这个会返回一个不断增长的列表。另一方面:
def f(x, foo=[]):
foo = foo + [x]
return foo
这个就没有按预期工作。foo
曾经指向一个在 f()
被定义或第一次调用时创建的列表(我记不清了)。然后我们把那个列表拿出来,添加另一个列表,形成一个全新的列表,把这个新列表赋值给名称 foo
,并返回它。下次我们调用 f()
时,foo
会被重新指向那个旧的空列表,而我们上次并没有改变它。
Python的普通进程设计得比较严格,想要实现某些功能就得创建一些特殊的对象。
不过,Python很强大,可以让你创建一些特殊的对象,这些对象是某个特定类的实例,它们的行为正是你想要的。
下面的代码中有一些复杂的地方,但类A的实例之间是以一种特定的方式连接在一起的,这样就能实现你想要的行为。我觉得没有其他更简单的方法来让它们一起工作。
class A(dict):
li = []
def __init__(self,k = None,x = None):
weeth = ' empty'
if (k,x)!=(None,None) and type(x)==type(1):
weeth = ' with value '+repr(x+5)+' for key '+repr(k)
super(A, self).__setitem__(k,x+5)
A.li.append(self)
print '\n Instanciation of '+str(id(self))+weeth
def __setitem__(self,k,val):
if type(val)==type(1):
super(A, self).__setitem__(k,val+2)
print '\n Assignement of '+repr(val+2)+' to '+str(id(self))
also = [id(el) for el in A.li if el!=self]
for el in A.li:
if el!=self:
el.clear()
super(A, el).update(self)
el = self.items()
if also: print ' assignement done also for each of '+repr(also)
else:
print '\n Assignement of a non-integer '+repr(val)+' to '+str(id(self))+' : IMPOSSIBLE'
a = A('bn',12)
print 'A.li==',A.li
print 'a==',a
a[0] = 10
print 'a==',a
b =A()
print 'A.li==',A.li
print 'b==',b
c =A()
print 'A.li==',A.li
print 'c==',c
c['IMP'] = 'Elizabeth Taylor'
print 'c==',c
d =A('ZUI',103)
print 'A.li==',A.li
print 'd==',d
print '\na==',a
print 'b==',b
print 'c==',c
print 'd==',d
c['X45'] = 22
print 'a==',a
print 'b==',b
print 'c==',c
print 'd==',d
print '\n=========================================='
A.li = []
print "\nCreation of {'maize': 3, 'rice': 12, 'wheat': 7} with name 'x'"
x = A()
x['rice'] = 10
x['wheat'] = 5
x['maize'] = 1
print "\nCreation of {'yval':50} with name 'y' and {} with name 'z'"
y = A('yval',45)
z = A()
print '\nx==',x
print 'y==',y
print 'z==',z
print
def assign(d,dic):
d.update(dic)
k = d.iterkeys().next()
d[k] = d[k]
assign(z, {'kilo':123,'jili':14,'somoto':78})
print 'x==',x
print 'y==',y
print 'z==',z
结果
Instanciation of 18527472 with value 17 for key 'bn'
A.li== [{'bn': 17}]
a== {'bn': 17}
Assignement of 12 to 18527472
a== {0: 12, 'bn': 17}
Instanciation of 18528232 empty
A.li== [{0: 12, 'bn': 17}, {}]
b== {}
Instanciation of 18528080 empty
A.li== [{0: 12, 'bn': 17}, {}, {}]
c== {}
Assignement of a non-integer 'Elizabeth Taylor' to 18528080 : IMPOSSIBLE
c== {}
Instanciation of 18528384 with value 108 for key 'ZUI'
A.li== [{0: 12, 'bn': 17}, {}, {}, {'ZUI': 108}]
d== {'ZUI': 108}
a== {0: 12, 'bn': 17}
b== {}
c== {}
d== {'ZUI': 108}
Assignement of 24 to 18528080
assignement done also for each of [18527472, 18528232, 18528384]
a== {'X45': 24}
b== {'X45': 24}
c== {'X45': 24}
d== {'X45': 24}
==========================================
Creation of {'maize': 3, 'rice': 12, 'wheat': 7} with name 'x'
Instanciation of 18528536 empty
Assignement of 12 to 18528536
Assignement of 7 to 18528536
Assignement of 3 to 18528536
Creation of {'yval':50} with name 'y' and {} with name 'z'
Instanciation of 18528688 with value 50 for key 'yval'
Instanciation of 18528840 empty
x== {'maize': 3, 'rice': 12, 'wheat': 7}
y== {'yval': 50}
z== {}
Assignement of 125 to 18528840
assignement done also for each of [18528536, 18528688]
x== {'somoto': 78, 'jili': 14, 'kilo': 125}
y== {'somoto': 78, 'jili': 14, 'kilo': 125}
z== {'kilo': 125, 'jili': 14, 'somoto': 78}
对于第一个问题的回答是:你不能这样做,即使可以的话也不应该这样做。
对于第二个问题的回答是:如果是一个列表,可以用 a[:]=b
来替换。如果是一个字典,可以先用 a.clear(); a.update(b)
来清空再更新。