class test:
def __init__(self):
self.see=0
self.dic={"1":self.see}
examine=test()
examine.see+=1
print examine.dic["1"]
print examine.see
结果为0和1,这没有任何意义。
print id(examine.dic["1"])
print id(examine.see)
他们也有不同的内存地址
但是,如果你使用相同的例子但是你有一个数组而不是变量。你得到了预期的输出。
有任何解释吗?
这给出了预期的输出:
class test:
def __init__(self):
self.see=[0]
self.dic={"1":self.see}
examine=test()
examine.see[0]+=1
print examine.dic["1"][0]
print examine.see[0]
答案 0 :(得分:4)
简短回答:
数组/ list
是可变的,而整数/ int
则不是。
答案 1 :(得分:3)
列表是可变的(它们可以就地更改),当您更改列表时,相同的对象会更新(ID不会更改,因为不需要新对象)。
整数是不可变的 - 这意味着要改变某些东西的价值,你必须创建一个新的对象,它将具有不同的id。字符串以相同的方式工作,你会遇到同样的问题"如果您设置self.see = 'a'
,然后执行examine.see += ' b'
>>> a = 'a'
>>> id(a)
3075861968L
>>> z = a
>>> id(z)
3075861968L
>>> a += ' b'
>>> id(a)
3075385776L
>>> id(z)
3075861968L
>>> z
'a'
>>> a
'a b'
在Python中,名称指向值;和值由Python管理。 id()
方法返回值的唯一标识符,而不是名称。
任意数量的名称都可以指向相同的值。这意味着,您可以拥有多个名称,这些名称都链接到相同的ID。
首次创建类对象时,名称see
指向整数对象的值,该对象的值为1
。然后,当您创建类dic
时,"1"
键现在指向see
指向的同一对象;这是1
。
由于1
(整数类型的对象)是不可变的 - 每当您更新它时,原始对象都会被替换并创建一个新对象 - 这就是id()
的返回值发生变化的原因。
Python足够聪明,知道还有一些其他名称指向" old"价值,所以它将它保存在内存中。
但是,现在你有两个对象;字典仍然指向" old"一,see
现在指向新的。
当您使用列表时,Python不需要创建新对象,因为它可以修改列表而不会破坏它;因为列表是可变的。现在,当您创建一个列表并为其指向两个名称时,两个名称都指向同一个对象。当您更新此对象(通过添加值,或删除值或更改其值)时,相同的对象会更新 - 因此指向它的所有内容都将更新"更新"值。
答案 2 :(得分:2)
examine.dic["1"]
和examine.see
确实有不同的位置,即使前者的初始值是从后者复制的。
根据您使用数组的情况,您不会更改examine.see
的值:而是更改examine.see[0]
,这会更改它指向的数组的内容(这是别名到examine.dic["1"]
)。
答案 3 :(得分:1)
当您执行self.dic={"1":self.see}
时,此时dict值将设置为self.see
的值。如果您稍后执行examine.see += 1
,则会将examine.see
设置为新值。这对dict没有影响,因为dict被设置为self.see
的值;它不知道“继续观察”名称self.see
以查看是否指向不同的值。
如果您将self.see
设置为列表,然后执行examine.see += [1]
,则不会将examine.see
设置为新值,而是更改现有值。这将在dict中可见,因为再次将dict设置为值,并且该值可以更改。
有时a += b
将a
设置为新值,有时会更改现有值。发生哪一个取决于a
的类型;您需要知道examine.see
知道examine.see += something
的作用。
答案 4 :(得分:1)
其他人已经解决了可变性/拳击问题。你似乎要求的是后期绑定。这是可能的,但有点违反直觉,并且可能有更好的解决方案来解决您的根本问题...如果我们知道它是什么。
class test:
@property
def dic(self):
self._dic.update({'1': self.see})
return self._dic
def __init__(self):
self.see = 0
self._dic = {}
>>> ex=test()
>>> ex.see
0
>>> ex.see+=1
>>> ex.see
1
>>> ex.dic
{'1': 1}
>>> ex.see+=1
>>> ex.dic
{'1': 2}
事实上,在这个人为的例子中,它甚至有点危险,因为返回self._dic
消费者可以直接修改字典。但那没关系,因为你不需要在现实生活中这样做。如果您想要self.see
的值,只需获取self.see
的值。
事实上,看起来这就是你想要的:
class test:
_see = 0
@property
def see(self):
self._see+=1
return self._see
或者,你知道,只是itertools.count()
:P
答案 5 :(得分:0)
这个解决方案对我有用。随意使用它。
class integer:
def __init__(self, integer):
self.value=integer
def plus(self):
self.value=self.value+1
def output(self):
return self.value
该解决方案将可变类型int替换为其地址用作引用的类。 此外,您可以更改类对象,并且更改适用于字典指向的内容。它有点像指针/数据结构。