기본 콘텐츠로 건너뛰기

[Linear Algebra] 직교적 투영(Orthogonal Projection)

[python] 시퀀스, 이터러블 & 이터레이터

시퀀스, 이터러블 & 이터레이터

내용

시퀀스(Sequence)와 이터러블(iterable)

인덱스를 가진 요소들로 구성된 객체를 시퀀스(Sequence)라고 하며 파이썬은 리스트, 바이트 배열, 문자열, 튜플, range, byte와 같은 내장 시퀀스 형(type)들을 제공합니다.

시퀀스는 불변형가변형으로 구분할 수 있으며 한 객체내의 모든 요소의 자료형이 같은 동종형(homogeneous type)과 그렇지 않은 이종형(heterogeneous type)으로 분류할 수 있습니다. 예로서 문자열은 모든 요소가 문자로 이루어지므로 동종형입니다. 리스트는 수, 문자, 다른 리스트나 객체 등을 요소로 가질 수 있으므로 동종형 뿐만 아니라 이종형이 됩니다. 당연히 저장이나 연산에서 동종형이 이종형보다 효율적입니다.

이터러블(iterable)은 요소들를 하나씩 호출할 수 있는 객체를 의미합니다. 그러므로 문자형, 리스트를 포함하는 모든 시퀀스는 이터러블입니다. 그러나 모든 이터러블이 시퀀스가 아닙니다. 예로서 사전(dictionary)형 객체의 요소들은 인덱스를 가지지 않지만 반복문 등을 사용하여 각각의 요소를 호출할 수 있으므로 이터러블입니다. 다음 객체 dic는 사전형 객체로 반복문 중의 하나인 for 문을 사용하여 요소들 각각을 호출할 수 있습니다. 이 경우 사전의 키(key)만이 반환됩니다.

사전(dictionary) 형은 키와 값으로 구성되며 각각을 메소드로 호출할 수 있습니다. 그러나 다음 코드와 같이 사전 객체 자체에서 요소를 호출할 경우 인덱스 역할을 하는 키만이 호출됩니다. 값이나 키와 값을 모두 호출하기 위해서는 .values()와 .items() 메소드를 사용합니다.

dic={'book':1, 'computer':2}
for i in dic:
    print(i)
book
computer
for i in dic.values():
    print(i)
1
2
for i in dic.items():
    print(i)
('book', 1)
('computer', 2)

위 결과에 의하면 사전형은 시퀀스는 아니지만 이터러블 객체입니다.

  • 시퀀스(sequence)
    • 인덱스에 의해 객체의 각 요소에 순서가 정해져 있는 객체
    • 리스트, 튜플, 문자열, range
  • 이터러블(iterable)
    • 객체의 각 요소를 개별적으로 호출할 수 있는 객체
    • 지연된 평가가 이루어지는 이터레이터(iterator) 역시 이터러블

set 형은 내부의 요소들에 인덱스를 포함하지 않습니다. 즉, 각 요소에 순서를 지정할 수 없으므로 시퀀스 객체는 아닙니다. 그러나 for 문을 사용하여 요소를 하나씩 참조할 수 있습니다. 그러므로 set 형은 이터러블이지만 시퀀스는 아닙니다.

x=set([3, 1, 5, 7]); x
{1, 3, 5, 7}
for i in x:
  print(i)
1
3
5
7
x[0]
TypeError: 'set' object is not subscriptable

모든 객체는 기본적으로 숫자(number), 문자열(string), 리스트(list), 사전(dictionary), 집합(set) 등의 유형에 포함되며 각 자료형은 그에 대응하는 고유한 클래스(class)와 연결됩니다. 그러므로 사용자가 생성하는 객체는 이 자료형들 중 하나의 클래스와 연결되는 객체가 됩니다. 클래스는 자체적인 속성과 메서드(함수)를 가지며, 특정한 클래스와 연결된 객체는 그 클래스의 속성과 메소드를 사용할 수 있습니다. 이터러블 중 인덱스 없이 요소를 호출할 수 있는 것은 클래스에 이러한 동작을 일으키는 메소드를 가진다는 것을 의미합니다. 파이썬은 클래스를 생성할 경우 자동적으로 부여되는 내장 속성과 메소드를 제공하는데 그 중의 하나인 속성 __iter__가 이터러블을 생성합니다.

내장 메소드 또는 속성은 이름 앞뒤로 이중 밑줄(under score)를 함유하고 있으며 파이썬에서 객체를 생성할 경우 자동적으로 부여되는 메소드입니다. 메소드(method)는 작동 영역이 한정된 함수로서 "클래스" 편에서 자세히 소개합니다.

객체의 클래스가 포함하는 속성이나 메서드는 dir(객체) 함수로 확인할 수 있습니다. 위의 set 형 객체인 x의 모든 속성과 메서드들은 다음과 같습니다.

print(dir(x))
['__and__', '__class__', '__class_getitem__', ..., 'symmetric_difference_update', 'union', 'update']

이터러블(iterable) 객체는 내장 속성인 __iter__를 포함합니다. 연산자 in을 사용하여 이 속성의 포함 여부를 알아봅니다.

'__iter__' in dir(x)
True

이터러블이 시퀀스보다 광의적인 개념입니다.

이터레이터(iterator)

다음 코드는 내장함수 range()이 할당된 객체 x로서 range 형입니다. 이 타입은 파이썬의 기본 자료형(수, 문자형, 리스트, 튜플, 집합, 사전 등)에 포함되지 않은 상태이므로 평가가 이루어지지 않습니다. 즉, 객체의 구체적인 내용을 반환하지 못하는 상태로 단지 객체의 생성만을 나타냅니다.

x=range(9);x
range(0, 9)
type(x)
range

다음 결과는 객체 x의 각 요소에 인덱스가 부여 됨을 의미합니다. 또한 for 반복문에 의해 각각의 요소를 호출할 수 있습니다. 즉, 이 객체는 스퀀스이며 이터러블입니다.

x[2]
2
for i in x:
    print(i, end=" ")
0 1 2 3 4 5 6 7 8

위의 인덱스와 for 문 사용외에 이 객체를 평가하기 위해서는 객체의 자료형을 평가 가능한 기본형으로 변환해야 합니다. 다음은 리스트형으로 변환하기 위해 list() 함수를 적용한 것입니다.

list(x)
[0, 1, 2, 3, 4, 5, 6, 7, 8]

객체 x와 같이 객체 생성 후 평가를 위한 부가적인 작업이 필요한 평가 방식을 지연된 평가(lazy evaluation)라 하며 이러한 방식으로 평가되는 객체들은 위와 같이 요소들을 하나씩 호출할 수 있습니다. 즉, 이터러블입니다. 이 지연된 평가와 이터러블의 두 특성을 모두 가진 객체를 이터레이터(iterator)라고 합니다. 이터레이터의 이 지연된 평가 방식은 변환 등의 부가적인 실행이 이루어질 때까지는 실행되지 않기 때문에 메모리 관리에 효율적입니다.

이터레이터(Iterator)

이터레이터는 이터러블(iterable)이면서 지연된 평가(lazy evaluation)에 의해 실행되는 객체입니다.

이터레이터 객체를 생성하는 클래스는 내장 메소드__iter____next__를 포함합니다. 메소드 __iter__는 이 객체가 이터러블임을 나타내고 __next__는 지연된 방식으로 평가됨을 의미합니다. 즉, 이터레이터는 위에서 소개한 for 문이나 list() 등의 부가적인 적용 이전에 스스로 평가할 수 있는 장치인 __next__ 메소드를 가지고 있습니다.

  • __iter__()
    • 이터러블 객체에 포함되는 내장 메소드(built-in method)
    • 이 메소드 실행으로 __next__ 메서드를 생성, 즉 이터레이터로 전환
      • 이터러블 객체.__iter__() ⇒ 이터레이터 객체 생성
      • 내장 함수 iter(이터러블)를 사용하여 이터레이터 객체를 생성할 수 있음
  • __next__()
    • 이터러블이면서 지연된 평가로 이루어지는 객체는 __iter__와 함께 포함되는 내장 메소드
    • 객체의 요소를 하나씩 반환하는 메서드
    • 이 메소드에 의해 반환된 요소는 메모리에서 삭제 됩니다.
    • 모든 항목이 반환된 경우(평가된 경우) 파이썬 자체적으로 제공하는 에러(예외)의 종류인 StopIteration가 발생
    • 내장 메소드 __iter__(), __next__()를 포함하는 객체인 경우 내장함수 next()함수를 적용할 수 있음

다음 객체 a는 리스트이므로 이터러블이지만 지연된 평가방식을 따르지 않습니다. 그러므로 이 객체와 연결된 리스트 클래스는 내장 메소드 __iter__()는 포함하지만 __next__()는 가지고 있지 않습니다. 내장함수 dir()로 확인할 수 있습니다.

a=[1,2,3]; a
[1, 2, 3]
'__iter__' in dir(a)
True
'__next__' in dir(a)
False

즉, 위 객체 a는 이터러블이지만 이터레이터는 아닙니다. 그러나 __iter__() 메소드를 포함하므로 다음과 같이 객체내에 이 메소드를 활성시키는 것으로 __next__()와 연결할 수 있습니다. 결과적으로 객체 a를 이터레이터로 변환할 수 있습니다.

a1=a.__iter__()
a1
<list_iterator at 0x7f2ce4b655e0>
'__next__' in dir(a1)
True
print(next(a1))
print(next(a1))
print(next(a1))
print(next(a1))
1
2
3
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[35], line 4
      2 print(next(a1))
      3 print(next(a1))
----< 4 print(next(a1))

StopIteration: 

내장 메소드 __iter__()를 포함하는 객체 즉, 이터러블 객체의 경우 내장함수 iter()next()를 사용하여 위 코드와 동일하게 이터레이터를 생성할 수 있습니다.

b=["a", 1, "b", 3]
print("__iter__" in dir(b))
print("__next__" in dir(b))
True
False

위 결과에 의하면 객체 b는 이터러블이지만 이터레이터는 아닙니다. iter() 함수를 사용하여 이터레이터로 전환할 수 있습니다.

b1=iter(b)
print("__iter__" in dir(b1))
print("__next__" in dir(b1))
True
True

객체 b1은 이터레이터입니다. 그러므로 next() 함수를 사용하여 요소를 하나씩 호출할 수 있습니다.

print(next(b1))
print(next(b1))
print(next(b1))
print(next(b1))
print(next(b1))
a
1
b
3

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[41], line 5
      3 print(next(b1))
      4 print(next(b1))
----< 5 print(next(b1))

StopIteration: 

시퀀스의 메소드

표 1은 시퀀스 객체에 적용할 수 있는 메소드를 나타냅니다.

표 1 시퀀스 메서드
메서드내용
len(seq) 시퀀스의 크기(요소의 수)를 반환
element in seq element가 seq에 포함 여부를 판단
seq.index(element, start, end) seq내에 element의 인덱스를 반환
(element가 여러개 존재할 경우 첫번째 인덱스를 반환)
검색을 시작할 위치(start)와 종료위치(end)를 지정할 경우
대상의 인덱스를 반환, end는 생략 가능
min(seq), max(seq) seq의 최소값, 최대값을 반환
seq1 + seq2 seq1과 seq2의 결합
seq * n seq를 n번 반복
seq1=[97, 98, 99]
seq2='good morning'
len(seq1)
3
len(seq2)
12
99 in seq1
True
'p' in seq2
False
seq2.index('o')
1
seq2.index('o', 3)
6
min(seq1), max(seq2)
(97, 'x')
seq1+seq2
[97, 98, 99, 'a', 'b', 'x', 'c', 'x']
seq1 *3
[97, 98, 99, 97, 98, 99, 97, 98, 99]

이 블로그의 인기 게시물

유사변환과 대각화

내용 유사변환 유사행렬의 특성 대각화(Diagonalization) 유사변환(Similarity transformation) 유사변환 n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사하다고 하며 이 변환을 유사 변환 (similarity transformation)이라고 합니다. $$\begin{equation}\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B \end{equation}$$ 식 1의 유사 변환은 다음과 같이 고유값을 적용하여 특성 방정식 형태로 정리할 수 있습니다. $$\begin{align} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align}$$ 위 식의 행렬식은 다음과 같이 정리됩니다. $$\begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \t

[matplotlib] 히스토그램(Histogram)

히스토그램(Histogram) 히스토그램은 확률분포의 그래픽적인 표현이며 막대그래프의 종류입니다. 이 그래프가 확률분포와 관계가 있으므로 통계적 요소를 나타내기 위해 많이 사용됩니다. plt.hist(X, bins=10)함수를 사용합니다. x=np.random.randn(1000) plt.hist(x, 10) plt.show() 위 그래프의 y축은 각 구간에 해당하는 갯수이다. 빈도수 대신 확률밀도를 나타내기 위해서는 위 함수의 매개변수 normed=True로 조정하여 나타낼 수 있다. 또한 매개변수 bins의 인수를 숫자로 전달할 수 있지만 리스트 객체로 지정할 수 있다. 막대그래프의 경우와 마찬가지로 각 막대의 폭은 매개변수 width에 의해 조정된다. y=np.linspace(min(x)-1, max(x)+1, 10) y array([-4.48810153, -3.54351935, -2.59893717, -1.65435499, -0.70977282, 0.23480936, 1.17939154, 2.12397372, 3.0685559 , 4.01313807]) plt.hist(x, y, normed=True) plt.show()

R 미분과 적분

내용 expression 미분 2차 미분 mosaic를 사용한 미분 적분 미분과 적분 R에서의 미분과 적분 함수는 expression()함수에 의해 생성된 표현식을 대상으로 합니다. expression expression(문자, 또는 식) 이 표현식의 평가는 eval() 함수에 의해 실행됩니다. > ex1<-expression(1+0:9) > ex1 expression(1 + 0:9) > eval(ex1) [1] 1 2 3 4 5 6 7 8 9 10 > ex2<-expression(u, 2, u+0:9) > ex2 expression(u, 2, u + 0:9) > ex2[1] expression(u) > ex2[2] expression(2) > ex2[3] expression(u + 0:9) > u<-0.9 > eval(ex2[3]) [1] 0.9 1.9 2.9 3.9 4.9 5.9 6.9 7.9 8.9 9.9 미분 D(표현식, 미분 변수) 함수로 미분을 실행합니다. 이 함수의 표현식은 expression() 함수로 생성된 객체이며 미분 변수는 다음 식의 분모의 변수를 의미합니다. $$\frac{d}{d \text{변수}}\text{표현식}$$ 이 함수는 어떤 함수의 미분의 결과를 표현식으로 반환합니다. > D(expression(2*x^3), "x") 2 * (3 * x^2) > eq<-expression(log(x)) > eq expression(log(x)) > D(eq, "x") 1/x > eq2<-expression(a/(1+b*exp(-d*x))); eq2 expression(a/(1 + b * exp(-d * x))) > D(eq2, "x") a * (b * (exp(-d * x) * d))/(1 + b