Date : 2023-07-11
Topic : Lambda 표현식, closure, 파일 입출력
Note
람다 표현식(Lambda Expression)
: lambda에 매개변수를 지정 후 :(콜론) 뒤에 반환값(return value)으로 사용할 식을 지정
lambda 매개변수들: 식
- 람다 표현식으로 만들면 함수 객체가 나오는데, 이 상태로는 함수 호출X
- 람다 표현식은 이름이 없는 함수를 만들기 때문임. (익명 함수라고도 함. Anonymous function)
# 함수 정의
def plus_ten(x):
return x+10
plus_ten(1)
- lambda로 만든 익명 함수를 호출하려면 다음과 같이 람다 표현식을 변수에 할당
# 위 함수를 람다 표현식으로
plus_ten=lambda x: x+10
plus_ten(1)
- 람다 표현식은 변수에 할당하지 않고 람다 표현식 자체를 바로 호출할 수 있음.
- 람다 표현식을 ()(괄호)로 묶은 뒤, 다시 ()를 붙이고 인수를 넣어서 호출
(lambda 매개변수들: 식)(인수들)
(lambda x: x + 10)(1) # 11
- 람다 표현식 안에서는 변수를 만들 수 없다.
- 변수 없이 식 한 줄로 표현할 수 있어야 함.
- 변수가 필요한 코드일 경우 def로 함수를 작성하는 것이 좋음.
(lambda x:y=10; x+y)(1)
>>> syntaxerror: invalid syntax
- 람다 표현식 바깥에 있는 변수는 사용할 수 있음.
- 매개변수 x와 람다 표현식 바깥에 있는 y를 더해서 반환.
y=10
(lambda x: x+y)(1) # 11
- 람다 표현식을 인수로 사용하기
# 1.이렇게 정의된 함수 plus_ten을
def plus_ten(x):
return x+10
list(map(plus_ten, [1,2,3])) # [11,12,13]
# 2.plus_ten 대신 람다 표현식을 직접 대입
list(map(lambda x:x+10, [1,2,3])) # [11,12,13]
- 람다 표현식에 조건부 표현식 사용하기
- if, else 사용 시 :(콜론) 사용X
- elif 사용X - 조건식을 연속으로 사용해줘야 함
lambda 매개변수들: 식1 if 조건식 else 식2
True면 if 조건식 실행, 아닐 경우 else 식2 실행
lambda 매개변수들: 식1 if 조건식1 else 식2 if 조건식2 else 식3
elif 대신 조건식을 연속으로 ( ↑ elif와 같은 기능 )
- 그러나 어렵지 않은 코드를 lambda로 표현하여 복잡하고 가독성이 떨어진다면 def 함수 권장
map, filter, reduce
- map에 여러 객체 넣기 : 람다 표현식에 매개변수에 개수에 맞게 반복 가능한 객체도 콤마로 구분해서 넣어주면 됨.
a=[1,2,3,4,5,6,7,8,9,10]
list(map(lambda x: str(x) if x % 3 == 0 else x, a)) # 3의 배수를 문자열로 출력, 아니면 그대로x
# [1,2,'3',4,5,'6',7,8,'9',10]
a=[1,2,3,4,5] # 2.반복 가능한 객체도 콤마로 구분해서 넣어줌
b=[2,4,6,8,10]
list(map(lambda x,y: x*y,a,b)) # 1.표현식의 매개변수 개수(x,y 2개)에 맞게
# [2, 8, 18, 32, 50]
- filter 사용하기 : 반복 가능 객체에서 특정 조건에 맞는 요소만 가져오는데, filter에 지정한 함수의 반환값이 True일 때만 해당 요소를 가져옴
filter(함수, 반복 가능한 객체)
# 1.함수 f를
def f(x):
return x>5 and x<10 # 5보다 크고 10보다 작은 x
a=[8,3,2,10,15,7,1,9,0,11]
list(filter(f,a)) # [8,7,9] # 참인 요소만 출력
# 2.람다 표현식으로 만들어서 filter에 넣기
list(filter(lambda x: x>5 and x<10, a)) # [8,7,9]
- reduce : 반복 가능한 객체의 각 요소를 지정된 함수로 처리한 뒤 이전 결과와 누적해서 반환하는 함수
reduce(함수, 반복 가능한 객체)
def f(x, y):
return x + y
a = [1, 2, 3, 4, 5]
from functools import reduce
reduce(f, a) # 15
# 저장된 요소를 순서대로 더한 뒤 누적된 결과를 반환
a=[1,2,3,4,5]
from functools import reduce # 내장함수X, functools에서 reduce를 불러와야 함
reduce(lambda x,y: x+y, a) # 지정된 함수 x+y를 a의 요소로 누적

※ 그러나 reduce는 코드가 조금만 복잡해져도 가독성이 안좋아지기 때문에, 반복문으로 처리할 수 있는 경우라면 for, while문으로 처리하는 것이 좋다. ↓
#의미하는 바를 한 눈에 알아볼 수 있다.
a = [1, 2, 3, 4, 5]
x = a[0]
for i in range(len(a) - 1): # len(a)=5이므로 range(4)
x = x + a[i + 1] # a[0] + (a[1]+a[2]+a[3]+a[4])
x # 15
클로저 (closure) 사용하기
- 변수 사용 범위
- 전역 변수(global variable): 함수 포함하여 스크립트 전체에서 접근할 수 있는 변수
- 전역 범위(global scope): 전역 변수에 접근할 수 있는 범위
x=10 # 전역 변수
def foo():
print(x) # 전역 변수 출력 ## 10
foo()
print(x) # 전역 변수 출력 ## 10
- 지역 변수(local variable): 변수를 만든 함수 안에서만 접근 가능(함수 바깥에서 접근X)
- 지역 범위(local scope): 지역 변수를 접근할 수 있는 범위
def foo():
x=10 # foo의 지역 변수
print(x) # foo의 지역 변수 출력
foo()
print(x) # 에러. foo의 지역 변수 출력 불가
x=10 # 전역 변수
def foo():
x=20 # x는 foo의 지역 변수
print(x) # foo의 지역 변수 출력
foo()
print(x) # 전역 변수 출력
'''op
20
10
'''
# 이때 지역 변수x와 전역 변수x는 서로 다른 x
- global 키워드 : 함수 안에서 전역 변수의 값을 변경하려면 global 전역변수 사용.
- 함수 안에서 변수를 global로 지정하면 전역 변수를 사용
- 전역 변수가 없을 때, 함수 안에서 global을 사용하면 해당 변수는 전역 변수
x=10 # 전역 변수
def foo():
global x # 전역 변수x를 사용하겠다고 설정
x=20 # x는 전역 변수
print(x) # 전역 변수 출력
foo()
print(x) # 전역 변수 출력
'''op
20
20
'''
# 전역변수x가 없는 상태
def foo():
global x # x를 전역 변수로 만듦
x=20 # x는 전역 변수
print(x) # 전역 변수 출력
foo()
print(x) # 전역 변수 출력
- 함수 안에서 함수 만들기
def 함수이름1():
코드
def 함수이름2():
코드
# 동작 순서chk
# print_hello > print_message 순으로 실행
def print_hello(): #2
hello='Hello, world!' #3
def print_message(): #5
print(hello) #6
print_message() #4
print_hello() #1(함수 호출), 7
- 지역 변수 변경하기
# 안쪽 함수B에서 바깥쪽 함수A의 지역 변수x를 변경해보기
def A():
x=10 # A의 지역 변수x
def B():
x=20 # x에 20 할당(B의 지역 변수x)
B()
print(x) # A의 지역 변수x 출력
A() # 10
- 현재 함수 바깥쪽에 있는 지역 변수의 값을 변경하려면 nonlocal 키워드 사용
- nonlocal 지역변수
- nonlocal: 현재 함수의 지역 변수가 아니라는 뜻(바깥쪽 함수의 지역 함수 사용)
- 현재 함수의 바깥쪽에 있는 지역 변수를 찾을 때 가장 가까운 함수부터 먼저 찾는다.
def A():
x=10 # A의 지역 변수x
def B():
nonlocal x # 현재 함수 바깥쪽에 있는 지역 변수 사용
x=20 # A의 지역 변수 x에 20 할당
B()
print(x) # A의 지역 변수x 출력
A() # 20
# 실행 순서 이해하고 주석 달기
def A():
x=10
y=100
def B():
x=20
def C():
nonlocal x # 가장 가까운 함수의 변수 x 사용 (x=20)
nonlocal y # 가장 가까운 함수의 변수 y 사용 (y=100)
x=x+30
y=y+300
print(x)
print(y)
C()
B()
A()
# 50 ## print(x)
# 400 ## print(y)
- global로 전역 변수 사용하기 : 함수가 몇 단계든 상관 없이 global 키워드를 사용하면 무조건 전역 변수를 사용하게 됨
- 파이썬에서 global을 제공하지만 함수에서 값을 주고받을 때는 매개변수와 반환값을 사용하는 것이 좋다. 특히 전역 변수는 코드가 복잡해졌을 때 변수의 값을 어디서 바꾸는지 알기가 힘드므로 전역 변수는 가급적이면 사용하지 않는 것을 권장
x = 1
def A():
x = 10
def B():
x = 20
def C():
global x # 전역 변수 x = 1을 사용
x = x + 30
print(x)
C()
B()
A() # 31
- 클로저(closure) 사용하기 : 함수를 둘러싼 환경(지역 변수, 코드 등)을 계속 유지하다가, 함수를 호출할 때 다시 꺼내서 사용하는 함수
- 프로그램의 흐름을 변수에 저장할 수 있음
- 지역 변수와 코드를 묶어서 사용하고 싶을 때 활용
- 클로저에 속한 지역 변수는 바깥에서 직접 접근할 수 없으므로 데이터를 숨기고 싶을 때 활용
- 함수를 반환할 때는 함수 이름만 반환해야 하며 ()(괄호)를 붙이면 안됨 (↓return mul_add)
- 프로그램의 흐름을 변수에 저장할 수 있음
# 함수 바깥쪽 지역 변수 a,b를 사용하여 a*x+b를 계산하는 함수 mul_add를 만든 뒤
# 함수 mul_add 자체를 반환함
def calc():
a=3
b=5
def mul_add(x):
return a*x+b # 함수 바깥쪽 지역 변수 a,b를 사용하여 계산
return mul_add # mul_add 함수를 반환
c=calc() # calc() 함수 호출 후 반환값을 c에 저장
print(c(1),c(2),c(3),c(4),c(5)) # 8 11 14 17 20

- lambda로 클로저 만들기 ( 함께 사용하는 경우 多 )
def calc():
a=3
b=5
return lambda x: a*x+b # mul_add 함수를 람다 표현식으로 변경 후 그 자체를 반환
c=calc()
print(c(1),c(2),c(3),c(4),c(5))
파일의 입출력 과정
표준입력장치(키보드 등) input() → print() 표준출력장치(모니터)
이 둘을 합쳐서 콘솔(Console)
- read() / readline() / readlines()는 파일 내용을 읽음
- write() / writelines()는 파일 내용을 쓰기
파일 입출력 기본 과정
- file open
- open() 함수에서 파일명을 지정하고 읽기인지, 쓰기인지 지정
- open() 함수의 마지막 매개변수를 모드(Mode)라고 함
- 읽기용: 변수명=open("파일명", "r")
- 쓰기용: 변수명=open("파일명", "w")
- file read & write
- file close
# 파일 경로 찾아서 열기
#inFp=open("C:\Users\bb2_b\data1.txt", "r", encoding="utf-8")
inFp=open("data1.txt", "r", encoding="utf-8")
inStr=inFp.readline()
print(inStr, end="")
inStr=inFp.readline()
print(inStr, end="")
inStr=inFp.readline()
print(inStr, end="")
inStr=inFp.readline()
print(inStr, end="")
inFp.close()
'''op: 저장된 txt파일 내용이 입력됨
박우정
파이썬
python
'''
inFp=None
inStr=""
inFp=open("data1.txt", "r", encoding="utf-8")
while True: # 무한 루프를 통해 텍스트가 몇 줄인지 몰라도 사용 가능
inStr=inFp.readline() # 한 줄 읽고 다시 루프
if inStr=="": # 더 이상 읽을 내용이 없으면(EOF) break
break
print(inStr, end="")
inFp.close()
inFp=None
inList=[]
inFp=open("data1.txt", "r", encoding="utf-8")
inList=inFp.readlines()
print(inList)
inFp.close()
# ['박우정\n', '파이썬\n', 'python']
< 실습 >
- 파일명으로 파일 읽기
inFp=None
inList=[]
inStr=""
strName=input("file name: ") # 확장자까지 입력! data1.txt
inFp=open(strName, "r", encoding="utf-8")
inList=inFp.readlines()
for inStr in inList:
print(inStr, end="")
inFp.close()
'''op:
file name: data1.txt
박우정
파이썬
python
'''
- 파일에 출력해보기
outFp=None
outStr=""
outFp=open("data1.txt", "w", encoding="utf-8")
while True:
outStr=input("내용 입력: ")
if outStr != "": # 공백이 아닌 내용이 입력되면 써짐
outFp.write(outStr+'\n')
else: # 공백+'\n' 시 종료
break
outFp.close()
print("--- 정상적으로 파일에 써졌음 ---") # data1.txt 파일을 열어보면 입력한 내용이 출력됨
Tkinter 라이브러리
: GUI 프로그램을 만들기 위해 -
- 메인 창(Tk 객체) 생성
- 위젯 생성하고 창에 배치
- 메인 루프 실행
- Tkinter 라이브러리 맛보기 - 코랩 안되고 내 GUI를 사용하는 프로그램 사용해야함!! (ex:주피터 노트북)
import tkinter as tk
root=tk.Tk()
lbl=tk.Label(root, text="Educoding", underline=3)
lbl.pack()
txt=tk.Entry(root)
txt.pack()
btn=tk.Button(root, text="OK", activebackground="red", width=5)
btn.pack()
root.mainloop()

- 버튼 만들기
# coding: uft-8
# Tkinter 라이브러리 임포트
import tkinter as tk
# tk 객체 인스턴스 생성
root=tk.Tk()
def func():
print('Pushed')
txt=tk.Entry(root)
txt.pack()
# 버튼 생성
btn=tk.Button(root, text="Push!", command=func)
# 버튼 배치
btn.pack()
print("실행 준비") # 코드를 실행하면 출력창에 "실행 준비"가 프린트 되고
# 루트 표시
root.mainloop() # 'Push!' 버튼을 누르면 'Pushed'가 출력된다.
print("실행 종료") # 창을 닫으면 실행 종료가 뜬다.
'''op:
실행 준비 # 코드 실행
Pushed # 버튼을 다섯 번 눌렀다.
Pushed
Pushed
Pushed
Pushed
실행 완료 # 창 닫음
'''

- if 조건문으로 버튼을 스위치처럼 사용하기 ( 클릭할 때마다 표시된 메시지가 반복해서 달라진다.)
# coding: uft-8
# Tkinter 라이브러리 임포트
import tkinter as tk
# tk 객체 인스턴스 생성
root=tk.Tk()
bAct=False
print(type(bAct)) # boolean인지 타입 체크
# 버튼 눌렀을 때 처리
def func():
global bAct
# Label 표시 변경
if bAct: # 조건문 설정으로 switch 역할
label.config(text='Apple')
else:
label.config(text='Orange')
bAct=not(bAct)
# 레이블 생성
label=tk.Label(root, text="Apple")
# 레이블 배치
label.pack()
# 버튼 생성
btn=tk.Button(root, text="Push!", command=func) # command
# 버튼 배치
btn.pack()
print("실행 준비")
# 루트 표시
root.mainloop()
print("실행 완료")


- 버튼을 누른 다음 특정 동작을 하면 표시가 돌아오도록 프로그램을 변경
# coding: uft-8
# Tkinter 라이브러리 임포트
import tkinter as tk
# tk 객체 인스턴스 생성
root=tk.Tk()
# 버튼을 눌렀을 때 처리
def func():
# Label 표시 변경
label.config(text="Pushed")
# 마우스 커서가 버튼을 벗어났을 때 이벤트 추가
def func_event(ev):
# Label 표시 변경
label.config(text="Pushed")
# 레이블 생성
label=tk.Label(root, text="Push Button")
# 레이블 배치
label.pack()
# 버튼 생성
btn=tk.Button(root, text="Push!", command=func) #command
# 버튼 배치
btn.pack()
# 마우스 커서가 버튼을 벗어났을 때 이벤트 추가
btn.bind('<Leave>', func_event)
print("실행 준비")
# 루트 표시
root.mainloop()
print("실행 완료")
- 버튼 만들기 - event object
import tkinter as tk
root=tk.Tk()
def func():
label.config(text='Pushed')
def func_event_click(ev):
disp=str(ev.x)+'/'+str(ev.y)
label.config(text=disp)
label=tk.Label(root, text="Push Button")
label.pack()
button=tk.Button(root, text='Push', command=func)
button.pack()
button.bind('<Button-1>', func_event_click)
root.mainloop()
- 라디오 버튼 만들기
# radio button
import tkinter as tk
def Action1():
lbl.config(text='Option 1')
def Action2():
lbl.config(text='Option 2')
root=tk.Tk()
lbl=tk.Label(root, text="EduCoding", underline=3)
lbl.pack()
rbvar=""
rb1=tk.Radiobutton(root, text='Option 1', variable=rbvar, value='a', indicatoron=0, command=Action1)
rb1.pack()
rb2=tk.Radiobutton(root, text='Option 2', variable=rbvar, value='b', indicatoron=0, command=Action2)
rb2.pack()
# indicatoron이 0이면 버튼 형태, 1이면 단추 형태 (형식은 라디오버튼이다)
root.mainloop()'데이터 분석 학습일지🐣' 카테고리의 다른 글
| 27일차(1) - SQL 기초 문법 (SELECT, WHERE, LIMIT, DISTINCT) (0) | 2023.07.27 |
|---|---|
| 18일차 - 파이썬 시각화 실습(Numpy, Pandas, Matplotlib, Seaborn) (0) | 2023.07.14 |
| 15일차 - 리스트 튜플 응용, 서식 formatting, 함수 (0) | 2023.07.11 |
| 14일차 - 반복문 (for, while), 디버깅 (0) | 2023.07.11 |
| 12일차 - 시퀀스 자료형 - 리스트, 튜플, 딕셔너리 (2), if 조건문 (0) | 2023.07.07 |