목차보기

로직4_Logic

분기문은 어떤 특정 조건에 따라서, 임무를 추가로 수행하거나, 건너뛸 수 있습니다. 분기문의 조건에는 사용자의 입력이나, 센서의 반응, 시간 충족 등이 변수에 영향을 주고, 변수의 상태에 따라 분기가 결정됩니다.

들여쓰기

로직, 함수, 모듈, 객체 등 sub루틴에 진입할 때, 들여쓰기를 합니다. 문법에 위배되지 않지만, PEP 8(Python Enhancement Proposal 8)에서는 들여쓰기를 'tab'을 사용하기보다, '띄어쓰기 4회'를 사용할 것을 권장합니다. 이는 코드를 작성, 공유하는 사람들에게 일관성을 부여합니다.

모든 .py파일에 대하여 tab size를 4로 고정하기 위해서는 "setting.json"에 다음과 같이 추가해야 합니다.

"[python]": {
  "editor.insertSpaces": true,
  "editor.tabSize": 4
},

if

if문은 가장 단순한 분기를 만들어냅니다.

4_Logic > 01_IF.py
if val == 1:
    print("val is 1")
  
4_Logic > 01-1_else.py
if val == 1:
    print("val is 1")
elif val == 2:
    print("val is 2")
elif val == 3:
    print("val is 3")
else:
    print("val is not 1, 2 or 3")

match

match문은 if문이 연속으로 있는 것과 같습니다. 가독성이 좋아집니다.

case _:는 다른 언어의 default:와 동일합니다. 모든 case에 해당사항이 없을 때, 수행됩니다.

4_Logic > 02_Match.py
match val:
    case 1:
        print("first")
    case 2:
        print("second")
    case 3:
        print("third")
    case _:
        print("none of those")

조건이 2가지 일 때,

match val:
    case 1 | 2:
        print("val is 1 or 2")

for

for문은 n번 반복합니다.

4_Logic > 03_For.py
for i in (1, 2, 3, 4, 5):
    print(i, end=" ")  # 0 1 2 3 4
4_Logic > 03-1_Range.py
for i in range(5):  # 0이상 5미만
    print(i, end=" ")  # 0 1 2 3 4
  
for i in range(1, 5):  # 1이상 5미만
    print(i, end=" ")  # 1 2 3 4

for ... else

for ... else는 for문이 break없이 모두 수행 되었을 때, 수행합니다.

4_Logic > 03-2_For_else.py
for i in range(5):
    print(i, end=" ")
else:
    print("for else #1") # 수행 됩니다.

for i in range(5):
    if i == 3:
        break
    print(i, end=" ")
else:
    print("for else #2") # 수행되지 않습니다.

while

while문은 조건이 참이면 반복합니다. 조건의 변화가 없다면 무한으로 반복합니다.

4_Logic > 04_While.py
while i < 5:
    print(i)
    i += 1

break/continue

  • break를 만나면, loop를 탈출합니다.
  • countinue를 만나면, loop의 처음으로 이동합니다.
4_Logic > 05_Break.py
for i in range(10):
    if i == 2:
        continue # 이번 루틴만 건너 뜀
    if i == 5:
        break # 현재 루프를 종료
    print("%d 번째" % i)

pass, 미구현

로직, 함수, 모듈, 객체 등 구현할 때, 반드시 내용을 포함해야 합니다. 다만, 당장 구현이 어려운 경우 해당 부분을 미구현으로 남겨둘 수 있습니다.

4_Logic > 06_Pass.py
val = 1
if val == 1:
    pass
else:
    print(val)

함수5_Function

  • 코드의 재사용을 위해 함수를 사용합니다.
  • 함수를 호출하기 위해서는 먼저 함수가 정의되어야 합니다.
  • 함수를 정의 할 때 def(define, 정의하다) 키워드를 사용합니다.
  • :(콜론)으로 마무리 합니다.
  • 내용(body)는 들여쓰기(indentation) 후 작성합니다.
  • 함수의 작명규칙은 변수와 동일합니다(소문자+'_' 권장).
  • 함수는 정의 및 호출시 소괄호()를 붙여야 합니다.
5_Function > 01_Function.py
def func1(): # define 정의
    print("contents 1") # 함수 내용
    print("contents 2") # 함수 내용2

func1() # call 호출
func1() # call 호출(2번째)

scope

global vs. local
global local
위치 main stream sub stream(function, object ...)
접근 모든 위치에서 접근 가능 해당 위치에서만 접근 가능

local변수가 필요한 이유

그럼에도 불구하고 구조적으로 global변수에 접근을 하려면 global keywords를 사용합니다.

5_Function > 01-3_Scope.py
def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam) # After local assignment: test spams
    do_nonlocal()
    print("After nonlocal assignment:", spam) # After nonlocal assignment: nonlocal spam
    do_global()
    print("After global assignment:", spam) # After global assignment: nonlocal spam
    # 접근 위치가 scope_test()이기 때문에 nonlocal이 호출

print("In global scope:", spam) # In global scope: global spam

arguments

입력인자를 통한 정보전달

5_Function > 02_Arguments.py
def func1(x): # step 2: 100 받음
    print(x) # step 3: 100 출력
  
func1(100); # step 1: 100 전달

기본 값

다음과 같이 선언할 때, 값을 지정하면, 호출할 때 값을 전달하지 않으면 기본값으로 설정됩니다.

5_Function > 02-1_Keywords.py
def func1(x=1):
    print(x)

func1(); # x=1

호출 방법

함수에게 정보를 전달하는 방법은 소괄호()안에 작성하는 방법입니다. 호출방법으로는:

모호함

'/', '*' 특수문자를 이용해서 argument의 특징을 강제할 수 있습니다.

5_Function > 02-3_Ambiguity.py
def foo(name, /, **kwds): # '/' 문자로 name의 성격을 pos로 강제
    return "name" in kwds  # name은 kwds의 name임이 확실합니다.

def bar(name, **kwds):
    return "name" in kwds  # kwds의 name인지, bar arg의 name인지???

ret = foo(1, **{"name": 2})

ret = bar(1, **{"name": 2})  # TypeError: bar()...

return 반환

5_Function > 03_Return.py
def ret100(): # step 2: 함수 시작
    return 100 # step 3: 100 반환
  
ans = ret100() # step 1: 함수 호출
# step 4: ans에 100 저장

가변 함수

입력 인자의 갯수가 일정하지 않을 때(가변), '*'기호를 이용해서 전달 받을 수 있습니다.

5_Function > 04_Sequence.py
def concat(*args, sep="/"):
    return sep.join(args)

concat("earth", "mars", "venus", "mercury", "jupiter")
# 출력: earth/mars/venus/mercury/jupiter
5_Function > 04-1_Unpack.py
def unpack(*args):
  for i in args:
      print(i, end=" ")

unpack("earth", "mars", "venus") # 출력: earth mars venus

딕션네리(자료형) 전달

5_Function > 05_Dictionary.py
def search(index="name", **dict):
  print(dict[index])

dict = {"name": "광해군", "year": 1592} # 출력: 광해군

함수 부가 정보 관리

Documentation, 문서화(함수 설명서)

  - 함수 뒤에 """로 작성된 문자열을 반환합니다.

5_Function > 06_Documentation.py
def f():
    """
    This is a function that prints the string 'Hello, world!'
    :return: None
    """
    print("Hello, world!")
    
print(f.__doc__)

Annotation, 주석(함수 인자, 리턴의 성격 출력)

5_Function > 07_Annotation.py
def f(ham: str, eggs: str = "eggs") -> str:
    print("Annotations:", f.__annotations__)
    # 출력: Annotations: {'ham': , 'eggs': , 'return': }

f("spam")

Lambda

Lambda(람다) 함수는 함수의 이름을 기술하지 않고, 간략하게 작성됩니다. 다음 경우에 설계합니다.

5_Function > 08_Lambda.py
def make_incrementor(n):
    return lambda x: x + n

f = make_incrementor(42)
print(f(0)) # 출력 : 42
print(f(1)) # 출력 : 43

콜렉션6_Collections

콜렉션은 자료구조, 데이터 묶음에 대하여 다룹니다.

list

6_Collections > 01_List.py
#         0         1        2       3         4       5        6
fruits = ["orange", "apple", "pear", "banana", "kiwi", "apple", "banana"]

fruits[0] # orange

fruits[6] # banana

fruits[3] = "tomato" # banana -> tomato
# ['orange', 'apple', 'pear', 'tomato', 'kiwi', 'apple', 'banana']
6_Collections > 01-1_Loop technique.py
for fruit in fruits:
    print(fruit, end=", ")
# 출력: orange, apple, pear, banana, kiwi, apple, banana, 

리스트의 찾기, 통계, 추가/삭제, 역순, 정렬 예제

List 함수
함수명 기능 비고
append(x) 아이템 추가 a[len(a):] = [x]
extend(iterable) 아이템 추가 a[len(a):] = iterable
insert(i, x) 주어진 위치(i)에 항목(x)을 삽입
remove(x) 리스트에서 값이 x와 같은 첫 번째 항목을 삭제. 없으면 ValueError
pop([i]) 주어진 위치(i)를 삭제, 생략시 마지막 아이템 삭제
clear() 모든 리스트 내 아이템 삭제 del a[:]
index(x[, start[, end]]) 리스트에 있는 항목 중 값이 x 와 같은 첫 번째 것의 인덱스 반환. 없으면 ValueError
count(x) 리스트에서 x 가 등장하는 횟수
sort(*, key=None, reverse=False) 정렬, 정렬 기준과 규칙(오름차순)
reverse() 리스트의 요소들을 거꾸로 배치
copy() 리스트 복사 b = a[:]
6_Collections > 01-2_List method.py
print(fruits.count("apple"))  # 2, 통계(갯수)
print(fruits.index("banana"))  # 3, 찾기(0부터)

fruits.reverse()
# 거꾸로 나열: ["banana", "apple", "kiwi", "banana", "pear", "apple", "orange"]

fruits.append("grape")
# 멤버 추가: ["banana", "apple", "kiwi", "banana", "pear", "apple", "orange", "grape"]

fruits.sort()
# 정렬(a~z): ["apple", "apple", "banana", "banana", "grape", "kiwi", "orange", "pear"]

print(fruits.pop()) # pear, 마지막 멤버

리스트 묶기

2개 이상의 리스트를 동시에 취급할 수 있습니다.

6_Collections > 01-2a_Zip.py
questions = ["name", "quest", "favorite color"]
answers = ["lancelot", "the holy grail", "blue"]
for q, a in zip(questions, answers):
    print("What is your {0}?  It is {1}.".format(q, a))
# What is your name?  It is lancelot.
# What is your quest?  It is the holy grail.
# What is your favorite color?  It is blue.

리스트간 비교하기

  1. 앞의 멤버부터 비교한다.
  2. 멤버의 수가 많은 것이 우선한다.
  3. 세부 리스트가 있다면, 세부 리스트끼리 비교한다.
6_Collections > 01-3_Compare.py
a = (1, 2, 3, 100)
b = (1, 2, 4, -100)
# (1, 2, 4, -100) > (1, 2, 3, 100)

a = (1, 2)
b = (1, 2, -1)
# (1, 2, -1) > (1, 2)

a = (1, 2, ("zz", "aa"))
b = (1, 2, ("aa", "ab", "ac"), 4)
# (1, 2, ('zz', 'aa')) > (1, 2, ('aa', 'ab', 'ac'), 4)

응용

stack으로 이용하기

6_Collections > 01-4_As stack.py
stack = [3, 4, 5]

stack.append(6)  # [3, 4, 5, 6]
stack.append(7)  # [3, 4, 5, 6, 7]

stack.pop()  # 7  # [3, 4, 5, 6]

stack.pop()  # 6  # [3, 4, 5]

stack.pop()  # 5  # [3, 4]

queue로 이용하기

6_Collections > 01-5_As queue.py
queue = deque(["Eric", "John", "Michael"])
queue.append("Terry") # deque(['Eric', 'John', 'Michael', 'Terry'])

queue.append("Graham") # deque(['Eric', 'John', 'Michael', 'Terry', 'Graham'])

print(queue.popleft())  # "Eric" - The first to arrive now leaves
print(queue.popleft())  # "John" - The second to arrive now leaves
# deque(['Michael', 'Terry', 'Graham'])

자동생성하기 Comprehension

6_Collections > 01-6_List Comprehensions.py
squares = []
for x in range(10):
    squares.append(x**2)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

comb = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
# [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

다중 리스트

6_Collections > 01-7_Nested list.py
matrix = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9, 10, 11, 12],
]

matrix[1][1] #6

transposed = [[row[i] for row in matrix] for i in range(4)]
# [ [1, 5, 9],
#   [2, 6, 10],
#   [3, 7, 11],
#   [4, 8, 12]
#]

멤버 삭제

6_Collections > 01-8_Del.py
a = [i for i in range(6)] # [0, 1, 2, 3, 4, 5]

del a[0] # [1, 2, 3, 4, 5]

del a[2:4] # [1, 2, 5]

del a[:] # []

tuple

튜플의 특징은 불변(선언하면 추후에 변경이 불가함)입니다. 단순 나열이라는 성질은 리스트와 동일한데, 굳이 튜플을 사용하는 이유는:

  1. 나중이라도 데이터가 변경되면 안 될 때(해쉬(지문)이라던가, 원본데이터 라든가)
  2. (리스트보다) 더 적은 메모리 사용
  3. (리스트보다) 더 빠른 성능
  4. 의도를 명확히 하고자 (이 변수는 앞으로 불변입니다.)
6_Collections > 02_Tuples.py
t = (12345, 54321, "hello!")
t2 = 12345, 54321, "hello!" # 생략 가능

empty = () # 빈 튜플
len(empty)  # 길이: 0

singleton = ("hello",)  # comma로 끝나도 무시함
# 출력: ('hello',)
len(singleton)  # 길이: 1

튜플 복사 예제(피보나치 수열): 데이터의 교환(a↔b)시 임시변수를 만드는 방법보다 효율적

6_Collections > 02-9a_Fibonacci.py
a, b = 0, 1
while a < 10:
    print(a)
    a, b = b, a + b  # (a, b) = (b, a + b) 튜플 복사  

set

Set(집합): 중복을 인정하지 않는 리스트

6_Collections > 03_Set.py
basket = {"apple", "orange", "apple", "pear", "orange", "banana"}
# {"orange", "banana", "pear", "apple"} - 중복된 것 삭제

"orange" in basket  # True - fast membership testing
"crabgrass" in basket  # False

합집합, 교집합, 차집합

a = set("abracadabra") # {'b', 'c', 'r', 'a', 'd'}
b = set("alacazam") # {'c', 'z', 'a', 'l', 'm'}

print(a - b)  # {'b', 'r', 'd'} = 차집합(A-B), 그룹A에만 있음

print(a | b)  # {'b', 'c', 'r', 'z', 'a', 'l', 'd', 'm'} = 합집합

print(a & b)  # {'c', 'a'} = 교집합

print(a ^ b)  # {'b', 'm', 'd', 'r', 'z', 'l'} = 합집합 - 교집합

dictionary

key:value(색인:값)을 하나의 멤버로 저장합니다.

6_Collections > 04_Dictionary.py
tel = {"jack": 4098, "sape": 4139}
tel["guido"] = 4127  # guido의 전화번호를 등록
# {"jack": 4098, "sape": 4139, "guido": 4127}

tel["jack"]  # 4098

del tel["sape"]  # sape 삭제
tel["irv"] = 4127  # irv 등록
# {"jack": 4098, "guido": 4127, "irv": 4127}

list(tel)  # ["jack", "guido", "irv"]

tel = sorted(tel)  # 정렬(오름차순)
# ["guido", "irv", "jack"]

"guido" in tel  # True
"jack" not in tel  # False

자동완성

6_Collections > 04-1_DictionaryComprehension.py
dict = {x: x**2 for x in (2, 4, 6)}
# {2: 4, 4: 16, 6: 36}

루프 기술

6_Collections > 04-2_Loop technique.py
knights = {"gallahad": "the pure", "robin": "the brave"}
for k, v in knights.items():
    print(k, v)
# gallahad the pure
# robin the brave

typecast

강제로 콜렉션 타입을 변경 할 수 있습니다.

6_Collections > 05_Typecast.py
menu = {"커피", "우유", "주스"}
# {'커피', '우유', '주스'} 

menu = list(menu)
# ['커피', '우유', '주스'] 

menu = tuple(menu)
# ('커피', '우유', '주스') 

menu = set(menu)
# {'커피', '주스', '우유'} 
이전 | 로직 | 다음