05 함수

|

05 함수

참고

애스크장고 AskDjango

함수

  • 함수는 코드 중복을 제거하기 위해 사용된다.
  • 구성
    • 1개의 함수명 (필수)
    • 0개 이상의 인자값 (선택)
    • 1개의 반환값 (선택) 반환값이 없는 경우에는 None을 리턴한다.

함수 유형

  • 인자 값, 반환 값 없는 함수
    def myfn1():
      result = 1 + 2
    print(myfn1())
    # 호출했지만, 반환값이 없어서  None 출력
    
  • 인자 값은 있지만, 반환 값은 없는 함수
    def myfn2(a, b, c):
      result = a + b + c
    print(myfn2(1, 2, 3))
    # 호출해도 반환값이 없어서 None 출력
    
  • 인자 값은 없지만, 반환 값은 있는 함수
    def myfn3():
      return 10
    print(myfn3())
    # 10 출력
    
  • 인자 값과 반환 값이 모두 있는 함수
    def myfn4(a, b, c):
      result = a + b + c
      return result
    print(myfn4(1, 2, 3))
    # 6 출력
    

Scope(변수의 유효 범위)

  • 변수가 선언되어, 해당 변수가 영향을 미치는 영역
  • 지역 변수(Local Variable): 함수 안에서 선언되어, 함수 내에서만 활용이 가능한 변수.
  • 전역 변수(Global Variable): 함수 밖에서 선언되어, 함수 안에서도 활용이 가능한 변수.

전역 변수같은 경우에는 코드의 가독성을 헤치므로 권장하지 않는다. 지역변수를 사용하여 값이 변동되어도, 버그 발생 확률을 낮출 수 있다. 하지만, 상수문법이 없는 파이썬에서 변수명을 전부 대문자로 입력하여 관례적으로 상수처럼 사용하기도 한다.

Positional/Keyword Arguments

인자

함수가 실행되는데 필요한 0개 이상의 변수 목록

Positional Arguments

인자의 위치에 기반한 인자

def fn_with_positional_arguments(name,age):
    print('이름: {} 나이: {}'.format(name,age))    
fn_with_positional_arguments('Tom',10)

Keyword Arguments

  • 인자의 이름에 기반한 인자
  • 디폴트 인자 문법이 함께 적용
    • 함수 호출 시에 해당 인자를 지정하지 않으면, 디폴트 인자값으로 값이 자동지정
  • key를 입력하지 않으면 위치기반으로 적용된다.
def fn_with_keyword_arguments(name="", age=0):
    print('이름: {} 나이: {}'.format(name,age))

# 키워드로 하면 순서 상관없다.
fn_with_keyword_arguments(name='Tom', age=10)
fn_with_keyword_arguments(age=10, name='Tom')

# 인자 지정하지 않으면, 디폴트 값으로 적용
fn_with_keyword_arguments(age=10)
fn_with_keyword_arguments(name='Tom')
# 키를 입력하지 않으면 위치 기반으로 적용
fn_with_keyword_arguments('Tom', 10)

기본 인자값은 함수가 실행될 때 계산되지 않고, 함수를 ‘정의’할 때 계산된다. 이러한 특성때문에 리스트나, 딕셔너리같은 mutuable한 데이터 타입은 문제를 일으킬 수 있다.

def buggy(arg, result=[]):
    result.append(arg)
    print(result)

처음 함수를 실행시에는 문제가 없어 보인다.

buggy(‘a’) [‘a’]

두번째로 함수를 실행했는데, ‘b’만 출력되는 것이 아니라 그 전의 ‘a’의 값도 남아 있는 것이다.

buggy(‘b’) [‘a’,’b’]

위에서 말했듯이, 기본 인자값은 정의 시 계산되기 때문에, result=[]는 메모리 어딘가에 지정이 되어있다. 그리고 리스트나 딕셔너리같은 mutuable 데이터 타입은 해당 메모리의 값을 변경할 수 있기 때문에 값을 변경해도 같은 메모리 주소에 반영이 된다. 그렇기에 위처럼 계속 기록이 되는 것이다.

위의 상황을 해결하긴 위해서 다음과 같이 작성해야 한다.

def nonbuggy(arg, result=None): #result를 None으로 지정
        if result is None:
            result = []
        result.append(arg)
        print(result)

Packing

인자의 개수를 제한하지 않고, 다수의 인자를 받을 수 있음 다수의 Positional Arguments를 하나의 tuple로 받는다.

def fn2(*colors):
    for color in colors:
        print(color)
fn2()
fn2('white')
fn2('white','yellow')
fn2('white','yellow','black','pink')
def fn3(color1, color2, *other_colors):
    print('color1:', color1)
    print('color2:', color2)
    for color in other_colors:
        print(color)
# 최소 2개의 인자 지정이 필요하다. 부족하면 TypeError
fn3('brown') # TypeError 발생
fn3('brown','green')
fn3('brown','green','white')
fn3('brown','green','whilte','yellow')

Unpacking

인자를 넘길 때 Sequence Data Type(리스트/튜플 등)을 다수의 인자인 것처럼 나눠서 전달 가능

colors = ['white', 'yellow', 'black']  
fn2(*colors) #white, yellow, black으로 3개 전달  
fn2('brown','pink',*colors)
#brown, pink, white, yellow, black으로 5개 전달  

other_colors = ('violet', 'coral', 'cyan')  
fn2('brown', 'pink', *colors, *other_colors)
#brown, pink, white, yellow, black, violet, coral, cyan

fn3('purple', *('aqua', 'beige', 'black'))
#purple, aqua, beige, black 튜플도 언패킹 가능

익명함수 (Anonymous Function)

lambda를 사용하여 익명 함수를 사용할 수 있다.

  • return문을 쓰지 않아도, 마지막 값을 리턴값으로 처리
  • 대개 인자로 1줄 함수를 지정할 때 많이 쓰임.
  • 일반 함수와 인자처리도 동일하게 처리된다.
# 인자 두 개를 받고 x + y 값은 반환하는 의미이다.
(lambda x, y: x + y)(1,2) # 바로 실행할 때

mysum3 = lambda *args: sum(args) # mysum에 할당
print(mysum3(1,2,3,4,5,6,7) # 28

1급객체

다른 객체들에 적용 가능한 연산을 모두 지원하는 객체

  • 인자로 넘기기, 변수에 대입하기 등
  • 종류: 일급 함수/클래스/컨트롤/타입/데이터타입 등

파이썬은 1급 함수/클래스를 지원한다.

  • 함수/클래스를 런타임에 생성 가능.
  • 함수/클래스를 변수에 할당이 가능
  • 함수/클래스를 인자나 리턴값으로서 전달 가능.

익명함수를 mysum1에 할당하고 이를 또 mysum2에 할당해도 잘 실행 된다.

mysum1 = lambda x, y: x + y
mysum2 = mysum1
mysum2(10,20) -> 30

함수를 인자로 받아 호출할 수 있다.

def myfn(fn, x, y):
    return fn(x,y)
myfn(mysum1, 10, 20) -> 30
myfn(lambda x,y:x*y, 10,20) -> 200
# 익명함수를 인자로 가능하다.
# 추후에 데코레이터에서 유용하게 사용할 수 있다.

고차함수 (Hign Order Function)

다른 함수를 생산/소비하는 함수 다른 함수를 인자로 받거나, 그 결과로 함수를 반환하는 함수

def base_calculator(base):
    wrap = lambda x, y: base + x + y
    return wrap
calc_10 = base_calculator(10)
# 이렇게 하면, calc_10은 lambda x, y: 10 + x +y의 함수를 가지게 된다.
calc_10(1,2) # 13
calc_10(10,20) # 40

04 흐름 제어

|

04 제어문

참고

애스크장고 AskDjango

조건문

if/else를 통해 참/거짓을 판별하여 흐름을 제어할 수 있다.

if 조건식:
  print("참이면 여기!")
else:
  print("거짓이면 여기!")

elif 추가해서 더 많은 경우로 나눌 수 있다.

score = 80
if score > 80:
  print("A")
elif score > 60:
  print("B")
else:
  print("C")

반복문

Iterable(반복가능한) Object로부터 가져올 값들을 모두 가져올 때까지 반복

for 변수 in Iterable Object:

  • 매 항목마다 수행할 코드 블록
  • 반복하다가 break문을 통해 반복문을 빠져나올 수 있다.
  • 또는 continue문을 통해 건너뛰고 위에서부터 진행할 수 있다.

기본

for i in range(20): # 0에서 19까지 순회
  print(i)
# 19까지 출력하면 더 이상 순회할기 없기에 위 반복문은 종료된다.

break

if문을 곁들여 조건에 성립하면 break하여 for문을 종료한다.

for i in range(20): # 0에서 19까지 순회
  print(i)
  if i > 10: #i가 10을 초과하면 종료한다.
    break

continue

if문을 곁들여 조건에 성립하면 건너뛰고 위에서 다시 시작한다.

for i in range(20): # 0에서 19까지 순회
  if i % 2 == 0: # 짝수인 숫자는 건너뛰고 다시 위에서 시작
    continue
  print(i)

중첩 반복문

이중 for문이라고도 불리는데, 2차원 리스트, 튜플 활용할 때 아주 중요하다.

for i in range(2,10):
    for j in range(1,10):
        print(i, j)
        break

반복문 내에서의 break는 근접한 반복문만 종료시킨다. 즉, 두 번째에서 1을 출력하고 종료하고 다시 위로 올라가 i는 i+1가 되고를 반복한다.

결과 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1

중첩 반복문을 한 번에 종료시키려면, 예외를 발생시키거나 함수 내에서 return문을 발생시켜야 한다.

def gugu():
    for i in range(2,10):
        for j in range(1,10):
            print(i, j)
            return None
gugu()

2 1 출력 후 종료

for문을 사용하게되면 range함수를 자주 접하게 된다. range함수는 문법적으로는 리스트가 아니라 Iterable(순회가능한) 객체이다.

while

while문도 for문처럼 반복을 수행한다.

while 조건:
    매 항목마다 수행할 코드 블록
i = 0
while i < 20:
    print(i)
    if i > 10:
        break
    i += 1

반복문은 무한 루프를 구성 시 용이하다. 반복문 조건을 항상 True로 하면 된다.

while True:
    if로 특정 조건을 충족하면 break로 종료하면 된다.

for문에서 무한루프를 원한다면, itertools.count 함수를 통해 호출한다.

from itertools import count

for i in count(1):
    print(i)
    if i > 60:
        break

i는 1부터 증가한다.

연습문제

2, 4, 6, 8단 구구단 출력하기

# range(start,stop,step) step에 2를 입력하여 2씩 넘어간다.
for i in range(2,9,2):
	for j in range(1,10): # 1~9 곱할 수
		print(i*j, end=' ')
    # i*j 곱한 수 출력
    # end 값을 스페이스 한칸을 주어 줄바꿈을 안하고 한 칸 띄어 출력한다.
	print() # 다음 단을 위해 한 번 줄바꿈 한다.

03 list, tuple, dictionary 정리

|

03 list, tuple, dictionary 정리

참고

애스크장고 AskDjango

여러 원소들을 가지고 있는 자료 구조

  • list, deque
  • set, fronzensets
  • dict, defaultdict, OrderedDict, Counter
  • tuple, namedtuple
  • **str

list생성

  • 생성문법: [], list(), list(iterable)
  • 여러 값을 순차적으로 저장, 순서를 보장
  • 리스트를 한 줄로 쓸 때에는 대개 끝에 쉼표를 쓰지 않음
  • 여러 줄로 나누어 쓸 때에는 항목 추가/삭제를 용이하게 하기 위해 끝에 쉼표를 쓴다.
numbers= [1,3,5,7,9]  
names = [  
  'Tom',  
  'Steve',  
  'Min',  
]  
  • 색인(index)지원: 0부터 시작하여 1씩 증가
    • numbers[0] 은 위의 numbers 리스트에서 맨 처음 항목(1)을 가르킨다.
  • 음수 색인 지원: -1은 맨 끝에서부터를 의미한다. -2는 끝에서 두 번째.
    • numbers[-1]는 numbers 리스트에서 9를 의미한다.
  • 다른 타입의 값들로도 구성 가능
    • a=[1,’1’,’2’,2] 이런식으로 가능 dict형, tuple형 들 여러 자료형을 넣을 수 있다.
    • 가급적 같은 타입으로 맞춰주는게 가독성 면에서 좋다.
list 메서드
  • numbers.append(값): numbers리스트 마지막에 값을 추가한다.
  • numbers.pop(공란 or 색인값): 공란인 경우 numbers 리스트의 마지막 값을 삭제하고, 색인값을 입력한 경우에는 해당 색인의 값을 삭제한다.
  • numbers.remove(값): numbers리스트에서 왼쪽부터 최조 발견된 값을 삭제한다. [1,2,3,2]일 때 remove(2)를 실행하면 맨 처음 2를 삭제한다.
  • numbers.insert(색인값,값): numbers리스트에서 색인값 위치에 값을 추가함. [1,2,3,2]일 때 insert(1,11) 1번 자리에 11값을 삽입함. -> [1,11,2,3,2]

슬라이스 하기

[시작인덱스:끝인덱스]를 통해 원하는 부분을 잘라 활용할 수 있다.

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

print(numbers[1:]) #1번째부터 끝까지 출력  
# [2,3,4,5,6,7,8,9,10] 출력  

print(numbers[1:7]) #1번째부터 6번째까지 출력. 7미만이라 이해하면 될듯
# [2,3,4,5,6,7]  

print(numbers[1:7:2]) #1번째부터 6번째까지 2씩 증가하여 출력.
#[2,4,6]  

print(numbers[::-1]) #반대로 출력, 은근 쓰이니 기억하기!
#[10,9,8,7,6,5,4,3,2,1]

리스트 합치기

numbers1 = [1,3,5,7]
numbers2 = [2,4,6,8]
print(numbers1+numbers2)
[1,3,5,7,2,4,6,8]

List Comprehension

numbers1 = [1,3,5,7]
numbers2 = [2,4,6,8]
print([i + j for (i, j) in zip(numbers1, numbers2)])
# [3,7,11,15]

zip함수는 동일한 개수로 이루어진 자료형을 묶어주는 역할을 한다.

list(zip([1,2,3],[4,5,6]))
[(1,4),(2,5),(3,6)]
#이런식으로 첫번째 값, 두번째 값끼리 묶어주는 역할을 한다.
# 개수가 안맞으면, 맞는데까지만 묶어준다.

tuple

생성방법: (), tuple(). tuple(iterable) list와 비슷하지만 tuple에 저장된 값은 변경할 수 없다. numbers= (1,3,5,7) 일 때, numbers[0]=10 시도해보면 에러가 발생한다.

소괄호()안에 어떻게 입력하냐에 따라 우선순위 연산자 혹은 튜플이 된다.

tuple1 = (1 + 3) # 우선순위
tuple2 = (1 + 3,)# 튜플
tuple3 = (3)# 우선순위
tuple4 = (3,)# 튜플

즉, 콤마(,)를 쓰냐 안쓰냐에 따라 정해진다.

set

중복을 허용하지 않는 데이터의 집합 list/tuple의 중복을 제거할 때 유용하다.

set_numbers={1,3,4,5,1,4,3,1} 중괄호{} 사용하여, 내용  중복이 있으면 제거
set_numbers
{1,3,4,5}

list_numbers = [1,1,2,1,1,2,2,3,1,2,3]
list_numbers = list(set(list_numbers)) set함수를 이용해 중복을 제거하고 다시 list함수를 사용하여 리스트화
list_numbers
[1,2,3]

합, 교, 차, 여집합 사용하기

set_numbers1 = {1,3,4,5,1,4,3,1}
set_numbers2 = {1,3,4,11,13,14,15,11,14,13,11}
print(set_numbers1 - set_numbers2) 차집합
print(set_numbers1 + set_numbers2) 합집합
print(set_numbers1 & set_numbers2) 교집합
print(set_numbers1 ^ set_numbers2) 여집합

사전형 (dict)

  • key와 value의 쌍으로 구성된 집합
  • key 중복을 허용하지 않음.
  • 중괄호 내에 콜론 (:)으로 key/value를 구분 dict_values = {‘blue’:10, ‘yellow’:3, ‘blue’:9, ‘red’:7}
  • in 연산자로 멤버쉽 체크 지원 (Key의 등록 여부)
  • 순회(for) 시에는 key 목록만 순회
  • 멤버함수
    • .keys(): key 목록
    • .values(): value 목록
    • .items(): (key,value) 목록

02 데이터 타입

|

02 변수 및 데이터 타입

참고

애스크장고 AskDjango

변수(Variables)

  1. 프로그램이 실행되면서 필요한 데이터를 임시로 저장하는 공간
  2. 효율성을 높이기 위해 적절한 크기/ 용도의 변수에 값을 담아서 처리
  3. 하나의 소프트웨어가 동작하면서, 로직에 따라 수많은 새로운 변수가 생겨나고 변경되며 제거

파이썬은 메모리상에 값이 존재하고, 변수가 참조하는 형태라고 하는데, 이 부분은 더 공부해서 정리해봐야겠다.
예시로는
a=3 b=3 id(a), id(b)를 출력해보면 동일한 주소값이 표시된다.

데이터 타입(Data Types)

  1. 변수는 하나의 데이터를 담아두는 그릇 같은 개념이다.
  2. 용도에 따라 그릇이 다르듯, 용도에 맞게끔 활용하여 효율성을 높여야 한다.
  3. 자원은 유한하다는 것도 알아두자.

숫자 (Numeric Type)

  1. 정수형: int
  2. 실수형: float

파이썬2에서는 int, long, float, double형이 존재했는데, 파이썬3로 넘어가면서 int/float로 통합되었다 한다. 명시를 중요하는 개발자 입장에서는 별로 좋아하지 않을거 같은데, 나는 파이썬으로만 공부해서인지, 현재까지는 이게 편한다.
수의 범위 제한이 없다는데, 잘못 쓰면 메모리를 남용할 수 있을거 같다.

참/거짓 (Boolean)

나중에 배울 제어문은 참/거짓을 통해서 프로그램의 동작을 다양하게 할 수 있다.

  1. 참 - True
  2. 거짓 - False

비교연산자를 활용하여 Boolean 값을 받아올 수 있다. 이것을 통해 향후 조건문이라던가 반복문에서 활용할 수 있다.

비교 연산자 종류

  • <, <=, >, >=, ==, !=
  • is, is not

논리 연산자

  • or, and, not

bool() 함수를 이용하여 참/거짓을 출력할 수 있다.

  • 0은 False, 이 외에는 True
    • bool(0) -> False bool(-1) -> True
  • 빈 문자열은 False, 이 외에는 True
    • bool('') -> False bool(' ') -> True 스페이스도 문자열이다!
  • 빈 list/tuple/set/dict는 False, 이 외에는 true
    • bool([]) -> False bool([' ']) -> True

문자열 (String)

홑(‘)따옴표나 쌍따옴표(“)로 감싸진 애들은 문자열이다. name1 = ‘Python’ name2 = “Python”

I’m seokju를 출력하기 위해서 ‘I’m seokju’로 입력하면 오류가 발생한다.
이럴 경우에는 백슬래쉬()를 활용한 이스케이프처리를 해주거나 쌍따옴표로 감싸주고 ‘를 쓰면 된다.

  • 이스케이프: ‘I\‘m seokju’
  • 쌍따옴표: “I’m seokju”

홑(쌍)따옴표를 3개로 감싸주면, 여러 줄 문자열을 지원한다.

test = '''
Hi
I'm
Seokju
'''

문자열 형식 지정자

문자열 내에 {}와 같은 형태로 슬롯을 만들고 format함수를 통해 슬롯에 필요한 데이터를 남길 수 있다. format함수에 함수인자로서 슬롯을 지정하는 방법은 위치(Positional), 키워드(Keyword) 방법이 있다.

위치 인자 (Positional Arguments)

# a, b, c 출력. format의 맨 처음 인자가 {0} 순으로 입력이 된다.
'{0}, {1}, {2}'.format('a','b','c')

#a, b, c 출력. 부여된 번호가 없어 순서대로 입력
'{}, {}, {}'.format('a','b','c')

 # c, b, a 출력. - format인자가 0번째부터 시작하기 때문이다.
'{2}, {1}, {0}'.format('a','b','c')

 # c, b, a 출력. 언패킹이라는 건데, 추후 설명
'{2}, {1}, {0}'.format(*'abc')

 # 에러 발생 - 숫자만큼 인자 개수 맞춰줘야 한다.
'{0}, {1}, {2}'.format('a','b')

키워드 인자 (Keyword Arguments)

'{lat}, {lng}'.format(lat='37.24N', lng='-115.81W')

#딕셔너리 언패킹을 통해 출력
coord ={'lat':'1234', 'lng':'4444'}
'{lat}, {lng}'.format(**coord)

01 print함수 정리

|

01 print 함수 정리

  • 가장 기본적인 출력 함수
  • Seperator, End 옵션 사용
  • Fromat 형식 출력
# 기본 출력 결과 같음
print('Hello python') #작은 따옴표
print("Hello python") #큰 따옴표

# 세개로 묶으면 여러줄을 출력할 수 있다.
print("""Hello
python""") # 새개로 묶기

print('''Hello
python''') # 세개로 묶기

seperator 옵션 사용

print(3, 4) 이런식으로 입력하면 결과로는

3 4

숫자 사이가 공백으로 나눠진다. print의 sep 키워드를 활용하면 공백 대신에 다른 문자를 삽입할 수 있다.

print(3, 4, sep=',')

3,4

이런식으로 활용할 수 있다.

print('test', 'gmail.com', sep='@')

test@gmail.com

end 옵션 사용

파이썬의 print()는 기본적으로 출력 후 다음줄로 이동된다. 기본적으로 끝에 \n 이 포함되기 때문이다. 이것은 end 옵션을 사용하여 변경할 수 있다.

end 옵션 사용 전
print(3) # 기본으로 \n(개행)이 있기에 줄바꿈이 이뤄진다.
print(4)

3 4

end 옵션 사용 후
print(3, end='') # end 값으로 원하는 값 삽입 가능
print(4, end='')

34

format 사용

유동적인 값을 출력하는 기능으로 format 함수가 있다.

print('{} and {}'.format('test', 'best'))
# 중괄호에 맞게끔 인자를 줘야한다.
# 순서에 맞게 표시가 된다.

test and best

번호를 추가하여 순서를 줄 수도 있다.

print('{0} and {1} and {0}'.format('a', 'b'))
# 0과 1 2개의 숫자만 있기에 format함수 안에는 2개의 인자만 넣어야 한다

a and b and a

숫자가 아닌 키값으로도 할 수 있다.

print("{a} are {b}".format(a='You', b = 'Me'))
# a에 You b는 Me 할당

You are Me

%s, %d, %f 포맷팅 사용

%s : 문자 %d : 정수 %f : 실수

print("%s's number: %d" % ('serven', 7))

seven’s number: 7

print("Test1: {0: 5d}, Price: {1: 4.2f}".format(776, 6543.123))
# 정수는 다섯자리로 표시, 실수는 소수점 둘째자리까지만 표시

Test1: 776, Price: 6543.12

print("Test1: {0: 05d}, Price: {1: 4.2f}".format(776, 6543.123))
# 5d앞에 0을 붙히면 남은자리는 0으로 채운다는 얘기이다

Test1:00776, Price: 6543.12