Python의 람다(Lambda)

파이썬의 람다 기능은 익명 함수(Anonymous), 즉 이름이 없는 함수를 정의하기 위한 용도로 사용됩니다. 참고로 컴퓨터 분야에서 정의는 없던 것에 대한 구체적인 생성을 의미하며, 선언은 일단 이름만 붙여두고 구체적인 생성은 다른 곳에서 대신하는 것을 의미합니다.

일반적으로 파이썬에서 함수는 다음처럼 정의됩니다.

def func(a):
    return a+1

위와 동일한 람다 방식의 함수 정의는 다음과 같죠. 위의 동일성을 유지하기 위해 람다 함수를 func에 할당하여 이름을 붙인 경우입니다. 호출은 일반함수과 동일합니다.

func = lambda a: a+1

다른 예로, 인자를 두개 받아 받은 인자값을 합해 반환하는 람다 함수는 다음과 같습니다.

func = lambda a,b: a+b

이 람다 함수의 사용은 생각해 보면, map처럼 함수를 인자로 받는 함수에서와 같습니다.

r = list(map(lambda a,b: a+b, [1,2,3], [10,20,30]))
print(r) # [11, 22, 33]

덧붙여 람다 함수를 이용하여 함수를 반환하는 함수를 정의할 수 있습니다. 클로저(Closure)라고도 하죠.

def makeFunc(n):
    return lambda a : a % n == 1

isOdd = makeFunc(2)

print(isOdd(11))

물론 클로저 함수를 정의하기 위해 람다를 사용할 필요는 없습니다. 아래처럼요.

def makeFunc(n):
    def func(a):
        return a % n == 1
    return func

단, 위의 코드는 함수의 이름(func)을 불필요하게 부여했다는 점이 거슬립니다.

람다를 통한 함수의 정의는 제약이 많습니다. 람다 함수는 반드시 반환값에 대한 단 한줄의 코드로만 구성되어야 한다는 점입니다. 그렇다면 람다함수에서 어떤 논리적인 조건처리는 어떻게 구현할 수 있을까요? 거기에 대한 힌트는 아래의 코드를 통해 살펴볼 수 있습니다.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
r = list(
        map(
            lambda x: 
                'BIG' if x > 5 
                else 'SMALL' if x < 5 
                else 'MIDDLE',
            a
        )
    )
print(r) # ['SMALL', 'SMALL', 'SMALL', 'SMALL', 'MIDDLE', 'BIG', 'BIG', 'BIG', 'BIG', 'BIG']

이해를 돕고자 들여쓰기를 했는데, 리스트 요소 중 5보다 작으면 SMALL, 5보다 크면 BIG, 딱 5이면 MIDDLE 문자열로 구성된 또 다른 리스트를 반환하는 것입니다.

실제 코딩에서는 들여쓰기가 제거된 아래의 형태가 되겠네요.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
r = list(map(lambda x: 'BIG' if x > 5 else 'SMALL' if x < 5 else 'MIDDLE', a))
print(r)

웹에서 JavaScript만으로 데이터 압축하여 파일로 저장하기

몇 일전에 웹에서 자바스크립트만으로 압축 파일의 압축을 해제하는 내용을 정리했습니다. 해당 글은 아래와 같습니다.

Javascript 기반의 압축 라이브러리, jszip

이제는 다시 웹에서 사용자가 만든 어떤 데이터를 하나의 압축 파일로 만들 필요가 있어, 앞서 살펴본 압축 라이브러리를 이용해 바이너리 데이터와 텍스트 데이터를 각각 file.bin과 file.txt라는 파일명으로 하여 하나의 a.zip 파일로 압축한 후 사용자의 PC에 다운로드 하는 코드를 정리합니다.

먼저 압축하고자 하는 바이너리 데이터를 아래의 코드처럼 준비합니다.

let buffer = new ArrayBuffer(8);
let dataview = new DataView(buffer);

dataview.setInt32(0, 9438);
dataview.setFloat32(4, 3224.3224);

위의 데이터는 file.bin이라는 파일명으로 압축파일에 존재하도록 아래처럼 코드를 추가합니다.

let zip = new JSZip();
zip.file("file.bin", buffer);

앞서 언급했듯, 바이너리 뿐만 아니라 텍스트 파일도 압축 파일에 추가해 봅니다. 아래처럼요.

zip.file("file.txt", 'Hello한글Hi!');

이제 이렇게 압축된 내용을 a.zip 파일로 저장하는 코드는 다음과 같습니다.

let zipFileName = 'a.zip';
zip.generateAsync({ type: "blob" }).then(
    function (blob) {
        if (isIE()) {
            saveToFile_IE(zipFileName, blob);
        } else {
            saveToFile_Chrome(zipFileName, blob);
        }
    }
);

못보던 isIE와 saveToFile_IE, saveToFile_Chrome 함수가 보입니다. 이 놈들은 아래의 글을 참고하시면 파악할 수 있답니다.

웹에서 Javascript 만으로 텍스트 파일 생성