2014-09-04 2 views
0

python에서 itertools groupby 모듈로 작업하면서이 이상한 현상을 보았습니다.이 할당 된 객체가 원래 객체와 동일한 메모리 공간을 공유하는 이유는 무엇입니까?

y = 7 
x = y  
y = 9 

x will still be 7 

을하지만 내가 때 : 파이썬에서

는 변수 할당 (이것은 알려 주시기 바랍니다 잘못된 경우 나의 이해에서) 대신 원래의 메모리에 대한 포인터의 새 변수 자체 메모리를 할당하는 것을 의미 groupby 모듈로 작업하면서이 모듈을 사용하여 같은 키를 가진 항목을 하나의 그룹으로 그룹화했습니다. 기억이 이미 수정되었을 것이므로 원래 그룹을 되풀이하여 반복하는 것은 쓸모가 없었습니다. 예 :

for key, group in groupby(rows, lambda x: x[0]): 

    data = [thing[1] for thing in group] #accesses 1st attribute of element 
    data2 = [thing[2] for thing in group] # would yield [] as group is empty 

그래서 내가 대신이 시도 :

for key, group in groupby(rows, lambda x: x[0]): 
    #create a copy of group to reiterate over 
    toup = group 

    print toup #<itertools._grouper object at 0x1039a8850> 
    print group #<itertools._grouper object at 0x1039a8850> 

    data = [thing[1] for thing in group] #accesses 1st attribute of element 
    data2 = [thing[2] for thing in toup] 

데이터 2는 두번째 항목에 액세스해야하지만 수익률은 [] 그들은 주 모두 있기 때문에 같은 메모리가

내 질문은 왜 이런 일이 않습니다됩니다 ? toup toup에 그룹을 지정하면 다른 16 진수 주소 위치에 그룹 메모리 사본이 생깁니 까?

또한이 문제를 우회하여 두 번의 groupby 반복을 쓸 필요가 없도록하려면 어떻게해야합니까? 파이썬에서

+1

변수의 유형에 따라 다릅니다. 정수 및 문자열과 같은 프리미티브는 다른 변수에 할당하면 인스턴스 객체가 복사되지 않으므로 복사됩니다. 변수는 대신 인스턴스 객체에 대한 참조가됩니다. "a = []; b = a; print (a is b)"를 시도하면 True를 인쇄합니다. –

+2

* "변수 할당은 원래 메모리를 가리키는 포인터 대신에 새로운 변수에 자체 메모리를 할당하는 것을 의미합니다."* - Python 이름이 작동하지 않는 잘못된 방법입니다 (예 : http://nedbatchelder.com/text/names.html 참조) . 복사본을 생성하려면'toup = group [:]'을 사용하십시오. – jonrsharpe

+1

@Rawing은 사실이 아닙니다. (처음에는 파이썬이 실제로는 프리미티브를 가지고 있지 않으며, 예를 들어 정수 *는 * 인스턴스입니다.); 차이점은 정수는 불변이다. 목록은 변경할 수 있습니다. 'a = 1; b = a; a is b'' * 여전히 * True이면,'b + = 1'은'a'에 영향을 미치지 않습니다 (정수는 불변이므로). – jonrsharpe

답변

0

는 변수 할당은 원래 메모리에 대한 포인터 대신에 새로운 변수 자체 메모리를 할당하는 의미

파이썬은 변경 가능 (다만 모든 것에 대해 예를 들어,리스트 반복자)과 불변의 객체를 (이 예 : 정수 및 문자열). 할당은 두 경우 모두 객체를 복사하지 않습니다. 변경 불가능한 객체를 사용하면 그 객체에 대한 모든 연산이 새로운 인스턴스가되므로 변경 가능한 유형과 마찬가지로 정수 또는 문자열을 "수정하는"문제는 발생하지 않습니다.

제 질문은 왜 이런 일입니까? toup toup에 그룹을 지정하면 다른 16 진수 주소 위치에 그룹 메모리 사본이 생깁니 까?

두 변수 모두 동일한 개체를 가리 킵니다. 하나를 반복하고 iterator를 소진하면 두 번째 변수를 반복하면 빈 시퀀스가 ​​생깁니다.

3

당신의 상태 : 파이썬에서

는 변수 할당 (이것은 알려 주시기 바랍니다 잘못된 경우 내 이해에서) 원래 메모리에 대한 포인터 대신에 새로운 변수에게 그것의 자신의 메모리를 할당하는 의미 :

올바르지 않습니다. 파이썬 이름은 (시간에) C 변수와 같은 측면을 가질 수 있으며 (때때로) C 포인터와 같은 측면을 가질 수 있습니다. 그들이 하나 또는 다른 것과 같다고 말하려고 시도하는 것은 혼란스러운 일입니다. 하지마. Python을 독특하고 관용적이라고 생각하십시오.

'변수'는 ​​더 많은 이름으로 생각해야합니다. 둘 이상의 일 수 있습니다. 의도하지 않은 경우에도 동일한 메모리 위치를 나타냅니다.

예 :

>>> y=7 
>>> x=7 
>>> x is y 
True 
>>> id(x) 
140316099265400 
>>> id(y) 
140316099265400 

그리고

가 (.로 인해 interning, 다음 에 해당 할 수 있습니다 구현 세부 사항 짧은 int 치의 인턴에 대한 PEP 237를 참조하십시오, 그러나 이것은이다) :

>>> x=9 
>>> y=5+4 
>>> x is y 
True 

파이썬 is 연산자는 메모리 주소를 비교하여 두 객체가 같은 객체 인 경우 True를 반환합니다. id 함수는 해당 주소를 반환합니다.

최종 예로서 고려 :

>>> li1=[1,2,3] 
>>> li2=[1,2,3] 
>>> li1==li2 
True 
>>> li1 is li2 
False 

비록 LI1 == LI2, 그들은 당신이 예에서와 같이, 하나를 변경하는 경우, 그렇지 않으면 모두 바꿀 것 별도의 목록을해야 :

(classic mistake 다른 파이썬 프로그래머가 조만간 만들게 될 다른 가변 객체에 대한 다중 참조로 인해 하나의 참조가 단일 객체처럼 작동 할 것으로 예상 됨)

jonrsharpe가 의견에서 지적했듯이 Ned Batchelders의 우수 개요 인 Facts and myths about Python Names and Values 또는 How to Think Like a Pythonista을 읽으십시오.

+1

두 번째 예제에서 인턴쉽에 대해 언급해야합니다. 즉, '300 is 60 * 5' (또는 모든 Python 구현에서 CPython 세부 사항)와 함께 발생하지는 않습니다. – jonrsharpe

+0

설명해 주셔서 감사합니다. – user2117728

+0

"파이썬 이름은 (시간에) C 변수와 비슷하며 (때때로) C 포인터와 같은 측면도 가질 수 있습니다."이들은 항상 C 포인터와 같습니다. 변수를 값으로 "복사"하는 일반적인 방법은 없습니다. –