PY | function, 함수와 변수의 영역

Stellar·2021년 5월 16일
0

Python

목록 보기
7/36
post-thumbnail

함수란?

프로그래밍을 하다보면 값만 바뀌고 같은 코드가 반복되는 경우가 있다. 이런 반복 코드를 작성해 놓고 필요할 때 계속 불러 쓸 수 있다. print, input 등도 파이썬에서 미리 만들어놓은 함수이다.

파이썬은 함수형 언어
함수형 언어란 인수로 함수가 전달될 수 있는 것을 뜻 함.

Q. 인자 == 인수 == 매개변수 맞나?

A.

# 함수의 기본 구조

def 함수이름(매개변수):
    실행할 코드
    ...
    return 반환값
    
  • 함수는 input parameter를 받아서 return 값을 output으로 리턴한다

  • 매개변수 (parameter) == argument : 함수 사용을 위해 입력해야할 변수

# 함수 호출

함수 호출 시 print 되는게 있고 안되는게 있는데 이 차이는 함수 코드안에 print()의 유무다

def calculate_total(amount): # 함수 생성
    tax = amount * 0.095
    saved = amount * 0.15
    total = amount + tax + saved
	
    print(total)
    return total # return을 해줘야 이 함수가 값을 가진다
    
calculate_total(20) # 함수 호출만 기능함, 함수안에 print()가 있는 경우 print가 자동으로 된다
# print(calculate_total(20)) 함수에 print()가 없는 경우 값을 print()로 감싸 화면에 표시해 준다

# 리턴(Return)

값을 반환하여 함수에 값을 저장한다. 조건문에 return이 있으면 해당 조건문은 끝이 나므로 else가 필요없다.
리턴 값이 if문, while문, for문 등에 인덴트(indent, 들여쓰기)되어 있는지 잘 확인하기
: 인덴트되어 있으면 값이 제대로 반환 되지않았음.

def get_occurrence_count(my_list):
  # 이 함수를 구현 해주세요
  counts = {}

  for i in my_list:
    if i in counts:
        counts[i] += 1
    else:
        counts[i] = 1
    #return counts # for문에 indent 되어 있어 값이 함수에 저장되지 않는다.
  
  return counts # 함수에만 종속되어있음
  
print(get_occurrence_count(["one", 2, 3, 2, "one"]))

# 함수를 실행하여 각 값의 수를 세어 반환함
>>> {"one": 2, 2: 2, 3: 1}

예제. 원면적과둘레구하기

import math

def calCircle(r) :
    area = math.pi * r * r
    circum = 2 * math.pi * r
    return (area, circum)

radi = float(input('반지름을 입력하세요 : '))

(a, c) = calCircle(radi) 
print('원의 면적은 {}, 원의 둘레는 {} 입니다.'.format(round(a, 2), round(c, 2))) # round()함수를 사용 소수점 둘째자리까지만 표기
  • round() 사용 시 리턴 받은 반환 값에 소수점 두 자리만 표기하는 옵션을 줄 수 있다.

Q. 함수 호출 시 리턴값 받은걸 어떻게 해야하는 거지?

A.반환 받은 리턴 값을 변수에 저장 후 사용해야 함.
함수 입력 값과 리턴 값의 개수는 상이해도 된다.

✔️ function value

def add(a, b) :
    print(a + b)

plus = add #함수 자체를 변수에 대입하여 사용.
plus(1, 2)

✔️ function parameter

def calc(op, a, b) :
    op(a, b)

def add(a, b) :
    print(a + b)

def multi(a, b) :
    print(a * b)

calc(add, 1, 2)
calc(multi, 3, 4)

✔️ local function, 지역 함수

함수 내부의 함수

def calcsum(n) :
    def add(a, b) :
        return a + b

    sum = 0
    for i in range(n+1) :
        sum = add(sum, i)
    return sum

print('~10 = ', calcsum(10))

✔️ factory function

def makeHello(message) :
    def hello(name) :
        print(message + ', ' + name)
    return hello

enghello = makeHello('Good morning')
hanhello = makeHello('안녕하세요')

enghello('Mr Kim')
hanhello('홍길동')

arguments, 인수의 종류

✔️ 인수의 기본 값, Parameter Default Value

  • 함수에서 인수의 기본 값을 설정할 수 있다.
  • 함수의 parameter에 default 값을 정의해 줄 수 도 있다.
  • ❗️default 값이 정의된 parameter가 default 값이 정의 되지 않은 parameter보다 먼저 위치해 있으면 안된다❗️
    • ❓️ 함수를 정의 할때 default value parameter를 non-default value parameter 앞에 정의 하면 안 되는 이유 - ❗️❗️ 파이썬 문법 상 정해진 순서가 있기때문에 순서를 지켜 쓰지 않으면 오류가 발생한다.
#기본 값
def calcstep(begin, end, step = 1) : #step = 1이 기본 값을 설정한다는 의미
    sum = 0
    for num in range(begin, end + 1, step) :
        sum += num
    return sum

print('1 ~ 100 = ', calcstep(1, 10, 2))
print('1 ~ 100 = ', calcstep(1, 100))

# positional arguments, 위치 인수

def love_you(my_name, your_name):
    print(f"{my_name} loves {your_name}")


love_you("커피", "라떼") # 기본적인 형태로 순서대로 값이 parameter로 input되는 argument

>>> 커피 loves 라떼

# Keyword Arguments, 키워드 인수

함수의 인수명을 직접적으로 카리키는 것을 키워드 인수라 함.
키워드가 명확해 순서가 뒤바껴도 상관없다.

#키워드 인수
def calcstep(begin, end, step) : 
    sum = 0
    for num in range(begin, end + 1, step) :
        sum += num
    return sum

#인수명을 직접적으로 카리키는 것을 키워드 인수라 함.
print('1 ~ 100 = ', calcstep(begin = 1, end = 10, step = 1))

#키워드가 명확해 순서가 뒤바껴도 상관없다.
print('1 ~ 100 = ', calcstep(step = 1, begin = 1, end = 10)) 

#인수 마지막만 키워드 인수여도 가능.
print('1 ~ 100 = ', calcstep(3, 5, step = 10))

#키워드인수가 순서에 맞지않게 뒤에 위치해도 불가능.
#print('1 ~ 100 = ', calcstep(3, 5, end = 10))

#키워드 인수는 앞쪽에 오면 에러가 난다.
#print('1 ~ 100 = ', calcstep(begin = 3, 5, 10)) 

# Mixing positional arguments and keyword arguments

def love_you(my_name, your_name):
    print(f"{my_name} loves {your_name}")


love_you("커피", your_name="라떼") 
# keyword arguments는 순서가 바뀌어도 상관 없지만 positional arguments는 순서를 지켜줘야 한다

>>> 커피 loves 라떼

✔️ 가변 인수, Non-keyworded variable length of arguments

  • 인수 앞에 *을 붙여 사용한다. * 이 붙으면 인수가 몇 개가 와도 상관이 없다는 말.
    기존 함수에는 지정된 인수의 개수 만큼만 줄 수 있지만 가변인수를 쓸 경우 무제한.
  • Keyworded variable length of arguments와 동일하지만 keyword 를 사용하지 않고 순서대로 값을 전달하는 방식
  • tuple로 변환되어 함수에 전달

#가변 인수, vararg `*` 이 붙으면 몇 개가 와도 상관이 없다는 말.
def intsum(*ints):
    sum = 0
    for num in ints :
        sum += num
    return sum

print(intsum(1, 1, 5, 3))
print(intsum(1, 1, 5, 3, 10 ,23, 55))
print(intsum(1, 1, 5, 3, 10 ,23, 55, 11, 84, 30))

주의.

  1. 가변 인수는 항상 마지막에 위치할 것.
  2. 하나만 사용할 것.
# 가능
def intsum(s, *ints): 
    sum = 0
    for num in ints :
        sum += num
    return sum

# 불가능
def intsum(*ints, s): 
    sum = 0
    for num in ints :
        sum += num
    return sum

# 불가능
def intsum(*ints, *ints): 
    sum = 0
    for num in ints :
        sum += num
    return sum

참고한 사이트

✔️ 가변 키워드 인수, Keyworded variable length of arguments

  • Keyworded variable length of arguments는 dictionary 형태로 지정된다.
  • Keyworded variable length of arguments를 사용할때 일반적으로 argument 이름을 **kwargs 라고 parameter 이름을 정합니다.
  • 함수 body 안에서는 dictionary를 사용하듯이 kwargs를 사용하면 된다.

#가변 키워드 인수
def calcstep(**args) :
    begin = args['begin']
    end = args['end']
    step = args['step']
    
    sum = 0
    for num in range(begin, end + 1, step) :
        sum += num
    return sum

print('1 ~ 100 = ', calcstep(begin = 1, end = 10, step = 1))
print('1 ~ 100 = ', calcstep(step = 1, begin = 1, end = 7)) 

Q. ' '값이 인수와 똑같아야하는가?

a.

✔️ 혼합 사용 예제

인수, 가변 인수, 가변 키워드 인수 순으로 사용한다.

def calcscore(name, *score, **option) :
    print(name)
    sum = 0
    for s in score :
        sum += s
    print('총점 : ', sum)
    if option['avg'] == True :
        print('평균 : ', sum / len(score))

calcscore('김상현', 88, 99, 77, avg = True)
calcscore('김한솔', 99, 98, 95, 89, avg = False)

변수의 영역

✔️ Local, 지역 변수.

local 변수란 함수 내에서만 사용되는 변수를 뜻 함.
따라서 함수 내부의 변수는 외부로 가져오지 못하니 print() 사용도 못 함.

지역변수 예제1.

#지역 변수
def kim() :
    temp = '이건 kim() 함수의 내부 변수' #지역 변수
    print(temp)

kim()
#print(temp) #실행 시 찾을 수 없다고 나옴.

지역변수 예제2.

#지역 변수 2
def kim() :
    temp = '이건 kim() 함수의 내부 변수' #지역 변수
    print(temp)

def lee() :
    temp = 2 ** 10 #지역 변수
    return temp

def park(a) :
    temp = a * 2 #지역 변수
    print(temp)

kim()
print(lee())
park(6)

=============================== RESTART: C:\Users\GIEC\Desktop\기초문법\1031\test.py ==============================
이건 kim() 함수의 내부 변수
1024
12

✔️ Global, 전역 변수

함수 밖에 정의 한 변수를 뜻 함.
따라서 함수 내, 외부에서 사용 가능.

전역변수 예제1.

#전역 변수
salerate = 0.9 #전역 변수

def kim() :
    print('오늘의 할인율 : ', salerate)

def park() :
    price = 1000
    print('가격 : ', price * salerate)

kim()

salerate = 1.1 # 전역 변수를 재정의
park()

전역변수 예제2. id와 결과 값이 다른 것을 확인할 수 있다.

#전역 변수 2
price = 1000

def sale() :
    price = 500
    print('함수 내부 price변수', price, id(price))

sale()
print('함수 외부 price변수', price, id(price))

=============================== RESTART: C:\Users\GIEC\Desktop\기초문법\1031\test.py ==============================
함수 내부 price변수 500 1672006266448
함수 외부 price변수 1000 1672006266640

전역변수 예제3. 지역 변수를 전역 변수로 만들 수 있다.

예제 2번과 다르게 id 값이 동일한 것을 알 수 있다.

#전역 변수 3
price = 1000

def sale() :
    global price # 전역변수로 정의.
    price = 500
    print('함수 내부 price변수', price, id(price))

sale()
print('함수 외부 price변수', price, id(price))

=============================== RESTART: C:\Users\GIEC\Desktop\기초문법\1031\test.py ==============================
함수 내부 price변수 500 1742881484368
함수 외부 price변수 500 1742881484368

Gnerator, 제너레이터

제너레이터의 사전적 의미는 발전기 또는 뭔가를 만드는 사람이나 물건을 뜻 함.
yield 키워드와 함께 쓰이는데, yield는 return과 달리 여러 줄로 사용 가능하다. 또한 return은 문장을 끝내지만 yield는 반환만 할 뿐 종료되지 않아 yield 아래에 코드를 추가할 수 있다.
함수에서 Iterable한 객체를 만들 수 있다.

def myGenerator() :
    yield 'first'
    yield 'second'
    yield 'third'

for word in myGenerator() : #함수를 ier 객체로 사용함.
    print(word)
    
========================= RESTART: /Users/boksilhwang/Documents/test.py =========================
first
second
third

Gnerator 예제.

def MyCounterGen(low, high) :
    while low <= high:
        yield low
        low += 1

for i in MyCounterGen(1, 10) :
    print(i, end=' ')

Gnerator 예제2. sequence

def seqgen(data):
    for index in range(0, len(data), 2):
        yield data[index:index +2]

solarterm = seqgen('입춘우수경칩춘분청명곡우입하소만망종하지소서대서')
for k in solarterm :
    print(k, end=', ')

generator 예제 3. generator comprehension

data = '입춘우수경칩춘분청명곡우입하소만망종하지소서대서'
for k in (data[index:index+2] for index in range(0, len(data), 2)) :
    print(k, end=', ')

0개의 댓글