본문 바로가기
Study/CODE 3기 [Jump to python]

[2조:ACE] Python 스터디 #3

by 박무준 2024. 3. 19.

ace_3주차.py
0.00MB

2조 - 강수환 고정윤 문하진 박무준 최정우 최혜윤

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

파이썬 스터디 3주차
진도: 04-1 함수 ~ 04-4 프로그램의 입출력

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

I. 04-1 함수

작성자 최혜윤, 고정윤

함수란?

- 입력값을 가지고 어떤 일을 수행한 후 그 결과물을 내어 놓는 것.

프로그래밍에서 함수를 사용하는 이유: 반복되는 내용을 한 번에 작성하기 위해서, 프로그램의 흐름을 일목요연하게 보기 위해서(오류 위치 확인 등) 

파이썬 함수의 구조 - def는 함수를 만들 때 사용하는 예약어. return도 자주 사용함.

def 함수_이름(매개변수):
    수행할_문장1
    수행할_문장2
    ...

매개변수와 인수

매개변수 : 함수에 입력으로 전달된 값을 받는 변수 / 인수: 함수를 호출할 때 전달하는 입력값

[일반적인 함수]

def 함수_이름(매개변수):
    수행할_문장
    ...
    return 리턴값

[입력값이 없는 함수]

>>> def say():
        return 'Hi'

[리턴값이 없는 함수]

함수_이름(입력_인수1, 입력_인수2, ...)

[입력값도, 리턴값도 없는 함수]

함수_이름()

 

매개변수를 지정하여 호출하기

2개의 숫자를 입력받은 후 첫 번째 수에서 두 번째 수를 뺄셈하여 리턴하는 sub 함수. 매개변수 지정하여 사용. 순서 상관없음.

>>> def sub(a, b):
        return a - b
>>> result = sub(a=7, b=3)
>>> print(result)
4
>>> result = sub(b=5, a=3)
>>> print(result)
-2

여러 개의 입력값을 받는 함수 만들기

매개변수 이름 앞에 *을 붙이면 입력값을 전부 모아 튜플로 만들어줌. (ex. *args, *pey, *python)

키워드 매개변수, kwargs

print_kwargs는 입력받은 매개변수 kwargs를 출력하는 단순한 함수이다.

함수의 입력값으로 a=1 사용되면 kwargs는 {'a' : 1}이라는 딕셔너리가 되고 입력값으로 name ='foo', age=3이 사용되면 kwargs는 

{'age': 3, 'name': 'foo'} 라는 딕셔너리가 된다. 

 

함수의 리턴값은 언제나 하나이다

add_add_mul은 2개의 입력 인수를 받아 더한 값과 곱한 값을 리턴하는 함수이다.

이 함수를 위와 같이 호출하면 리턴값은 a+b, a*b인데 리턴값을 받아들이는 변수는 result 하나만 쓰였다.

하지만 함수의 리턴값은 2개가 아니라 언제나 1개이므로 오류가 발생하지 않는다.

add_add_mul 함수의 리턴값 a+b, a*b는 튜플값 하나로 리턴된다.

따라서 result 변수는 다음과 같은 값을 가지게 된다.

만약 이 하나의 튜플값을 2개의 값으로 분리하여 받고 싶다면 함수를 다음과 같이 호출하면 된다.

이렇게하면 result1 은 7, result2는 12가 된다.

위와 같이 return문을 2번 사용해도 2개의 리턴값을 돌려주지 않는다.

보다시피 add_add_mul의 리턴값은 5 하나뿐이다. 

두번째 return문은 실행되지 않았다. 즉, 함수가 return 문을 만나는 순간, 리턴값을 돌려 준 다음 함수를 빠져나가게 된다.

 

매개변수에 초깃값 미리 설정하기

위 함수를 보면 매개변수가 name, age, man=True인데, man=True를 보면 매개변수에 미리 값을 넣어 준 것을 확인할 수 있다.

즉, 함수에 매개변수에 초깃값을 설정하는 방법이다.

 

say_myself 함수는 다음과 같이 2가지 방법으로 사용할 수 있다.

이 두가지 방법은 동일한 결과를 출력한다.

입력값으로 ("박응용", 27)처럼 2개를 주면 name에는 "박응용", age에는 27이 대입된다.

그리고 man이라는 변수에는 입력값을 주지 않았지만, man은 초깃값 True를 갖게 된다.


 

다음으로 초깃값이 설정된 부분을 False로 바꿔 호출하면 man 변수에 False값이 대입되어 "남자입니다,"가 아닌,

"여자입니다."가 출력된다.

 

함수의 매개변수에 초깃값을 설정할 때 주의해야 하는 것은 바로 초깃값을 설정한 매개변수의 위치이다.

함수를 실행할 때 오류가 발생

위와 같이 함수를 호출한다면 name변수에는 "박응용"이 들어간다.

하지만 파이썬 인터프리터는 27을 man 매개변수와 age 매개변수 중 어느 곳에 대입해야 할지 판단하지 못해 

오류가 발생한다.

 

함수 안에서 선언한 변수의 효력 범위

함수 안에서 사용할 변수의 이름을 함수 밖에서도 동일하게 사용한다면 어떻게 될까?

먼저 a라는 변수를 생성하고 1을 대입했다. 그리고 입력으로 들어온 값에 1을 더해 주고 결괏값은 리턴하지 않는

vartest 함수를 선언했다. 그리고 vartest 함수에 입력값으로 a를 주고, print(a)로 출력했다.

 

vartest 함수에는 매개변수 a의 값에 1을 더했으므로, 2가 출력될 것 같지만, 프로그램 소스를 작성해서 실행해 보면 결괏값은 1이 나온다.

 

그 이유는 함수 안에서 사용하는 매개변수는 함수 안에서만 사용하는 '함수만의 변수'이기 때문이다.

즉, def vartest(a)에서 입력값을 전달받는 매개변수 a는 함수 안에서만 사용하는 변수일 뿐,

함수 밖의 변수 a와는 전혀 상관없다.

vartest(3)을 수행하면 vartest 함수 안에서 a는 4가 되지만, 함수를 호출하고 난 후 print(a) 문장은 오류가 발생한다.

그 이유는 print(a)에서 사용한 a 변수는 어디에서도 선언되지 않았기 때문이다.

 

함수 안에서 함수 밖의 변수를 변경하는 방법

1. return 사용하기

vartest 함수는 입력으로 들어온 값에 1을 더한 값을 리턴하도록 변경했다.

따라서 a = vartest(a)라고 작성하면 a 에는 vartest 함수의 리턴값이 대입된다.

 

2. global 명령어 사용하기

위에서 볼 수 있듯, vartest 함수 안의 global a 문장은 함수 안에서 함수 밖의 a 변수를 직접 사용하겠다는 뜻이다.

하지만 프로그래밍을 할 때 global 명령어는 사용하지 않는 것이 좋다.

함수는 독립적으로 존재하는 것이 좋기 때문이다. 

(외부 변수에 종속적인 함수는 그다지 좋은 함수 아님)

lambda 예약어

lambda는 함수를 생성할 때 사용하는 예약어로, def와 동일한 역할을 한다.

lambda로 만든 함수는 return 명령어가 없어도 표현식의 결괏값을 리턴
                       

add는 2개의 인수를 받아 서로 더한값을 리턴하는 lambda 함수이다.

위는 def를 사용한 다음 함수와 하는 일이 동일하다.

 

II. 04-2 사용자 입출력

작성자 박무준

first. what is INPUT

>>> a = input()
Life is too short, you need python
>>> a
'Life is too short, you need python'

input()을 쓰게 되면 입력값을 쓸 수 있는 칸이 나오게 됩니다. 여기에 원하는 값을 쓸 수 있게 됩니다.

입력하는 부분에 <안내메시지>를 넣고 싶다면 어떻게 해야할까요?

>>>a=input("입력값을 입력해주세요!")

like this 이렇게요!

주의할점! input안의 값은 type함수를 이용해서 알아봤을 때 무조건 string 즉, 문자열입니다!

04-2 내용은 생각보다 적네요! 마지막으로 print에서 글자 쓸 때 꿀팁을 알아봅시다.

1) 큰따옴표로 둘러싸인 문자열은 + 연산과 동일하다

2) 문자열 띄어쓰기는 쉼표로 한다

3) 한 줄에 결괏값 출력하기-end=' '을 사용하면 할 수 있습니다

>>>print(i, end=' ')

 

 

III. 04-3 파일 읽고 쓰기

작성자 문하진

 파일생성하기

  • r(읽기모드):파일을 읽기만 할 때 사용
  • w(쓰기모드):파일에 내용 쓸 때 사용
  • a(추가모드):파일의 마지막에 새로운 내용을 추가할 때 사용

해당 파일 안에 출력될 내용이 들어가게 된다.

f = open("새파일.txt", 'w') 
for i in range(1, 11): 
   data = "%d번째 줄입니다.\n" % i 
   f.write(data)
f.close()

 

 파일 읽는 방법

1) readline 함수 이용하기

파일을 읽기모드로 연 후 readline()함수를 사용해서 파일의 첫번째 줄을 읽어 출력한다. 

f = open("C:/doit/새파일.txt", 'r')
line = f.readline()
print(line)
f.close()

2) readlines 함수 사용하기

파일의 모든 줄을 읽어서 각각의 줄을 요소로 가지는 리스트를 리턴한다. 

f = open("C:/doit?새파일.txt", 'r')
lines = f.readlines()
for line in lines:
    print(line)
f.close()

3) read 함수 사용하기

f.read()는 파일의 내용 전체를 문자열로 리턴한다.  

f = open("C:/doit/새파일.txt", 'r')
data = f.read()
print(data)
f.close()

 

 

 파일 객체를 for문과 함께 사용하기

파일 객체 (f)는 for문과 함께 사용하여 파일을 줄 단위로 읽을 수 있다.

f = open("C:/doit/새파일.txt", 'r')
for line in f:
    print(line)
f.close()

 

파일에 새로운 내용 추가하기

파일을 추가 모드('a')로 열면 원래 있던 값을 유지하면서 새로운 값만을 추가할 수 있다. 

아래 코드에서 추가 모드로 파일을 열었기 때문에 원래의 내용 다음부터 결괏값을 적는다. 

f = open("C:/doit/새파일.txt",'a') 
for i in range(11, 20): 
    data = "%d번째 줄입니다.\n" % i 
    f.write(data) 
f.close()

 

with문과 함께 사용하기

with문을 이용해서 파일을 열고 닫는 것을 자동으로 처리할 수 있다. 

with블록을 벗어나는 순간 열린 파일 객체 f는 자동으로 닫힌다.

with open("foo.txt", "w") as f:
     f. write("Life is too short, you need python")

 

IV. 04-4 프로그램의 입출력

작성자 최정우
파이썬의 'sys'모듈은 파이썬의 인터프리터와 직접적으로 상호작용 하는 기능들을 제공합니다. 이것을 통해 실행중인 프로그램에 대한 정보를 얻거나, 인터프리터에 영향을 줄 수 있는 다양한 작업을 수행할 수 있습니다.

가장 많이 사용되는 기능은 바로 명령줄 인수 접근인 'sys.argv'입니다. 보통 파이썬 코드에 전달된 명령줄 인수에 접근할 때 사용됩니다.

활용 예시

import sys
if len(sys.argv) > 1:
    print(f"Hello, {sys.argv[1]}!")
else:
    print("Hello world!")

이 코드는 sys 모듈의 argv 기능을 사용하여 명령줄 인수를 처리하는 예제입니다. 명령줄에서 추가 인수를 제공하면 해당 인수를 사용하여 인사말을 출력하고, 인수를 제공하지 않으면 기본 메세지인 "Hello world!"를 출력합니다.

활용 예시 2

import sys
user_input = input("프로그램을 종료하시겠습니까? (y/n): ")
if user_input.lower() == 'y':
    print("프로그램을 종료합니다.")
    sys.exit() 
elif user_input.lower() == 'n':
    print("프로그램을 계속 실행합니다.")
else:
    print("잘못된 입력입니다. 프로그램을 종료합니다.")
    sys.exit(1)

sys 모듈 중에서 가장 많이 쓰이는 스크립트 강제 종료 함수로 코드를 만들어 보았습니다. 이 함수를 호출하면 현재 실행 중인 프로그램이 즉시 종료됩니다. 이 코드는 프로그램의 실행 또는 종료 상태를 나타내는 데 사용됩니다. 사용자가 y를 입력하면 프로그램은 종료되고 n을 입력하면 프로그램이 계속 실행 됩니다.

V. QUIZ.

작성자 강수환

퀴즈1

while True:
  n=int(input())
  if n== -1:
    break
  divisor = []
  for i in range(1,n):
    if n%i==0:
      divisor.append(i)
  if sum(divisor)==n:
    print(n, "=", " + ".join(str(i) for i in divisor))
  else:
    print(n, "is NOT perfect.")

문제를 보고 어떻게 이 코드를 짤 것인지 사고해보겠습니다.

먼저 예제 입력 1을 보면 코드 실행을 한 번만 시키는데 값을 여러 번 대입하고 -1을 넣었을 때 실행이 끝난다는 것을 알 수 있다. 실행을 중지시키는 제어문은 break라고 할 수 있겠습니다!

while True:
  n=int(input())
  if n== -1:
    break

그럼 여기까지는 일단 쓰고 시작합니다.

for if를 생각할 때 걸러질 전체 집합과 거를 기준이되는 조건을 생각해야합니다.
기준이 되는 조건이 n%i==0 이므로  가능한 요소를 모두 포함하는 전체 집합은 n보다 작은 자연수로 하겠습니다.

for i in range(1,n):
    if n%i==0:
      a.append(i)

이렇게 n보다 작은 자연수 집합에서 기준을 만족하는 녀석들을 거르고 그 녀석들은 divisor에 모아주겠습니다.기준은 sum(divisor)==n sum은 리스트의 합을 구하기 위해 존재하는 녀석입니다.

네 이제 마지막 관문입니다..
print 할 문장 안에 변수에 따라 바뀌는게 많을수록 표현하기 어려워집니다.
n is NOT perfect는 변수가 n밖에 없고 n 그자체여서 그냥 print(n,' = is NOT perfect.')라고 표현하면 그만입니다.

하지만

6 = 1 + 2 + 3

변수의 영향을 받는 print를 생각해보겠습니다.

6은 변수 그 자체입니다. 쉽네요 n, 하면 되겠어요
=은 변수에 따라 변하지 않습니다. 더 쉽네요 '=' 하면 되겠어요
1은 인수 중 첫 번째 수네요. divisor[1]해도 되는데 그러면 인수의 개수도 바뀌는 상황에서 뒤에 녀석들을 쓸 수가 없어요.
1,2,3 이 녀석들이 divisor 리스트에 모두 포함된 녀석들이라는 것
리스트에 있는 요소들을 문자열로 합칠 때 쓰는 방법 -> join
join은 이런 상황을 위해서 태어난 아이에요. 
근데 이때  리스트의 요소들이 문자열이라면 의도된 대로 바로 사용할 수 있는데 숫자라면 join함수 사용이 불가능합니다.
이때 리스트 자체를 문자열로 만드는게 아니라 각각의 요소를 문자열로 만드는게 필요한데요!
리스트를 생성하거나 변환할 때는 리스트 컴프리헨션을 사용하겠다는 생각을 해야해요
(애초에 for if  쓰는게 확정된 순간부터는 컴프리헨션으로 표현해야 빠르겠네요.. for if 만세 컴프리헨션 만세)

그런 의미로 위에 divisor 생성도 컴프리헨션으로 해보고 divisor 변환도 컴프리헨션으로 해보겠습니다.
divisor=[i for i in range(1,n) if n%i==0]
divisor_str=[str(x) for x in divisor]
str으로 바꾸어서 '+'.join으로 연결해주면 끝입니다.

최적화된 답은

while True:
  n=int(input())
  if n== -1:
    break
  divisor = [i for i in range(1,n) if n%i==0]
  divisor_str = [str(x) for x in divisor]
  if sum(divisor)==n:
    print(n, "=", " + ".join(divisor_str))
  else:
    print(n, "is NOT perfect.")