- 예제1

a=11
if a<5: 
    print('a=....1,2,3,4')
elif a>10: 
    print('a=11,12,13,....')
else: 
    print('a=5,6,7,...,10')
a=11,12,13,....

- 예제2

a,b=2,3 
if a==b:
    print('a=b')
else: 
    if a<b: 
        print('a<b')
    else:
        print('a>b')
a<b

- 예제3

a=2
if a==1: 
    print('a=1')

2이면 뭐 하라고 한 적 없으니까 그냥 아무것도 실행하지 않음

for 문

- 예제1-리스트!

for i in [1,2,3,4]:
    print(i)
1
2
3
4
i
4

i는 4로 저장되고 종료

- 예제2- 튜플!

for i in (1,2,3,4):
    print(i)
1
2
3
4

- 예제3-스트링!

for i in '1234':
    print(i)
1
2
3
4

- 의문

for i in ???: 
    print(i)

에서 물음표 자리에 올 수 있는 것이 무엇일까?

- 예제4

a=5 
for i in a:
    print(i)

이렇게 입력하면 에러 발생

5라고 출력될 줄 알았는데 아니었다.

무슨 차이인가?

1차원 이상의 자료에서 for문 정의가 가능하다

- 예제5

L=[[1,2,3],[3,4,5]]
for i in L:
    print(i)
[1, 2, 3]
[3, 4, 5]
import pandas as pd
df=pd.DataFrame(L)
df
0 1 2
0 1 2 3
1 3 4 5
for i in df:
    print(i)
0
1
2

column명 불러오는 건가?

import numpy as np 
ndr=np.array(L)
ndr
array([[1, 2, 3],
       [3, 4, 5]])
for i in ndr: 
    print(i)
[1 2 3]
[3 4 5]
i
array([3, 4, 5])

for문의 동작원리

for i in ???: 
    print(i)

??? 자리에 올 수 있는 것은 dir()하여 __iter__()라는 메서드가 있는 object이다.

이러한 오브젝트를 iterable한 object라 한다

a=1
dir(a)
['__abs__',
 '__add__',
 '__and__',
 '__bool__',
 '__ceil__',
 '__class__',
 '__delattr__',
 '__dir__',
 '__divmod__',
 '__doc__',
 '__eq__',
 '__float__',
 '__floor__',
 '__floordiv__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__index__',
 '__init__',
 '__init_subclass__',
 '__int__',
 '__invert__',
 '__le__',
 '__lshift__',
 '__lt__',
 '__mod__',
 '__mul__',
 '__ne__',
 '__neg__',
 '__new__',
 '__or__',
 '__pos__',
 '__pow__',
 '__radd__',
 '__rand__',
 '__rdivmod__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rfloordiv__',
 '__rlshift__',
 '__rmod__',
 '__rmul__',
 '__ror__',
 '__round__',
 '__rpow__',
 '__rrshift__',
 '__rshift__',
 '__rsub__',
 '__rtruediv__',
 '__rxor__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__sub__',
 '__subclasshook__',
 '__truediv__',
 '__trunc__',
 '__xor__',
 'as_integer_ratio',
 'bit_length',
 'conjugate',
 'denominator',
 'from_bytes',
 'imag',
 'numerator',
 'real',
 'to_bytes']

예상대로 int클래스의 인스턴스는 __iter__()가 없다.

- 위에서 정의한 L(list), df, ndr(ndarray) 는 모두 __iter__() 함수가 있다. 따라서 iterable한 오브젝트이다.

iterable한 오브젝트는 iterator로 만들 수 있는 특징이 있다.

iterable한 오브젝트를 어떻게 iterator로 만드는가?

df
0 1 2
0 1 2 3
1 3 4 5
dfiter1=df.__iter__()
dfiter2=iter(df)
dfiter1?
Type:        generator
String form: <generator object RangeIndex.__iter__ at 0x0000028645753270>
Docstring:   <no docstring>

- dfiter1은 generator라는 클래스에서 만들어진 인스턴스 오브젝트이다.

dir(dfiter1)
['__class__',
 '__del__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__lt__',
 '__name__',
 '__ne__',
 '__new__',
 '__next__',
 '__qualname__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'close',
 'gi_code',
 'gi_frame',
 'gi_running',
 'gi_yieldfrom',
 'send',
 'throw']
dfiter1.__next__()
1

next 메소드? 카운트 느낌!, BUT 영구적인 것은 아니고 STOP하게 됨


for 문의 작동원리

for i in L:
    print(i)

(1) iter함수를 사용해서 L이라는 오브젝트를 iterator로 만든다. L이라는 오브젝트가 이터러블하기 때문에 가능

(2) iterator에서 .__next__()함수를 호출하고 결과를 i에 저장한뒤에 for문 블락안에 있는 내용(들여쓰기 된 내용)을 실행한다.

(3) StopIteration 에러가 발생하면 for 문을 멈춘다.

이런 원리로 for문이 돌아가는 듯!


Liter=iter(L)
Liter.__next__()
[1, 2, 3]

123나오고 345 나오고 STOP

ndriter=iter(ndr)
print(ndriter.__next__())
[1 2 3]

range()

- for문의 정석은 아래와 같이 range()를 사용하는 것이다.

for i in range(5):
    print(i)
0
1
2
3
4

in 다음애는 iterable만 가능

- range(5)의 정체는 그냥 iterable object이다.

a=range(5)

- 그래서 언제든지 iterator로 바꿀 수 있다.

aiter=iter(a)
aiter.__next__()
4

0~4까지 출력 후 error 출력

이터레이터의 개념은 디버깅에 응용가능

for i in zip([1,2,3],'abc'):
    print(i)
(1, 'a')
(2, 'b')
(3, 'c')
zip([1,2,3],'abc')
<zip at 0x28645783d80>

어차피 for i in ????: ????의 자리는 iterable object 자리이다.

z=zip([1,2,3],'abc')
dir(z)
['__class__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__lt__',
 '__ne__',
 '__new__',
 '__next__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__']

- __next__()함수가 있음 $\to$ z자체가 iterator였다. (iterable object 이면서)

z.__next__()
(2, 'b')

첫번째, 두번째, 세번째 그리고 마지막엔 에러

for i in ???: 
    print(i)

- ??? 자리에 iterator 자체가와도 무방한 듯!!!

- 확인

L=iter([1,2,3,4])
for i in L:
    print(i)
1
2
3
4
i
4