ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 파이썬: 람다 표현식
    Python/이것저것 파이썬 2023. 10. 7. 07:12
    반응형

    1씩 증가하는 카운터

    import tkinter
    
    counter = 0
    
    
    def add():
        global counter
        counter += 1
        label.config(text=str(counter))
    
    
    root = tkinter.Tk()
    
    label = tkinter.Label(root, text=str(counter))
    label.pack()
    
    button = tkinter.Button(root, text='증가', width=15, command=add)
    button.pack()
    
    root.mainloop()

     

    여기에 5씩 증가하는 버튼을 추가한다면?

    import tkinter
    
    counter = 0
    
    
    def add1():
        global counter
        counter += 1
        label.config(text=str(counter))
    
    
    def add5():
        global counter
        counter += 5
        label.config(text=str(counter))
    
    
    root = tkinter.Tk()
    
    label = tkinter.Label(root, text=str(counter))
    label.pack()
    
    button1 = tkinter.Button(root, text='1 증가', width=15, command=add1)
    button1.pack()
    
    button5 = tkinter.Button(root, text='5 증가', width=15, command=add5)
    button5.pack()
    
    root.mainloop()

     

    코드의 중복이 보인다. 

    add1 함수와 add5를 합칠 수 있다. 
    인수를 이용하면 1, 5 뿐만 아니라 모든 수를 받을 수 있는 유연한 코드가 된다. 
    중복을 줄이고, 유연하기까지 하니 좋은 코드

    def add(number):
        global counter
        counter += number
        label.config(text=str(counter))

     

    그런데 이렇게 좋은 코드를 쓸 수 없다니~!

    Button의 command 인수에는 함수 이름만 전달할 수 있다. 
    함수이름 뒤에  '()'를 붙이면 실행이 되어 버린다.

    그러므로 다음 코드의 command에는 add(1)의 리턴 값인 None만 들어가기 때문에... 
    의도대로 작동하지 않는다.  

    import tkinter
    
    counter = 0
    
    
    def add(number):
        global counter
        counter += number
        label.config(text=str(counter))
    
    
    root = tkinter.Tk()
    
    label = tkinter.Label(root, text=str(counter))
    label.pack()
    
    button1 = tkinter.Button(root, text='1 증가', width=15, command=add(1))  # 
    button1.pack()
    
    button5 = tkinter.Button(root, text='5 증가', width=15, command=add(5))  # 
    button5.pack()
    
    root.mainloop()

     

    람다표현식

    어떻게 하면 개선된 add함수를 사용할 수 있을까?
    이때 필요한 것이 람다표현식이다.

    람다표현식으로 add함수를 감싸고
    람다식의 인수에 1 또는 5를 넣어서 add함수에 전달하면
    이것은 정의일 뿐 실행되지 않기 때문에 
    사용할 수 있다. 

    람다에 대해 잘 모르신다면 다음 링크를 참고
    https://wikidocs.net/24#lambda   
    https://dojang.io/mod/page/view.php?id=2359 

    import tkinter
    
    counter = 0
    
    
    def add(number):
        global counter
        counter += number
        label.config(text=str(counter))
    
    
    root = tkinter.Tk()
    
    label = tkinter.Label(root, text=str(counter))
    label.pack()
    
    button1 = tkinter.Button(root, text='1 증가', width=15, command=lambda x=1: add(x))
    button1.pack()
    
    button5 = tkinter.Button(root, text='5 증가', width=15, command=lambda x=5: add(x))
    button5.pack()
    
    root.mainloop()

     

     

    만약 람다가 없었다면?

    혹 때려다 혹 붙인 격이 된다. 

    import tkinter
    
    counter = 0
    
    
    def add(number):
        global counter
        counter += number
        label.config(text=str(counter))
    
    
    def add1():
        add(1)
    
    
    def add5():
        add(5)
    
    
    root = tkinter.Tk()
    
    label = tkinter.Label(root, text=str(counter))
    label.pack()
    
    button1 = tkinter.Button(root, text='+ 1', width=15, command=add1)
    button1.pack()
    
    button5 = tkinter.Button(root, text='+ 5', width=15, command=add5)
    button5.pack()
    
    root.mainloop()

     

    클래스

    전역변수가 눈에 거슬린다면 클래스에 담아주자...

    import tkinter
    
    
    class MainFrame:
        def __init__(self, root):
            self.counter = 0
            self.label = tkinter.Label(root, text=str(self.counter))
            self.label.pack()
            self.button1 = tkinter.Button(root, text='1 증가', width=15, command=lambda x=1: self.add(x))
            self.button1.pack()
            self.button5 = tkinter.Button(root, text='5 증가', width=15, command=lambda x=5: self.add(x))
            self.button5.pack()
    
        def add(self, number: int):
            self.counter += number
            self.label.config(text=str(self.counter))  # str이 없어도 작동하지만...
    
    
    def main():
        root = tkinter.Tk()
        MainFrame(root)
        root.mainloop()
    
    
    if __name__ == '__main__':
        main()

    반응형
Designed by Tistory.