betterway12(얇은복사,깊은복사정의)

김승환·2021년 7월 11일

코딩의 기술

목록 보기
3/36

스트라이드와 슬라이스를 한 식에 함께 사용하지 말라
스트라이드 : 리스트[시작 : 끝 : 증가값]으로 일정한 간격을 두고 슬라이싱을 할 수 있는 특별한 구문

x = ['빨강', '주황', '노랑', '녹색', '파랑', '자주']
odds = x[::2] #0부터 시작해서 2씩 증가해서 추출 하면 빨강, 노랑, 파랑
evens = x[1::2] #1부터 시작해서 2씩 증가하여 추출 하면 주황 녹색 자주
print(odds)
print(evens)

['빨강', '노랑', '파랑']['주황', '녹색', '자주']
단점 : 스트라이드를 사용할 때 예기치 못한 동작 발생 가능이 있다.
ex : 기존에 사용하는 방식

#byte나 str은 기존방식처럼 잘 작동한다.
x = b'mongoose'
y = x[::-1]
print(y)

x = '寿司'
y = x[::-1]
print(y)

b'esoognom'
司寿
하지만 유니코드 데이터를 UTF-8로 인코딩한 문자열에서는 작동X

#  utf-8로 인코딩해서 역으로 동작했을땐 되지만 다시 디코딩하면 작동안하는 모습.
w = '寿司'
x = w.encode('utf-8')
y = x[::-1]
print(x)
print(y)
# 오류가 나는 부분. 오류를 보고 싶으면 커멘트를 해제할것
#2바이트 이상 코드를 작동하면 역순으로 했을때 코드가 깨지기 때문에 에러 발생
z = y.decode('utf-8')
print(z)

a=x.decode('utf-8')
print(a)

b'\xe5\xaf\xbf\xe5\x8f\xb8'
b'\xb8\x8f\xe5\xbf\xaf\xe5'

UnicodeDecodeError Traceback (most recent call last)
in
7 # 오류가 나는 부분. 오류를 보고 싶으면 커멘트를 해제할것
8 #2바이트 이상 코드를 작동하면 역순으로 했을때 코드가 깨지기 때문에 에러 발생
----> 9 z = y.decode('utf-8')
10 print(z)
11

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb8 in position 0: invalid start byte

#아스키코드 범위에 들어가면 문제없이 그대로 작동 (1바이트)
w = 'asga12312'
x = w.encode('utf-8')
y = x[::-1]
z = y.decode('utf-8')
print(z)

21321agsa
-1 말고 다른 음수 증가값이 유용할까?

x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

# 처음부터 끝까지 2의 증가값으로 불러온다.
x[::2] # ['a', 'c', 'e', 'g']
print(x[::2])

#맨 뒤부터 처음까지 2의 증가값으로 불러온다.
x[::-2] # ['h', 'f', 'd', 'b']
print(x[::-2])

['a', 'c', 'e', 'g']['h', 'f', 'd', 'b']

아래 예시에 따라

  • 슬라이싱 구문에 스트라이딩까지 사용하면 매우 혼란스럽다.
  • 그렇기 때문에 시작값이나 끝값, 증가값을 함께 사용하지 말 것.
x[2::2]    # ['c', 'e', 'g']
x[-2::-2]  # ['g', 'e', 'c', 'a']
x[-2:2:-2] # ['g', 'e']
x[2:2:-2]  # []

아래 예시처럼 슬라이싱과 스트라이딩을 따로 사용

y = x[::2] # ['a', 'c', 'e', 'g']
z = y[1:-1] # ['c', 'e']
  • 스트라이딩한 다음 슬라이싱을 하면 데이터를 한 번 더 얕게 복사하게 된다.
  • 첫 번째 연산은 결과 슬라이스의 크기를 가능한 줄일 수 있어야 한다.
  • 두 단계의 연산에 필요한 시간과 메모리를 감당할 수 없다면 itertools 내장모듈의
    islice 메서드 고려

####추가 정보

  1. 단순 객체 복제
    변수만 복사를 하여 바라보는 객체는 동일
a = [1,2,3,4]
b = a # a를 b에 할당
print(b)

b[2] = 100
print(b) #b는 a와 같은 객체의 주소를 보고 있음.
print(a)

[1, 2, 3, 4][1, 2, 100, 4]
[1, 2, 100, 4]

b가 변경되면 a가 변경되는 이유는 변경가능(mutable) 객체 이기 때문
변경가능(mutable) : 변경가능한 객체 ex) list, dict
변경불가능(immutable) : 변경 불가능한 객체 ex) int, str, tuple

# immutable 예시
a = 10
b = a
print(b)
b= "abc"
print(b)
print(a)

10
abc
10

#####2. 얇은 복사(shallow copy)
복합객체라는 list를 생성하지만 안에 있는 내용은 단순 객체와 같은 객체

#얇은 복사 예시

import copy

a = [1, [1, 2, 3]]
b = copy.copy(a) #얇은 복사
print(b)

[1, [1, 2, 3]]

# 얇은 복사를 했기 때문에 복사된 리스트는 별도 객체로 복사본인 b만 수정됨.
b[0] = 100
print(b)
print(a)

#쉽게 이해

b = [int, list]로 a로부터 복사 int는 불변, list는 가변

[100, [1, 2, 3]]
[1, [1, 2, 3]]
#내부에 있는 list는 가변이기 때문에 리스트를 수정하면 둘 다 변경됨.
c = copy.copy(a)
c[1].append(4)
print(c)
print(a)

[1, [1, 2, 3, 4]]
[1, [1, 2, 3, 4]]

####3. 깊은 복사(deep copy)
복합객체를 새롭게 생성하고 그 안 내용까지 독립적으로 생성.

a = [1,[1,2,3]]
b = copy.deepcopy(a)
print(b)

b[0] = 100
b[1].append(4)
print(b)
print(a)

[1, [1, 2, 3]]
[100, [1, 2, 3, 4]]
[1, [1, 2, 3]]

#단순복사였다면?
x = ['a', 'b',['c', 'd', 'e'], 'f', 'g', 'h','i','j']
y = x[::2]
z = y[:-1]
print(z)

z[0]='aa'
print(z)
print(y)
print(x)

['a', ['c', 'd', 'e'], 'g']
['aa', ['c', 'd', 'e'], 'g']
['a', ['c', 'd', 'e'], 'g', 'i']
['a', 'b', ['c', 'd', 'e'], 'f', 'g', 'h', 'i', 'j']
#얇은 복사였다면?
x = ['a', 'b',['c', 'd', 'e'], 'f', 'g', 'h','i','j']
y = x[::2]
z = y[:-1]
print(z)

z[1].append('z')
print(z)
print(y)
print(x)

['a', ['c', 'd', 'e'], 'g']
['a', ['c', 'd', 'e', 'z'], 'g']
['a', ['c', 'd', 'e', 'z'], 'g', 'i']
['a', 'b', ['c', 'd', 'e', 'z'], 'f', 'g', 'h', 'i', 'j']

profile
인공지능 파이팅!

0개의 댓글