파이썬 클래스를 초기화 할 때 이상한 효과가 있습니다. 확실한 것을 간과하고 있는지 확실하지 않습니다.값을 가져야 만하는 인스턴스 변수를 변경하여 파이썬 클래스 변수가 변경됨
0 [1, 1, 1]
: 결과를 항복
class Test:
def __init__(self,x,y):
self.X = x
self.Y = y
self.X += 1
self.Y.append(1)
x = 0
y = []
Test(x,y)
Test(x,y)
Test(x,y)
print x, y
: 첫째
것부터, 나는 정수 값에 의해 전달하는 동안이 예와 같이 분명히 클래스에 전달 목록을 참조에 의해 전달되는 것을 알고 있어요
지금까지 너무 좋아. 이
stuff = {u'Item':['Test']}
ds = {}
DataSheet(stuff,ds)
print ds
DataSheet(stuff,ds)
print ds
DataSheet(stuff,ds)
print ds
수율처럼 호출
class DataSheet:
MISSINGKEYS = {u'Item': ["Missing"]}
def __init__(self,stuff,dataSheet):
self.dataSheet = dataSheet
if self.dataSheet.has_key(u'Item'):
self.dataSheet[u'Item'].append(stuff[u'Item'])
else:
self.dataSheet[u'Item'] = self.MISSINGKEYS[u'Item']
: 지금이 예를 살펴
stuff = {u'Item':['Test']}
ds = {}
DataSheet(stuff,ds)
print DataSheet.MISSINGKEYS
DataSheet(stuff,ds)
print DataSheet.MISSINGKEYS
DataSheet(stuff,ds)
print DataSheet.MISSINGKEYS
이 수율 :
{u'Item': ['Missing']}
{u'Item': ['Missing', ['Test']]}
{u'Item': ['Missing', ['Test'], ['Test']]}
지금 대신 인쇄 MISSINGKEYS
수 있습니다
{u'Item': ['Missing']}
{u'Item': ['Missing', ['Test']]}
{u'Item': ['Missing', ['Test'], ['Test']]}
똑같은 출력. 왜?
MISSINGKEYS
은 클래스 변수이지만 의도적으로 변경되지 않습니다. 클래스가이 라인에 들어가는 첫 번째 통화에서
self.dataSheet[u'Item'] = self.MISSINGKEYS[u'Item']
. 분명히 나는 단지 self.dataSheet[u'Item']
이 self.MISSINGKEYS[u'Item']
의 값을 취하고 그 참조 또는 그와 같은 것이되지 않도록하고 싶다. 다음과 같은 두 가지 통화에서
self.dataSheet[u'Item'].append(stuff[u'Item'])
대신 호출되는 라인과 self.dataSheet[u'Item']
과 self.MISSINGKEYS[u'Item']
되는 말아야에 append
작품.
이렇게하면 첫 번째 호출 후에 두 변수가 모두 동일한 개체를 참조하게됩니다. 여기에 무슨 일이 일어나고 있는지
ds == DataSheet.MISSINGKEYS
Out[170]: True
ds is DataSheet.MISSINGKEYS
Out[171]: False
누군가가 나에게 설명 할 수와 나는 그것을 피할 수있는 방법 :
그러나 동일하고 있지만, 그들은하지 않습니다?
편집
:ds[u'Item'] is DataSheet.MISSINGKEYS[u'Item']
Out[172]: True
그래서 좋아, 모두 사전 참조이 하나 개의 항목이 동일한 개체 : 나는이 시도. 대신 값을 할당 할 수 있습니까?여기
'self.dataSheet [u'Item '] = self.MISSINGKEYS [u'Item']'는 당신이 그것을 바꿀 때 어디에서나 변경할 수 있도록 참조를 만든다. 'self.dataSheet [u'Item '] = list (self.MISSINGKEYS [u'Item']) 복사본을 만들어야합니다. –
예. 이것은 내가 이해하지 못하는 파이썬에 관한 것입니다. 의식적으로 아무것도 복사하지 않아도되는 99.9 %의 모든 시간을 당신이 call-by-value를 수행하는 것처럼 작동시키고, 갑자기 이와 같은 것을 우연히 발견하게됩니다. . – Khris
변경 가능한 객체를 사용하면 변경할 수있는 객체에 대한 참조를 만들고, 객체가 불변 인 경우에만 'i = 12; b = i; i + = 12'int는 불변이므로 여전히 12가된다. 그러나 변경 가능한 구조로 변경이 이루어 지므로 새로운 객체가 생성되지 않는다. 기본적으로 변경 가능한 값/obect를 사용하고 참조를 원할 필요가없는 경우 객체에 따라 복사하거나 deepcopy해야합니다. –