제어문

- 파이썬 구문은 위에서 아래로 순차적으로 수행됨, 순차적인 흐름에 영향을 주는 것 

- 제어문은 반복문, 조건문으로 구성

1. 반복문: 비슷한 형태의 작업을 반복적으로 수행

2. 조건문: 주어진 조건에 따라 작업의 수행 여부를 선택적으로 결정


if, elif, else


value = 10

if value > 5:

    print("value is bigger than 5")

value is bigger than 5

money = 10


if money > 100:

    item = "apple"

else:

    item = "banna"

    

print("#1 item:", item)


# 어떤 조건에 따라 변수의 값만 바뀌는 경우 

item = "apple" if money > 100 else "banna"

print("#2 item:", item)

#1 item: banna

#2 item: banna

# 사용자로 부터 정수값을 입력받아 그에 맞는 학점을 반환 

score = int(input('Input Score: '))

if 90 <= score <= 100:

    grade = "A"

elif 80 <= score < 90:

    grade = "B"

elif 70 <= score < 80:

    grade = "C"

elif 60 <= score < 70:

    grade = "D"

else:

    grade = "F"


print("Grade is " + grade)

Input Score: 77

Grade is C


* python에서는 c나 자바 계열의 언어와 달리 조건문의 수치 비교가 직관적이다.

- python: 70 <= score < 80

- c: grade >= 70 && grade < 80


조건식의 참/거짓 판단

조건식의 참/거짓 판단을 기본적으로 자료형의 bool 판단 값과 같음

print("bool(True): ", bool(True))

print("bool(False): ", bool(False))

print("bool(13): ", bool(13))

print("bool(0.0): ", bool(0.0))

print("bool('apple'): ", bool('apple'))

print("bool(''): ", bool(''))

print("bool(()): ", bool(()))

print("bool([10, 20, 'Apple']): ", bool([10, 20, 'Apple']))

print("bool({})", bool({}))

print("bool(None): ", bool(None))


bool(True):  True

bool(False):  False

bool(13):  True

bool(0.0):  False

bool('apple'):  True

bool(''):  False

bool(()):  False

bool([10, 20, 'Apple']):  True

bool({}) False

bool(None):  False


단축 평가

조건식 전체를 판단하지 않고, 순차적으로 진행하다 그 수실의 평가가 자명한 경우에 뒤의 수식을 평가하지 않는 것


1. 예외 발생 코드

a = 0

if a & 10 / a:

    print("a가 0입니다.")

else:

    print("에러없이 통과")


Traceback (most recent call last):

  File "/Users/eunguru/Source/Python/Control/src/Control.py", line 55, in <module>

    if a & 10 / a:

ZeroDivisionError: division by zero


2. 단축 평가가 이루어져 예외가 발생 하지 않는 코드

- and 앞 부분인 a가 0이기 때문에, 즉 false이기 때문에 뒤에 수식을 평가하지 않아도 false이다.

a = 0

if a and 10 / a:

    print("a가 0입니다.")

else:

    print("에러없이 통과")

에러없이 통과

- 파이썬에서는 and, or의 경우 반드시 좌변 피연산자가 우변 피연산자보다 먼저 단축 평가되도록 파이썬 인터프리터에서 보장


3. 단축 평가의 장점

- 조건문의 결과가 결정되는 시점 이후로 추가적인 판별 연산을 수행하지 않기 때문에 속도가 향상

- 예제와 같은 Run time error 발생을 try-except 구문이 아닌 논리식으로 사전에 차단 가능


while문

value = 5

while value > 0:

    print("value:", value)

    value -= 1

value: 5

value: 4

value: 3

value: 2

value: 1


for문

- 인자로 받은 시쿼스형 객체와 이터레이션이 가능한 객체를 순차적으로 순회

- for문에 사용될 수 있는 시퀀스형 자료로는 문자열, 리스트, 튜플, 사전과 같은 내장 클래스와 내장함수 iter()로 생성되는 이터레이터 객체, 또는 __iter__(), __next__() 객체


1. for문을 이용하여 리스트와 사전의 각 항목을 출력

l = ['Apple', 100, 15.23]

for i in l:

    print('i:', i, 'type(i):', type(i))


i: Apple type(i): <class 'str'>

i: 100 type(i): <class 'int'>

i: 15.23 type(i): <class 'float'>


d = {'Apple':100, 'Orange':200, 'Banana':300}

for k, v in d.items():

    print('key:', k, 'value:', v)


key: Orange value: 200

key: Banana value: 300

key: Apple value: 100


2. 이터레이터 객체를 이용하여 for문을 수행

l1 = [10, 20, 30]

iterator = iter(l1)

for i in iterator:

print('i:', i)


i: 10

i: 20

i: 30


3. for문이 동작하는 원리, 이터레이션 예제

1) 순회가능한 객체(리스트, 튜플, 문자열)에서 이터레이터 객체를 가져옴

- 이터레이터: 순회 가능한 객체의 요소를 순서대로 접근할 수 있는 객체

2) 이터레이터 안의 __next__() 메서드를 실행

- __next__(): 현재 이터레이터가 가리키고 있는 객체의 요소를 리턴, 객체의 다음 요소를 가리킴, 내장함수 next()를 사용하여 실행 할 수 있음

3)  StopIteration 예외를 만날때까지 반복적으로 __next__()를 수행

s = 'abc'

it = iter(s)

print("it:", it)

it: <str_iterator object at 0x101a20908>

print("next(it):", next(it))

next(it): a

print("next(it):", next(it))

next(it): b

print("it.__next__():", it.__next__())

it.__next__(): c


#print("next(it):", next(it))

'''

Traceback (most recent call last):

  File "/Users/eunguru/Source/Python/Function/src/Function.py", line 232, in <module>

    print("next(it):", next(it))

StopIteration

'''


4. 중첩 for문

for n in [2,3]:

    print("__{0} 단 --".format(n))

    for i in [1, 2, 3, 4, 5, 6, 7, 8, 9]:

        print("{0} * {1} = {2}".format(n, i, n*i))


__2 단 --

2 * 1 = 2

2 * 2 = 4

2 * 3 = 6

2 * 4 = 8

2 * 5 = 10

2 * 6 = 12

2 * 7 = 14

2 * 8 = 16

2 * 9 = 18

__3 단 --

3 * 1 = 3

3 * 2 = 6

3 * 3 = 9

3 * 4 = 12

3 * 5 = 15

3 * 6 = 18

3 * 7 = 21

3 * 8 = 24

3 * 9 = 27


break, continue, else

1. break

L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for i in L:

    if i > 5:

        break

    print("Item: {0}".format(i))

Item: 1

Item: 2

Item: 3

Item: 4

Item: 5


2. continue

L1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for i in L1:

    if i % 2 == 0:

        continue

    print("Item: {0}".format(i))

Item: 1

Item: 3

Item: 5

Item: 7

Item: 9


3. else

- 그동안 c나 java 같은 언어의 else문과는 쫌 다름...;;

1) else 블록이 수행

L2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for i in L2:

    if i % 2 == 0:

        continue

    print("-Item: {0}".format(i))

else:

    '''

    for, while과 같은 반복문이 수행도중 break로 인하여 

    중간에 종료되지 않고 끝까지 수행 되었을 떄 else 블록이 수행 

    '''

    print("Exit without break.")

print("Always this is printed")

-Item: 1

-Item: 3

-Item: 5

-Item: 7

-Item: 9

Exit without break.

Always this is printed

2) else 블록이 수행되지 않음

L3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for i in L3:

    if i > 5:

        break

    print("Item: {0}".format(i))

else:

    print("Exit without break.")

print("Always this is printed")


Item: 1

Item: 2

Item: 3

Item: 4

Item: 5

Always this is printed


제어문과 연관된 유용한 함수들

1. range()

range(['시작값',] 종료값[,'증가값'])

- 정수 수열을 얻는 내장 함수

- 종료값은 필수항목, 시작값과 증가값은 생략가능, 생략시 시작값은 0, 증가값은 1을 기본값으로 사용

- 이터레이션 가능한 객체가 반환

print('list(range(10)):', list(range(10)))

print('list(range(5, 10)):', list(range(5, 10)))

print('list(range(10, 0, -1)):', list(range(10, 0, -1)))

print('list(range(10, 20, 2)):', list(range(10, 20, 2)))


list(range(10)): [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

list(range(5, 10)): [5, 6, 7, 8, 9]

list(range(10, 0, -1)): [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

list(range(10, 20, 2)): [10, 12, 14, 16, 18]


for i in range(10, 20, 2):

    print(i)

10

12

14

16

18


2. 리스트 항목과 인덱스 값을 동시에 얻는 방법

1) for문을 이용한 방법

L4 = ['Apple', 'Orange', 'Banana']

for i in range(len(L4)):

    print("Index: {0}, Value: {1}".format(i, L4[i]))

Index: 0, Value: Apple

Index: 1, Value: Orange

Index: 2, Value: Banana

2) enumerate('시퀀스 타입 객체'[, '시작값' = 0 ]): 튜플 형태로 (인덱스, 시퀀스 객체 아이템)이 반환

L5 = [100, 15.5, 'Apple']

for i in enumerate(L5):

    print(i)

(0, 100)

(1, 15.5)

(2, 'Apple')

* 시작값: 인덱스 순번의 시작값, 생략가능, 생략시 0이 기본값

L6 = [100, 15.5, 'Apple']

for i, v in enumerate(L6, 101):

    print(i, v)

101 100

102 15.5

103 Apple


3. 리스트 내장

<표현식> for <아이템> in <시퀀스 타입 객체> (if <조건식>)

- 시퀀스 타입 객체: 시퀀스형 객체나 이터레이션 가능한 객체

- 아이템: 리스트 객체의 개별 아이템

- 표현식: 개별 아이템을 사용하여 사상함수 형태로 새로운 리스트 객체를 생성하는데 사용

- if 조건식: 조건식에 맞는 원본 리스트의 아이템을 선별하는 경우에 사용, 생략 가능

L7 = [1, 2, 3, 4, 5]

print([i ** 2 for i in L7])

[1, 4, 9, 16, 25]


t = ('apple', 'banana', 'orange')

print([len(i) for i in t])

[5, 6, 6]


d = {100:'apple', 200:'banana', 300:'orange'}

print([v.upper() for v in d.values()])

['BANANA', 'ORANGE', 'APPLE']


print([i**3 for i in range(5)])

[0, 1, 8, 27, 64]


L8 = ['apple', 'banana', 'orange', 'kiwi']

print([i for i in L8 if len(i) > 5])

['banana', 'orange']


L_1 = [3, 4, 5]

L_2 = [1.5, -0.5, 4]

print([x * y for x in L_1 for y in L_2])

[4.5, -1.5, 12, 6.0, -2.0, 16, 7.5, -2.5, 20]


4. filter()

filter(<function> | None, <이터레이션이 가능한 자료형>)

-  <function> | None : 함수의 이름으로 필터링할 방법을 제공, None을 사용하면 아무런 필터링도 수행하지 않음

(시퀀스 객체의 모든 아이템을 선택하고자 하는 경우 None을 사용)


1)  None을 사용하여 아무런 필터링도 하지 않음. 원본 리스트와 동일한 내용이 출력

L9 = [10, 25, 30]

IterL = filter(None, L9)

for i in IterL:

    print("Item: {0}".format(i))

Item: 10

Item: 25

Item: 30

2) 필터링할 함수를 지정하여 필터링

def GetBiggerThan20(i):

    return i > 20

L10 = [10, 25, 30]

IterL1 = filter(GetBiggerThan20, L10)

for i in IterL1:

    print("Item: {0}".format(i))

Item: 25

Item: 30

3) filter()내장함수는 이터레이터를 반환, 리스트나 튜플에 담기위해서는 list(), tuple()을 사용해야 함

NewL = filter(GetBiggerThan20, L10)

print('NewL:', NewL, 'type(NewL):', type(NewL))

print('list(NewL):', list(NewL))

print('L10:', L10)

NewL: <filter object at 0x1021a3eb8> type(NewL): <class 'filter'>

list(NewL): [25, 30]

L10: [10, 25, 30]

*   책에는 이터레이터를 반환한다고 했는데.. 실제 코드상으로는 filter클래스가 반환된다.

4) 람다 함수로 구현

IterL2 = filter(lambda i: i>20, L10)

for i in IterL2:

    print("Item: {0}".format(i))

Item: 25

Item: 30

* 람다 함수: 이름이 없고 함수 객체만 존재하는 익명함수, return 구문을 적을 수 없음

여러개의 인수를 입력 받을 수 있고, 하나의 리턴값을 돌려줌, 한줄을 실행한 결과 값이 리턴값이 됨

lambda 인수 : 구문

- 람다 함수 예제

# 람다 함수의 객체는 사용 후 바로 사라짐  

g = lambda x, y : x * y

print("g(10, 20):", g(10, 20))

print("(lambda x: x * x)(3):", (lambda x: x * x)(3))

g(10, 20): 200

(lambda x: x * x)(3): 9


5. zip()

- 시퀀스형이나 이터레이터형 객체를 튜플 형태로 쌍을 묶을 수 있음

- zip() 함수의 인자로는 내장 시퀀스형 자료, 이터레이터를 지원하는 사용자 클래스, 이터레이터 객체가 가능

- 결합을 시키고자 하는 개수만큼 올 수 있음


1) zip()함수로 결합하는 예제

x = [10, 20, 30]

y = ['A', 'B', 'C']

for i in zip(x, y):

    print("Item: {0}".format(i))

Item: (10, 'A')

Item: (20, 'B')

Item: (30, 'C')

2) zip()함수의 반환값 확인

print('zip(x,y):', zip(x,y), 'type(zip(x,y)):', type(zip(x,y)))

zip(x,y): <zip object at 0x1007afe08> type(zip(x,y)): <class 'zip'>

* 책에는 반환값은 쌍을 이룬 튜플 객체의 이터레이터 형이라고 나옴..

3) zip()함수의 결과값을 list()함수를 이용하여 리스트 객체에 저장하는 예제

RetList = list(zip(x, y))

print('RetList:', RetList, 'type(RetList):', type(RetList))

RetList: [(10, 'A'), (20, 'B'), (30, 'C')] type(RetList): <class 'list'>

4) zip()함수로 결합되어 있는 결과를 분리, zip()함수 호출시 결합된 객체나 이터레이터 인자 앞에 *를 붙여 분리

x2, y2 = zip(*RetList)

print('x2:', x2, 'type(x2):', type(x2))

print('y2:', y2, 'type(y2):', type(y2))

x2: (10, 20, 30) type(x2): <class 'tuple'>

y2: ('A', 'B', 'C') type(y2): <class 'tuple'>

5) 2개 이상의 객체의 결합

a = [10, 20, 30]

b = "ABC"

c = (1.5, 2.5, 3.5)

RetList2 = list(zip(a, b, c))

print('RetList2: ', RetList2)

RetList2:  [(10, 'A', 1.5), (20, 'B', 2.5)]

6) 결합을 하는 인자의 개수가 동일하지 않은 경우

- 가장 짧은 쪽을 기준으로 결합, 나머지 시퀀스 객체는 포함 되지 않음

a1 = [10, 20, 30]

b1 = "ABCDE"

RetList3 = list(zip(a1, b1))

print('RetList3: ', RetList3)

RetList3:  [(10, 'A'), (20, 'B'), (30, 'C')]


6. map()

map(<함수이름>, 이터레이션이 가능한 객체, ...)

- 시퀀스형 객체를 순회하면서 모든 값을 갱신

- map()함수는 객체를 순회하며 각 아이템을 첫 인자인 함수에 전달하고, 함수의 수행 결과를 이터레이터 객체로 생성하여 반환


1) 리스트 객체의 아이템을 10씩 증가시키는 예제

L11 = [1, 2, 3]

def Add10(i):

    return i + 10

for i in map(Add10, L11):

    print("Item: {0}".format(i))

print('L11:', L11)

Item: 11

Item: 12

Item: 13

L11: [1, 2, 3]

2) map()함수의 반환값 확인, map()함수의 첫번쨰 인수를 람다 함수로 구현, map()함수의 결과값을 list()함수를 이용하여 리스트 객체에 저장하는 예제

RetList4 = map(lambda i : i+10, L11)

print('RetList4:', RetList4, 'type(RetList4):', type(RetList4))

print('list(RetList4):', list(RetList4))

print('L11:', L11)

RetList4: <map object at 0x102a1a320> type(RetList4): <class 'map'>

list(RetList4): [11, 12, 13]

L11: [1, 2, 3]

3) 수행할 함수가 2개 이상의 인자를 받는 경우, map()함수를 호출할 때도 수행할 함수에 맞는 이터레이션 가능한 객체를 전달해야 함

x1 = [1, 2, 3]

y1 = [2, 3, 4]

RetList5 = list(map(pow, x1, y1)) #pow = x1**y1

print('RetList5:', RetList5)

RetList5: [1, 8, 81]

*pow(x,y)함수는 2개의 인자를 받아 x의 y제곱 연산을 수행함, x**y와 동일


효율적인 순회 방법

1. for문을 이용하는 방법

- print()함수가 리스트 아이템 개수만큼 호출됨

l2 = ['Apple', 'Orange', 'Banana']

for i in l2:

    print(i)

Apple

Orange

Banana

2. join()메서드나 리스트 내장을 이용하는 경우

- print()함수가 단 한번만 호출됨

1) join()메소드 이용

print("\n".join(l2))

Apple

Orange

Banana

2) 리스트 내장을 이용하는 경우

print("\n".join(for i in l2))

Apple

Orange

Banana

* 리스트의 항목이 많으면 속도 차이가 커질수 있음


참고

1. format()


'컴&프로그래밍 > Python' 카테고리의 다른 글

7. 예외처리  (0) 2015.01.02
6. 모듈  (0) 2014.12.29
Mac OS X Yosemite에서 PyCharm 설치 후 실행  (0) 2014.12.27
5. 클래스  (0) 2014.12.20
Google Python Tutorial - Basic Python Exercises #2 List  (0) 2014.12.11
Google Python Tutorial - Basic Python Exercises #1 String  (0) 2014.12.05
Python 2.x에서 3.x로 변경  (0) 2014.12.03
튜플 자료형 특이사항  (0) 2014.10.19
자료형과 연산자  (0) 2014.10.18