Загружаем каталог…
Загружаем каталог…
Python_Day.4 변수의 범위, 람다, 내장 함수( map , filter ), 파일 입출력, 그리고 클래스의 첫걸음. 함수를 "값처럼" 다루기 시작한 날이다. 학습 네 번째 날이다. 오늘 배운 내용은 이렇다. 전역 변수와 지역 변수 람다( lambda ) 와 함수를 변수에 담기 input() 과 split() 내장 함수 : all , any , chr , dir , divmod , enumerate , eval , filter , map 파일 입출력 클래스 : 객체, 인스턴스, __init__ , self 1. 전역 변수와 지역 변수 JS에서 배운 전역 변수와 지역 변수의 개념은 Python에서도 그대로 적용된다. a = 1 def vartest(a): a = a + 1 vartest(a) print(a) # 1 vartest 안의 a 는 그 함수 안에서만 쓰이는 지역 변수 라서, 함수 밖의 a 값에는 영향을 주지 않는다. 그래서 출력은 2가 아니라 1이다. def vartest(a): a = a + 1 vartest(3) print(a) # NameError: name 'a' is not defined 이런 코드도 문제가 된다. 함수 밖 어디에도 a 라는 변수가 정의되어 있지 않아서 오류가 난다. 정상적으로 출력되게 고치면 이렇다. def vartest(a): a = a + 1 return a a = vartest(3) print(a) # 4 함수 안의 결과를 밖에서 쓰려면 return 으로 돌려주고, 밖에서 변수에 받아야 한다. return 이 없으면 함수를 호출해도 결과값이 없어서 a = vartest(3) 의 a 는 None 이 된다. 2. 람다와 함수를 변수에 담기 lambda # 함수명 = lambda 매개변수: 실행문 abc = lambda a, b: a * b sub = lambda x, b: x - b print(abc(3, 5)) # 15 print(sub(9, 4)) # 5 lambda 는 이름 없이 한 줄로 만드는 간단한 함수 다. 같은 함수를 def 로 쓰면 이렇다. def multi(x, y): return x * y multi2 = lambda x, y: x * y print(multi2(5, 2)) # 10 def plus(x): return x + 10 plus2 = lambda x: x + 10 print(plus2(11)) # 21 식 하나로 값을 돌려주는 단순한 함수는 lambda 로 간결하게 쓸 수 있다. return 을 따로 쓰지 않고, 콜론 뒤의 식이 곧 반환값 이다. JS의 화살표 함수( (x, y) => x * y )와 비슷한 역할이다. 필기에는 람다를 쓰는 이유로 "메모리 절약", "즉시 실행 함수라 정의하자마자 실행됨"이라고 적었는데, 정확하지 않다. 람다는 정의한다고 바로 실행되지 않고 , 함수를 만들 뿐이다. 이유는 가독성과 간결함 정도로 보는 것이 맞고, 바로 실행하려면 (lambda x: x + 1)(3) 처럼 괄호로 감싸서 호출해야 한다. 함수를 변수에 담기 def multi(x, y): return x * y print(multi(4, 5)) # 20 a = multi # 함수 이름을 a에 할당 (a는 별칭이 된다) print(a(4, 5)) # 20 (multi에 넣은 것과 같은 결과) print(type(a)) # <class 'function'> a = multi 처럼 괄호 없이 함수 이름만 대입하면 a 가 그 함수를 가리키게 된다. JS에서 head.onclick = on; 처럼 함수를 값으로 다루던 것과 같다. 함수는 다른 함수의 매개변수로도 넘길 수 있다. (Day.8의 콜백, 고차 함수 와 같은 개념이다.) def final(x, y, func1): print(x, y, func1(5, 6)) # 넘겨받은 함수에 5, 6을 넣어서 호출 final(3, 5, a) # 3 5 30 final 의 세 번째 인자로 multi ( a )를 넘겼고, 안에서 func1(5, 6) 이 multi(5, 6) 으로 실행되어 30이 나온다. 3. input()과 split() input() 으로 받은 값은 기본적으로 모두 문자열 이다. name = input('이름은?') score = input('학점은?') age = input('나이는?') print(name, score, age) print(type(name), type(score), type(age)) # 전부 <class 'str'> 숫자로 쓰려면 변환한다. num1 = int(input('첫번째 정수')) # 문자열 → 정수 num2 = int(input('두번째 정수')) print(num1 + num2) float1 = float(input('실수를 입력')) print(float1, type(float1)) # 정수 3을 입력하면 3.0으로 출력된다 split() 한 줄에 여러 값을 입력받아 나누고 싶을 때 split() 을 쓴다. a, b = input('숫자입력').split() # 입력: 3 4 → ['3', '4'] a, b = int(a), int(b) # 각각 정수로 변환 print(a + b, type(a + b)) # 7 <class 'int'> split() 은 문자열을 기준 문자로 잘라서 리스트로 만드는 함수다. 괄호 안에 아무것도 넣지 않으면 공백(띄어쓰기, 엔터) 을 기준으로 자른다. a = input('숫자입력').split() # 입력: 1 2 3 4 5 6 7 8 # a = ['1', '2', '3', '4', '5', '6', '7', '8'] 공백이 아닌 다른 문자로 입력하면 어떻게 될까. a = input('숫자입력').split() # 입력: 1,2,apple,home,66,go print(a, type(a)) # ['1,2,apple,home,66,go'] <class 'list'> 공백이 없어서 자를 곳이 없으니 통째로 하나 인 리스트가 된다. 쉼표로 자르려면 split(',') 처럼 기준 문자를 써 줘야 한다. print('1,2,apple'.split(',')) # ['1', '2', 'apple'] 문자열의 split 함수는 split(sep, maxsplit) 두 파라미터를 가진다. 파라미터 기본값 의미 sep None 구분자. None 이면 공백(띄어쓰기, 엔터)으로 자른다 maxsplit -1 최대 몇 번 자를지. -1 이면 제한 없이 끝까지 자른다 'a,b,c'.split(',', 1) # ['a', 'b,c'] (1번만 자름) 'a b c'.split(maxsplit=1) # ['a', 'b c'] # 'a b'.split(1) # 에러: 첫 번째 자리는 sep이라 문자열이어야 한다 sep 은 생략하고 split(',') 처럼 써도 되고, maxsplit 만 쓰려면 이름을 붙여서( maxsplit=1 ) 써야 한다. (참고: blockdmask 블로그의 split 정리) 실습: 딕셔너리에 이름과 응답 저장하기 문제: 빈 딕셔너리를 만들고, 무한 루프로 이름과 TV를 좋아하는지 입력받아 딕셔너리에 추가한다. "친구한테도 물어볼까?"에 no 가 입력되면 루프를 종료하고, 마지막에 items() 로 전부 출력한다. empty = dict() while True: name = input('이름을 말해봐') like_tv = input('TV보는 것은 좋아해?') empty[name] = like_tv # 이름을 키로, 대답을 값으로 저장 then = input('친구한테도 물어볼까?') if then == 'no': break print(empty.items()) 필기에서는 empty['name'], empty['like'] = name, like_tv 로 썼는데, 이러면 키가 'name' 과 'like' 두 개로 고정 되어서 반복할 때마다 값이 덮어씌워진다. empty[name] = like_tv 처럼 입력받은 이름을 키로 쓰면 사람마다 하나씩 차곡차곡 쌓인다. 4. 리스트 만드는 여러 방법 1~5를 담은 리스트를 세 가지 방식으로 만들 수 있다. # 리스트 컴프리헨션 nums = [i for i in range(1, 6)] print(nums) # [1, 2, 3, 4, 5] # list()로 형 변환 li2 = list(range(1, 6)) print(li2) # [1, 2, 3, 4, 5] # 빈 리스트에 for문으로 추가 re = [] # re = list() for i in li2: re.append(i) print(re) # [1, 2, 3, 4, 5] append 로 하나씩 쌓는 방식은 range(1, 6) 을 바로 list() 로 감싸면 되는 일이지만, append 를 연습하기 위한 흐름이었다. 5. 내장 함수 미리 만들어져 있는 내장 함수들도 배웠다. 함수 설명 abs(x) 절댓값 all(모음) 요소가 모두 참 이면 True , 하나라도 거짓이면 False . 빈 값이면 True any(모음) 요소 중 하나라도 참 이면 True , 모두 거짓이면 False . 빈 값이면 False chr(i) 유니코드 숫자 값을 받아 그에 해당하는 문자를 반환 dir(모음) 객체가 가진 내장 함수( .append , .count 등)를 보여 줌 divmod(a, b) a를 b로 나눈 몫과 나머지를 튜플 로 반환 enumerate(모음) 순서(인덱스)와 값을 함께 꺼냄 eval(문자열) 문자열로 된 표현식을 실행한 결과를 반환 filter(함수, 모음) 함수의 반환값이 참인 요소만 걸러냄 map(함수, 모음) 모든 요소에 함수를 적용 print(all([1, 2, 0]), all([])) # False True print(any([0, 0]), any([])) # False False print(chr(97)) # a print(divmod(7, 3)) # (2, 1) enumerate for i, name in enumerate(['body', 'foo', 'bar']): print(i, name) # 0 body # 1 foo # 2 bar for 문과 함께 쓰면 현재 요소의 순서와 값 을 한 번에 알 수 있다. 값뿐 아니라 인덱스도 필요할 때 편하다. eval print(eval('1+2')) # 3 print(eval("'hi'+'a'")) # hia print(eval('divmod(4,3)')) # (1, 1) eval 은 문자열 안의 식을 코드로 실행 해서 결과를 돌려준다. 숫자 식뿐 아니라 문자열 연산이나 함수 호출도 된다. 바깥 따옴표를 벗겨낸 식을 계산하는 것이다. JS의 eval 과 같은 역할이고, 사용자가 입력한 문자열을 그대로 넣으면 의도하지 않은 코드가 실행될 수 있으므로 조심해서 써야 한다. filter def positive(x): return x > 0 print(list(filter(positive, [1, 2, -3, -4, -5, 6]))) # [1, 2, 6] # 람다로 바꾸면 result = list(filter(lambda x: x > 0, [1, 2, -3, -4, -5, 6])) print(result) # [1, 2, 6] filter(함수, 모음) 은 첫 번째 인자로 함수 , 두 번째로 반복 가능한 데이터 를 받는다. 데이터의 요소를 하나씩 함수에 넣어서 반환값이 참인 것만 남긴다. 그래서 함수는 조건식 이어야 한다. for 와 if 를 합친 기능이다. JS Day.9에서 배운 filter 와 같은 역할이다. map def two_times(numberList): result = [] for number in numberList: result.append(number * 2) return result print(two_times([1, 2, 3, 4])) # [2, 4, 6, 8] def two_timess(x): return x * 2 print(list(map(two_timess, [1, 2, 3, 4]))) # [2, 4, 6, 8] print(list(map(lambda x: x * 2, [1, 2, 3, 4]))) # [2, 4, 6, 8] map(함수, 모음) 은 요소를 하나씩 함수에 넣어서 그 결과로 바꾼다. filter 가 조건 (참/거짓)으로 거르는 것이라면, map 은 연산 을 적용해서 값을 바꾸는 것이다. for 로 append 하던 것을 한 줄로 줄여 준다. def pp(x): return x + 20 print(pp(4)) # 24 print(list(map(pp, [1, 2, 3]))) # [21, 22, 23] print(list(map(lambda x: x + 20, [1, 2, 3]))) # [21, 22, 23] re2 = list(map(lambda i: i, [5, 4, 3, 2, 1])) print(re2) # [5, 4, 3, 2, 1] list1 = [1, 2, 3, 4, 5] re3 = list(map(lambda x: x + 10, list1)) print(re3) # [11, 12, 13, 14, 15] map, filter, 리스트 컴프리헨션 비교 같은 일을 세 가지로 쓸 수 있다. list1 = [1, 2, 3, 4, 5] def square(x): return x ** 2 print(list(map(square, list1))) # [1, 4, 9, 16, 25] print(list(map(lambda x: x ** 2, list1))) # 람다로 변경 print([i ** 2 for i in list1]) # 리스트 컴프리헨션으로 변경 # 3보다 작은 값만 (filter) print(list(filter(lambda x: x < 3, range(1, 6)))) # [1, 2] # 1~20 중 2의 배수만 print([x for x in range(2, 21, 2)]) # 증감값 이용 print([x for x in range(1, 21) if x % 2 == 0]) # if 조건 이용 print(list(filter(lambda x: x % 2 == 0, range(1, 21)))) # filter 이용 하는 일 map / filter 리스트 컴프리헨션 모든 요소를 변환 list(map(lambda x: x*2, a)) [x*2 for x in a] 조건에 맞는 요소만 list(filter(lambda x: x>0, a)) [x for x in a if x>0] map 과 filter 는 문법 구조가 같아서 하나를 익히면 나머지도 쉽다. 컴프리헨션은 같은 일을 더 짧게 쓸 수 있다. map 과 filter 는 결과를 리스트가 아니라 map 객체로 돌려준다. 그래서 list() 로 감싸야 값이 보인다. JS의 map , filter 가 곧바로 배열을 돌려주던 것과 다르다. 이 객체는 값이 필요해질 때 계산하는 방식이라, 아무도 값을 꺼내지 않으면 함수가 실행되지도 않는다. list(map(lambda x: print(x + 100, end=' '), range(1, 11))) # 101 102 103 ... 110 (list()로 감싸서 값을 꺼내야 실행됨) list() 없이 map(...) 만 쓰면 아무것도 출력되지 않는다. 다만 출력만 하려는 목적이라면 for 문이 더 읽기 쉽다. 6. 파일 입출력 열기 모드 모드 의미 r 읽기 (read) w 쓰기 (write). 파일이 없으면 생성하고, 있으면 내용을 지우고 새로 쓴다 a 추가 (append). 기존 내용 뒤에 이어 쓴다 f = open('파일명', '파일열기모드') 로 파일을 연다. 경로와 인코딩 절대경로 : 처음부터 끝까지 전부 쓴 경로( C:\Python\test.py ) 상대경로 : 현재 파일을 기준으로 쓰는 경로( ./ , ../ , ../../ ) 인코딩 : 문자를 숫자(바이트)로 바꾸는 것. 디코딩 은 숫자를 다시 문자로 바꾸는 것 UTF-8 : 가장 많이 쓰는 국제 표준 인코딩(유니코드) 한글과 영어는 파일에 저장될 때 숫자로 바뀌어 저장되므로, 저장할 때의 규칙과 읽을 때의 규칙이 같아야 한다. 그래서 open 을 할 때 encoding='UTF-8' 을 꾸준히 써 주는 것이 좋다. 읽기 f = open('./resource/news.txt', 'r', encoding='UTF-8') print(f.encoding) # 인코딩 확인 print(f.name) # 파일명 확인 print(f.mode) # 열기 모드 확인 result = f.read() # 파일 전체 읽기 print(result) f.close() # 파일을 열었으면 반드시 닫기 파일 객체는 for 문으로 줄 단위 로 읽을 수도 있다. f = open('./resource/news.txt', 'r', encoding='UTF-8') for a in f: print(a) # 한 줄씩 f.close() 각 줄 끝에는 줄바꿈( \n )이 붙어 있어서, print 가 또 줄바꿈을 하면 줄 사이에 빈 줄 이 생긴다. print(a.strip()) 나 print(a, end='') 로 없앨 수 있다. with: 알아서 닫아 주는 방식 with open('./resource/news.txt', 'r', encoding='UTF-8') as f: c = f.read() # f의 내용 전체를 문자열로 반환 print(type(c)) # <class 'str'> print(list(c)) # 글자 하나하나를 리스트로 with 를 쓰면 블록이 끝날 때 파일이 자동으로 닫힌다. 그래서 f.close() 를 따로 쓰지 않아도 된다. # read(n): n글자만 읽기 with open('./resource/news.txt', 'r', encoding='UTF-8') as f: c = f.read(30) # 30글자만 읽어서 c에 저장 print(c) # readline(): 한 줄 읽기 with open('./resource/news.txt', 'r', encoding='UTF-8') as f: line = f.readline() # 첫 줄 print(line) line = f.readline() # 한 번 더 쓰면 다음 줄 print(line) # readlines(): 모든 줄을 리스트로 with open('./resource/news.txt', 'r', encoding='UTF-8') as f: lines = f.readlines() print(lines) for i in lines: i = i.strip() # 양끝의 공백과 개행문자(\n)를 제거 print(i) 방법 읽는 범위 read() 전체를 문자열 하나로 ( read(n) 은 n글자) readline() 한 줄. 호출할 때마다 다음 줄 readlines() 모든 줄을 리스트로 for a in f 한 줄씩 readline() 을 두 번 쓰면 첫 줄, 둘째 줄이 차례로 나오는 것은 파일에서 읽던 위치가 이어지기 때문이다. 쓰기 # 'story.txt' 파일을 생성하여 쓴다 with open('./resource/story.txt', 'w', encoding='utf-8') as f: f.write('hi 파이썬\n') # 문자열 쓰기(저장) # 이어서 추가 with open('./resource/story.txt', 'a', encoding='utf-8') as f: f.write('이어서 한 줄 더\n') # 여러 줄: writelines with open('./resource/list.txt', 'w', encoding='utf-8') as f: li = ['React\n', 'DB\n', 'Python\n'] # f.write(li) # 에러: write는 문자열만 받는다 f.writelines(li) # 리스트는 writelines를 이용 write() 는 문자열 하나 만 쓸 수 있어서 리스트를 넣으면 에러가 난다. 리스트는 writelines() 를 쓴다. writelines 는 줄바꿈을 자동으로 넣어 주지 않으므로 각 문자열 끝에 \n 을 직접 붙여야 한다. 또 'w' 로 같은 파일을 다시 열면 이전 내용이 사라지므로, 이어 쓸 때는 'a' 를 쓴다. 연습 문제 # Q3. 프로그램 오류 수정하기 input1 = int(input('첫 번째 숫자를 입력하세요')) input2 = int(input('두 번째 숫자를 입력하세요')) total = input1 + input2 print(f'두 수의 합은 {total}입니다') input 의 결과는 문자열이라서, int() 로 감싸야 숫자로 더해진다. 감
То, что RADAR обнаружил и классифицировал для этой возможности. Это опубликованный источником текст, а не подтверждение, что предложение ещё действует.
Python_Day.4. Python_Day.4 변수의 범위, 람다, 내장 함수( map , filter ), 파일 입출력, 그리고 클래스의 첫걸음. 함수를 "값처럼" 다루기 시작한 날이다. 학습 네 번째 날이다. 오늘 배운 내용은 이렇다. 전역 변수와 지역 변수 람다( lambda ) 와 함수를 변수에 담기 input() 과 split() 내장 함수 : all , any , chr , dir , divmod , enumerate , eval , filter , map 파일 입출력 클래스 : 객체, 인스턴스, __init__ , self 1. 전역 변수와 지역 변수 JS에서 배운 전역 변수와 지역 변수의 개념은 Python에서도 그대로 적용된다. a = 1 def vartest(a): a = a + 1…
Открыть источник