728x90
반응형

 

 

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 이라는 리스트에서 짝수만 뽑아낸 [2, 4, 6, 8, 10] 리스트를 만들려고 합니다. 어떻게 하면 될까요? 우선, for 구문을 이용해서 할 수 있겠지요?

list_orig = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list_result = []
for num in list_orig:
    if num % 2 == 0:
        list_result.append(num)
print(list_result)

 

이것을 filter 함수를 이용해서도 구현할 수 있는데요. 먼저 filter 함수는 어떤 형태로 사용하는지 봅시다.

filter(조건함수, 순회가능한객체)

조건함수는 걸러내기위한 조건을 담은 함수를 의미하고, 순회가능한객체는 리스트, 튜플 등이 해당된다.

일단 조건함수부터 구현해보자.

def is_even(num):
    return num % 2 == 0

이처럼 리턴값이 boolean 타입이어야 한다.

이제, 위의 조건함수과 함께 filter 함수를 사용해서 구현해보자.

list_orig = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list_result = filter(is_even, list_orig)
print(type(list_result))

그런데, filter 함수가 리턴하는 값은 filter 객체이므로, list 내장함수로 filter객체를 리스트로 변환해주어야 한다.

list_orig = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list_result = list(filter(is_even, list_orig))
print(list_result)

이렇게, 조작함수가 간단한 경우에는 lambda 함수로 작성하는 경우가 많다.

list_orig = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list_result = list(filter(lambda num : num % 2 == 0, list_orig))
print(list_result)

이렇게 하면, for구문을 이용해서 구현한 것보다 라인수가 많이 줄어든 것을 알 수 있다.

 

참고로, 이 것을 또 다른 방법으로... 리스트 내포(list comprehesion) 구문을 이용해서도 가능하다.

list_orig = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list_result = [num for num in list_orig if num % 2 == 0]
print(list_result)

 

lambda 함수와 리스트 내포에 대해서는 별도로 글을 남겼으니, 해당 글을 참고 바란다.

 

 

 

 

 

 

 

 

728x90
반응형
728x90
반응형

 

 

리스트를 [1, 2, 3, 4, 5] --> [10, 20, 30, 40, 50] 과 같이 변환하려면 어떻게 할까? 먼저, 생각나는 것은 for 문을 사용해볼 수 있을 것이다.

list_orig = [1, 2, 3, 4, 5]
list_result = []
for num in list_orig:
    list_result.append(num * 10)
print(list_result)

이것을 map 함수로도 구현할 수 있는데, map 함수의 형식을 먼저 살펴보자.

map(조작함수, 순회가능한객체)

조작함수 부분은 위의 for 구문에서 num * 10 의 기능을 해주는 함수이고, 순회가능한객체는 리스트, 튜플 등이 해당된다.

일단 조작함수부터 구현해보자.

def mul_ten(num):
    return num * 10

 

이제, 위의 조작함수과 함께 map 함수를 사용해서 구현해보자.

list_orig = [1, 2, 3, 4, 5]
list_result = map(mul_ten, list_orig)
print(type(list_result))

그런데, map 함수가 리턴하는 값은 map 객체이므로, list 내장함수로 map객체를 리스트로 변환해주어야 한다.

list_orig = [1, 2, 3, 4, 5]
list_result = list(map(mul_ten, list_orig))
print(list_result)

이렇게, 조작함수가 간단한 경우에는 lambda 함수로 작성하는 경우가 많다.

list_orig = [1, 2, 3, 4, 5]
list_result = list(map(lambda num: num*10, list_orig))
print(list_result)

이렇게 하면, for구문을 이용해서 구현한 것보다 라인수가 많이 줄어든 것을 알 수 있다.

 

참고로, 이 것을 또 다른 방법으로... 리스트 내포(list comprehesion) 구문을 이용해서도 가능하다.

list_orig = [1, 2, 3, 4, 5]
list_result = [num* 10 for num in list_orig]
print(list_result)

 

lambda 함수와 리스트 내포에 대해서는 별도로 글을 남겼으니, 해당 글을 참고 바란다.

 

그리고, map 함수를 사용할때, 2개 이상의 리스트를 조작해서 새로운 리스트를 만들때에도 사용할 수 있다.

[1, 2, 3] 와 [4, 5, 6] 을 이용해서 각 항목을 더해서 [5, 7, 9] 리스트를 만들어낼 수 있다.

list1 = [1, 2, 3]
list2 = [4, 5, 6]
list_result = list(map(lambda x, y: x + y, list1, list2))
print(list_result)

 

728x90
반응형
728x90
반응형

 

 

 

lamda 함수란, 한줄짜리 짧은 이름없는(익명) 함수

 

일반적인 함수의 사용예

def add(x, y):
    return x + y

print(add(10,20))

# 파이썬에서 함수는 객체이며, 변수에 저장이 될 수 있다.
add2 = add
print(add2(10,20))

 

lambda 함수 기본형태

lambda 인자: 리턴값

 

사용예

result = (lambda x, y: x + y)(10, 20)
print(result)

 

# 람다 함수를 변수에 넣는다.
add3 = lambda x, y: x + y
print(add3(10,20))

 

이런식으로 리스트에도 넣을 수 있다. 이것은 일반 함수도 가능한 일이다.

lambda_list = [lambda x: x+10, lambda x:x+100]
print(lambda_list[0](5))
print(lambda_list[1](5))

 

한가지 주의할 점: 인자에 타입 힌트를 사용할 수 없음

# 인자에 타입힌트 사용하면 에러 발생
add4 = lambda x: int, y: int : x + y
print(add4(10,20))

 

 

 

728x90
반응형
728x90
반응형

 

 

 

다들 알고 있는 것처럼, 파이썬은 동적 타입 언어이다. 이 것은 변수의 타입을 지정하지 않고, 모든 타입의 데이터를 넣을 수 있다는 말이다. 반면에 Java 와 같은 정적 타입 언어는 변수 선언시에 타입을 반드시 지정하고 해당 타입의 데이터만 넣을 수 있는데, 만약, 다른 타입의 데이터를 넣게 되면, IDE 등에서 에러표시를 해줄 것이며, 컴파일할 때에도 에러를 뿜어내고 컴파일 실패하게 된다.

public class Hello {
    public static void main(String[] args) {
        int num;
        // num = 10;
        num = "Hello Java";
        System.out.println(num);
    }
}

 

반면에, 파이썬은 다음처럼 아무런 문제가 없이 실행이 된다.

num = 1
print(type(num))
print(num);

num = "Hello Python"
print(type(num))
print(num);

 

어찌 보면, 파이썬의 이런 동적 타입 특성이 매우 편하게 다가옵니다. 일회성으로 빠르게 작성하거나, 소규모의 프로그램을 작성할 때에는 아주 큰 장점으로 작용하지만,  프로그램이 규모가 점점 커지면, 오히려 동적 타입이 에러를 유발하는 원인이 되어서 안정성에 위협적인 요소가 될 수 있다. 이런 이유때문에 정적 타입 언어를 선호하기도 한다. 예를 들어서 Javascript 도 Python 과 같은 동적타입언어인데, 이런 문제를 해결하고자 정적타입언어인 Typescript 를 만들어내기도 했다. 그러나, Typescript 는 완전한 정적타입언어여서 Javascript 의 가장 큰 장점인 유연함을 모두 빼앗아버렸다.

파이썬에서는 좀 더 멋진 방법을 제공하기 시작했는데, 바로 타입 힌팅이라는 것이다. 또는 타입 어노테이션 이라고도 한다. 파이썬 3.5 부터 지원하기 시작했다. 이것은 정적타입언어처럼 소스에 타입을 명시할 수 있도록 하였다. 

타입 힌트를 제공하여 여러가지 장점들이 생겼다. 일단 개발자가 보기에도 변수에 어떤 타입을 넣어야 할지를 알 수 있게 하였고, 코드편집기나 Linter 에서 해석을 할 수 있도록 하여서, 코드자동완성이나 타입체킹을 할 수 있게 되었다.

Visual Studio Code 의 설정에서 Type Checking Mode 를 켜준다.

num: int = 1
print(type(num))
print(num);

num = "Hello Python"
print(type(num))
print(num);

그러면, 위와 같이 num 에 int 형을 명시해주면, "Hello Python" 에 빨간 밑줄이 생겨서 타입에 문제가 있다고 표시해줄 것이다.

함수를 정의할 때에도 역시 인자와 리턴값에 타입을 명시해줄 수 있다.

name = "Tom"

def hello(msg):
    print(msg)

def hello2(msg: str) -> None:
    print(msg)

hello(name)
hello2(name)

 

여기에서 중요점이 한가지 있는데, 파이썬의 타입힌트강제사항이 아니라는 점입이다. 타입힌트는 사용해도 되고, 사용하지 않아도 상관이 없습니다. 그리고, 타입힌트를 사용한 경우에 다른 타입이 들어가더라도 파이썬 인터프리터는 아무런 문제 없이 실행까지 됩니다.

 

이제부터 파이썬에 타입힌트를 추가하는 법을 좀 더 구체적으로 알아봅시다. 우선, 변수에 타입힌트를 추가해보겠다.

member_no = 31

nick = "홍길동"

phones = ["010-1234-5678", "010-9876-4321"]

address = {
    "nation": "대한민국",
    "city": "서울",
    "gu": "강남구",
    "zipcode": "12345"
}

위의 코드는 아래와 같이 변경해볼 수 있다.

from typing import List, Dict

member_no: int = 31

nick: str = "홍길동"

phones: list[str] = ["010-1234-5678", "010-9876-4321"] # Python 3.9 이상
phones: List[str] = ["010-1234-5678", "010-9876-4321"] # Python 3.8 이하

# Python 3.9 이상
address: dict[str, str] = {
    "nation": "대한민국",
    "city": "서울",
    "gu": "강남구",
    "zipcode": "12345"
}

# Python 3.8 이하
address: Dict[str, str] = {
    "nation": "대한민국",
    "city": "서울",
    "gu": "강남구",
    "zipcode": "12345"
}

 

이번에는 함수에도 타입힌트를 적용해봅시다.

def print_name(name):
    ret_val = "당신의 이름은 " + name + 입니다.
    print(ret_val)
    return ret_val


def print2(str_val):
    print("좋은 세상이군! " + str_val + " 잘 살아보자")


def multiply(n1, n2=3.5):
    return n1 * n2


def make_list(msg, times=3):
    return [msg] * times

위의 코드는 아래와 같이 변경해 볼 수 있겠다.

def print_name(name: str) -> str:
    ret_val: str = "당신의 이름은 " + name + 입니다.
    print(ret_val)
    return ret_val


def print2(str_val: str) -> None:
    print("좋은 세상이군! " + str_val + " 잘 살아보자")


def multiply(n1: int, n2: float = 3.5) -> float:
    return n1 * n2


def make_list(msg: str, times: int = 3) -> list[str]:
    return [msg] * times

 

사용자 정의 타입의 클래스에도 타입힌트를 사용할 수 있다.

class Car:
    pass


def make_car(id: int) -> Car:
    return Car()


def fix_car(user: Car) -> Car:
    return Car()

 

여기까지 파이썬의 타입힌트에 대해서 알아보았다. 파이썬에서 타입힌트를 제공함으로써 코드 편집기에서 타입에 문제가 생기면 표시를 해주어서 타입 관련된 버그를 미리 찾아서 없앨 수 있어서 프로그램 유지보수에 아주 좋다. 그러면서도 강제적이지 않아서, 편하게 사용할 수 있다. 다른 동적타입언어서도 이런 타입힌트를 적용해주면 좋겠다. 예를 들어, Javascript 에도 꼭 적용이 되면 좋겠다. 앞으로 모든 파이썬 프로젝트에는 타입힌트를 꼭 적용해서 개발해야겠다.

 

 

 

728x90
반응형

+ Recent posts