혼공파 : 함수 #2 (고급편)

채록·2021년 1월 8일
0

짜투리

목록 보기
9/26

들어가는말

헤이해졌다. 정신차려!

TIL #26과 이어진다.

파이썬은 함수를 좀 더 편리하게 사용할 수 있게 다양한 기능들을 제공해 준다.

튜플(tuple) 과 람다(lambda)

튜플 : 함수와 함께 많이 사용되는 리스트와 비슷한 자료형으로 리스트와 다른 점은 한번 결정된 요소는 바꿀 수 없다는 것이다.

람다 : 매개변수로 함수를 전달하기 위해 함수 구문을 작성하는 것이 번거롭고, 코드 공간 낭비라는 생각이 들때 함수를 간단하고 쉽게 선언하는 방법


튜플(tuple)

형식

(데이터, 데이터, 데이터)

실습 예제1

tuple_test = (10, 20, 30)

tuple_test[0]
-> 10
tuple_test[1]
-> 20
tuple_test[2]
-> 30

실습 예제2 (에러 발생 상황)

tuple_test = (10, 20, 30)

tuple_test[0]=1
->
Traceback (most recent call last):
    File "<tuple>, line 3, in <module>
        tuple_test[0] = 1
TypeError: 'tuple' object does not support item assignment

튜플의 활용성

리스트와 튜플

[a, b] = [10, 20]
(c, d) = (10, 20)

print('a:', a)
print('b:', b)
print('c:', c)
print('d:', d)
->
a: 10
b: 20
c: 30
d: 40

괄호가 없는 튜플

tuple_text = 10, 20
print('tuple_test :', tuple_test)
print('type(tuple_test) :', type(tuple_test))
->
tuple_test : (10, 20)
type(tuple_test) : <class 'tuple>

괄호가 없는 튜플 활용

a, b = 10, 20
print('a :', a)
print('b :', b)
->
a : 10
b : 20

변수의 값을 교환하는 튜플

a, b = 10, 20
print('a:', a)
print('b:', b)
->
a: 10
b: 20

# 교환 후
a, b = b, a
print('a:', a)
print('b:', b)
->
a: 20
b: 10

편리하게 사용할 수 있는 값 교환 방법이다!!


튜플 주의!

요소를 하나만 가질 경우

# 리스트는 다음과 같은 형태로 생성한다.
[273]

# 튜플은 다음과 같은 형태로 생성해야 한다.
(273, ) # 이와 같이 쉼표를 넣어서 선언해야 한다.

튜플과 함수

튜플은 함수의 리턴에 많이 사용된다. (여러 개의 값을 리턴하고 할당할 수 있기 때문!!!)

# 함수 선언
def test():
    return (10, 20)

# 여러 개의 값을 리턴받기
a, b = test()

 # 출력하기
 print('a:', a)
 print('b:', b)
 ->
 a: 10
 b: 20

위와 같이 괄호 없이 여러 값을 할당하는 것은 튜플만 가능하다!!



람다(lambda)

함수라는 기능을 매개변수로 전달하는 코드를 좀 더 효율적으로 작성할 수 있도록 파이썬이 제공하는 기능

함수의 매개변수로 함수 전달하기

# 매개변수로 받은 함수를 10번 호출하는 함수
def call+10(func):
    for i in range(10):
        func()
        
# 간단한 출력하는 함수
def print_hello():
    print('안녕하세요')

# 조합하기
call_10(print_hello) # 매개벼수로 함수를 전달한다.

->
안녕하세요
(* 10)

filter()함수와 map()함수

함수를 매개변수로 전달하는 대표적인 표준 함수

filter()

리스트의 요소를 함수에 넣고 리턴된 값이 True인 것으로, 새로운 릿트를 구성해 주는 함수

filter(함수, 리스트)

map()

리스트의 요소를 함수에 넣고 리턴된 값으로 새로운 리스트를 구성해주는 함수

map(함수, 리스트)
# 함수 선언하기
def power(item):
    return item * item
def under_3(item):
    return item < 3
    
# 변수 선언
list_input_a = p1, 2, 3, 4, 5]

# map()함수 사용
output_a = map(power, list_input_a) # 함수를 매개변수로 넣었다.
print('# map()함수의 실행 결과')
print('map(power, list_input_a):', output_a)
print('map(power, list_input_a):', list(output_a))

# filter() 함수 사용
output_b = filter(under_3, list_input_a) # 함수를 매개변수로 넣었다.
print('# filter()함수의 실행 결과')
print('filter(under_3, list_input_a):', output_b)
print('filter(under_3, list_input_a):', list(output_b))

->
# map() 함수의 실행 결과
map(power, list_input_a): <map object at 0x03862270>
map(power, list_input_a): [1, 4, 9, 16, 25]

# filter() 함수의 실행 결과
filter(under_3, list_input_a): <filter object at 0x03862290>
filter(under_3, list_input_a): [1, 2]

제너레이터 (generator)

map object
filter object

***내용 추가하기***


람다의 개념

" 간단한 함수를 쉽게 선언하는 방법 "

lambda 매개변수: 리턴값
# 함수 선언하기
power = lambda x: x * x
under_3 = lambda x: x < 3

# 변수 선언하기
list_input_a = [1, 2, 3, 4, 5]

# map()함수 사용
output_a = map(power, list_input_a) # 함수를 매개변수로 넣었다.
print('# map()함수의 실행 결과')
print('map(power, list_input_a):', output_a)
print('map(power, list_input_a):', list(output_a))

# filter() 함수 사용
output_b = filter(under_3, list_input_a) # 함수를 매개변수로 넣었다.
print('# filter()함수의 실행 결과')
print('filter(under_3, list_input_a):', output_b)
print('filter(under_3, list_input_a):', list(output_b))

->
# map() 함수의 실행 결과
map(power, list_input_a): <map object at 0x03862270>
map(power, list_input_a): [1, 4, 9, 16, 25]

# filter() 함수의 실행 결과
filter(under_3, list_input_a): <filter object at 0x03862290>
filter(under_3, list_input_a): [1, 2]

사용법이 조금 복잡해 보인다.. 다음과 같이 함수의 매개변수에 바로 넣을 수 도 있다!!!!!!!

# 변수 선언하기
list_input_a = [1, 2, 3, 4, 5]

# map()함수 사용
output_a = map(lambda x x * x, list_input_a) # power() 함수를 선언하지도 않고, 매개변수로 바로 넣었다!
print('# map()함수의 실행 결과')
print('map(power, list_input_a):', output_a)
print('map(power, list_input_a):', list(output_a))

# filter() 함수 사용
output_b = filter(lambda x; x < 3, list_input_a) # under_3() 함수를 선언하지도 않고, 매개변수로 바로 넣었다!
print('# filter()함수의 실행 결과')
print('filter(under_3, list_input_a):', output_b)
print('filter(under_3, list_input_a):', list(output_b))

매개변수가 여러개인 람다

lambda x, y: x * y



파일 처리

파일과 관련된 처리를 하는 함수는 표준 함수가 기본으로 제공된다. 파일은 크기 1. 텍스트 파일2. 바이너리 파일로 나뉜다.


텍스트 파일

파일을 처리하려면,,,

파일 열기 -> 파일 읽기 / 파일 쓰기


파일 열고 닫기 open() / close()

파일을 열땐 open() 함수를 사용한다.

파일 객체 = open(문자열: 파일 경로, 문자열: 읽기 보드)

open()함수의 첫번째 매개변수 = 파일 경로(path) 입력
open()함수의 두번째 매개변수 = 모드(mode) 지정

모드에서 지정 가능한 것

w : write 모드 (새로 쓰기 모드)
a : append 모드 (뒤에 이어서 쓰기 모드)
r : read 모드 (읽기 모드)

파일을 닫을 땐 close() 함수를 사용한다.

파일 객체.close()
# 파일 열기
file = open('basic.txt', 'w')

# 파일에 텍스트 쓰기
file.write('Hello Python Programming...!')

# 파일 닫기
file.close()

이렇게 파일을 종료하면 프로그램과 같은 폴더에 basic.txt 라는 파일이 생성된다. 이 파일을 메모장과 같은 것으로 열어보면 "Hello Python Proramming...!" 라는 문구를 확인할 수 있다.

open()함수로 열어주었으면 close()함수로 닫아주어야 한다!


with 키워드

조건문과 반복문이 들어가다 보면 파일을 열고 닫지 않는 실수를 할 수도 있다. 이런 실수를 방지하기 위해 with 키워드라는 기능이 존재한다.

with open(문자열: 파일 경로, 문자열: 모드) as 파일 객체:
    문장

바로 위의 코드들을 with 키워드를 활용해 바꿔보면,,

# 파일 열기
with open('basic.txt', 'w') as file:
    # 파일에 텍스트를 쓴다.
        	file.write('Hello Python Programming...!')

이런식으로 코드가 작성되면 with 구문이 종료될 때 자동으로 파일이 닫힌다.


텍스트 읽기 : reat()

파일 객체.read()

파일을 열고 파일 객체의 read() 함수를 호출하기만 하면 내부에 잇는 데이터를 모두 읽어 출력한다.

# 파일 열기
with open('basic.txt', 'r') as file: # 읽기 모드!
    # 파일을 읽고 출력한다.
    contentx = file.read()
print(contents)
->
Hello Python Programming...!

텍스트 한 줄씩 읽기

CSV
XML
JSON
...

CSV

Comma Separated Values : 쉼표로 구분된 값들

이름,, 몸무게
윤인성, 176, 62
연하진, 169, 50
  • CSV 파일은 한 줄에 하나의 데이터를 나타낸다.
  • 각각의 줄은 쉼표를 사용해 데이터를 구분한다
  • 첫 번째 줄에 헤더(header)를 넣어 각 데이터가 무엇을 나타내는지 설명해줄 수 있다.
# 랜덤한 숫자를 만들기 위해 가져오기
import random
# 간단한 한글 리스트 만들기
hanguls = list('가나다라마바사아자차카타파하')
# 파일을 쓰기 모드로 연다.
with open('info.txt','w) as file:
    for i in range(1000):
        # 랜덤한 값으로 변수를 생성한다
        name = random.choice(hanguls) + random.choice(hanguls)
        weight = random.rndrange(40, 100)
        height = random.randrange(140, 200)
        # 텍스트를 쓴다.
        file.write('{}, {}, {}\n'.format(name, weight, height))
        
->
다자, 98, 171
나차, 60, 171
타카, 56, 153
마아, 71, 144
타카, 95, 160
가마, 52, 163
...생략....
#info.txt에 생성된 데이터이다.

데이터가 많아졌을 때...
for 반복문을 사용한다!

for 한 줄을 나타내는 문자열 in 파일 객체:
    처리

실습 예제 : 비만도 계산하기

with open(info.txt', 'r')as file:
    for line in file:
        # 변수 선언하기
        (name, weight, height) = line.strip().split(", ")
        
        # 데이터가 문제없는지 확인한다 : 문제가 있으면 지나감
        if (not name) or (not weight) or (not height):
            continue
        # 결과를 계산한다.
        bmi = int(weight) / ((int(height) / 100) **2)
        result = ""
        if 25 <= bmi:
            result = "과체중"
        elif 18.5 <= bmi:
            result = "정상 체중"
            
        else:
            result = "저체중"
            
        # 출력하기
        print('\n\.join([
            "이름: {}",
            "몸무게: {}",
            "키: {}",
            "BMI: {}",
            "결과: {}"
        ]).format(name, weight,height, bmi, result))
        print()

->
이름: 나자
몸무게: 82: 193
BMI: 22.014013799028163
결과: 정상체중

이름: 차카
몸무게: 90: 153
BMI: 38.446751249519416
결과: 과체중

이름: 카다
ㅗㅁ무게: 61: 175
BMI: 19.981367346938776
결과: 정상 체중
... 생략 ...




보충 내용

writelines()

이 함수에 대해 알고싶어 구글링을 하면

# Open a file in write mode
fo= open('foo.txt', 'rw+')

# write sequence of lines at the end of the file.
seq = ["This is 6th line\n", "This is 7th line"]
line = fo.writelines(seq)

# Now read complete file from beginning.
fo.seek(0,0)
for index in range(7):
    line = fo.next()
    print "Line No %d - %s" % (index, line)

위 같은 예시를 찾아 볼 수 있다.
대충 리스트를 매개변수로 넣어서 사용한다 정도로 파악된다.

기능을 파악하기 위해 예제를 만들어보면

with open('test.txt', 'w') as file:
    # writeline() 기본 사용
    file.witelines(["안녕하세요.", \
        "줄바꿈이 될까요,\
        "안 될까요?",\
        "띄어쓰기라도 하지 않을까요?"]
    # writeline() 매개변수의 리스트는 여러 자료형을 가질 수 있을까?
    file.writelines([True, 273, "문자열"])
    
->
traceback (most recent all last):
   File "test.y, line 8, in <module>
     file.riteline([True, 273, "문자열"])
TypeError: write() argument must be str, not bool

위 에러 사항을 통해 writeline()함수는 내부적으로 write()함수를 사용하는 것으로 파악된다!!!!
비록 에러가 났지만 첫 번째 writelines()함수는 정상적으로 실행 되었으니 test.txt 파일을 열어보면

안녕하세요.줄바꿈이 될까요안 될까요?띄어쓰기라도 하지 않을까요?

를 확인 할 수 있다.


제너레이터 (generator)

  • 파이썬의 특수한 문법구조이다
  • 이터레이터를 직접 만들때 사용하는 코드이다.
  • 함수 내부에 yield 키워드를 사용하면 해ㅏㅇ 함수는 제너레이터 함수가 되며, 일반 함수와는 달리 함수를 호출해도 함수 내부의 코드가 실행되지 않는다.
# 함수 선언
def test():
    print('함수가 호출되었다')
    yield "test"
    
# 함수 호출
print("A 지점 통과")
test()

print("B 지점 통과")
test()
print(test())

->
A 지점 통과
B 지점 통과
<generator object test at 0x02F20C90>

원래... test()함수를 호출하면 "함수가 호출되었습니다."라는 문자열이 출력되어야 하지만.. 출력되지 않았다!!11
-> 함수의 리턴값으로 <generator object test at 0x02F20C90> 등이 출력된다. 즉,, 제너레이터 함수는 제너레이터를 리턴한다. 출력된 <generator object test at 0x02F20C90>는 제너레이터 객체이다.

제너레이터 객체

제너레이터 객체는 next() 함수를 사용해 함수 내부의 코드를 실행한다.

  • 이 때 yield 키워드 부분까지만 실행하며, next() 함수의 리턴값으로 yield 키워드 뒤에 입력한 값이 출력된다.!!
# 함수 선언
def test():
    print("A 지점 통과")
    yield 1
    print("B 지점 통과")
    yield 2
    print("C 지점 통과")
# 함수 호출
output = test()
# next() 함수 호출
print("D 지점 통과")
a = next(output)
print(a)
print("E 지점 통과")
b = next(output)
print(b)
print("F 지점 통과")
c = next(output)
print(c)
# 한번 더 실행하기
next(output)

->
D 지점 통과
A 지점 통과
1
E 지점 통과
B 지점 통과
2
F 지점 통과
C 지점 통과
Traceback (most recent call last):
  file "generator01.py", liine 22, in <module>
    c = next(output)
Stopiteration

next() 함수를 호출한 이후 yield 키워드를 만나지 못하고 함수가 끝나면 StopIteration이라는 예외가 발생한다!

  • 제너레이터 객체는 함수의 코드를 조금씩 실행할 때 사용한다. (메모리의 효율성을 위해!)
  • 제너레이터 객체와 이터레이터 객체는 완전히 같지는 않지만, 기본적인 단계에서는 거의 비슷하다고~ 볼수있다!




마무리

야,,, 어렵다 졸립구 어려워.

profile
🍎 🍊 🍋 🍏 🍇

0개의 댓글