ROKO

[Python] function 본문

Computer Science/Programming Language

[Python] function

RO_KO 2023. 3. 4. 00:03
728x90

function의 목적

function은 왜 쓰는걸까? 가독성과 코드의 재사용?

성능에는 변화가 없다면 궁극적인 목표에는 안좋은게 아닌가?

 

파이썬은 def를 통해 함수로 지정하게되면 실행시 함수 내부 코드를 indentation을 기준으로 최적화 코드로 변환한다.

따라서 같은 반복문을 2번 반복하는것보다 함수를 2번 호출하는것이 더 빠르다.

 

궁금하다면 import time을 통해 각각 실행시간을 확인하는 실험을 해보면 알 수 있다.

import time

def func():
    num = 0
    for i in range(100000):
        num += i

t1 = time.perf_counter()
num = 0

for i in range(100000):
    num += i

for i in range(100000):
    num += i

for i in range(100000):
    num += i
t2 = time.perf_counter()
func()
func()
func()
t3 = time.perf_counter()

print(t2-t1)
print(t3-t2)

for문 / 함수사용

시간 결과 차이를 보면 같은 코드임에도 유의미한 차이가 나는것을 알 수 있다.


namespace

print(globals())

해당 소스코드 파일에 있는 모든 namespace가 나열된다. 하지만 소스코드에 함수를 정의한 경우 함수 내부에서 구현되는 변수들은 globals()에 포함되지 않는다.

 

함수는 함수만의 namespace를 갖게 되는데 함수 실행시 내부 코드에

print(locals())

를 작성하면 함수의 namespace들이 출력된다.

 

locals()는 실행된 공간에서의 namespace들을 전부 return해준다. 만약 전역코드로 실행했다면 globals()와 같은 결과가 나오게 되었을 것이다. 함수안에 또 함수가 정의된 경우도 서로 다른 namespace 공간으로 분류된다. 즉 A함수안에 정의된 B함수가 있을때 A함수에서 locals()를 출력한다고 하더라도 B함수의 내부의 namespace들은 출력되지 않는다.

 

namespace 참조

같은 namespace가 아니라면 변수를 참조할 수 없다.하지만 globals()의 변수들이나 상위 함수에 있는 namespace들의 변수들은 참조가 가능하다.

왜 굳이 namespace를 정의하고 분리하는 걸까?

namespace를 고려하지 않는다면 동시에 여러 함수나 코드에서 같은 변수를 접근하게 된다면 값이 무질서하게 변경되고 프로그래밍을 할때 이러한 관계성을 고려해서 코드를 짜야한다. 코드 자체의 생산성도 떨어질 뿐더러 구현도 어려워지기 때문에 namespace의 분리가 필요하다. 그러면 복잡한 관계를 고려하지않고 알고리즘에만 집중하여 작성할 수 있을 것이다.

 

외부변수 변경방법

함수내부에서 외부변수와 같은 변수이름을 가진 객체를 생성해 변경하더라도 다른 namespace에서 생성되었기 때문에 같은 이름이지만 다른 변수로 분류가 된다. 만약 함수내부에서 외부 변수를 직접적으로 변경하고 싶은 경우 어떻게 해야 할까?

 

함수에서 global이나 nonlocal 이용해 객체를 생성하게 되면 외부변수를 참조하게 된다.

lang = 'jython'
def func():
      global lang = 'python'


func()
print(lang)

# python

function parameter

def func(a, b):
      pass

임의의 함수 func()가 있다고 가정하자

location mapping

func('a', 'b')

input 자리로 parameter를 결정하는것을 위치인자로 매핑한다고 한다.

keyword mapping

func(b='b', a='a')

위치가 다르더라도 각 위치의 매개변수에 직접적으로 키워드를 이용해 input해주는 방식을 키워드인자 매핑이라고 한다.

 

두가지를 혼용할 경우 위치인자가 항상 키워드인자보다 먼저 위치해야하기 때문에 규칙을 지켜 사용해야 한다.

func('a', b='b') # True
func(a = 'a', 'b') # False

 

함수를 선언할때 default값을 지정하여 선언할 수 있다. 만약 input이 아무것도 없다면 default값을 기준으로 함수가 실행된다.

def func(a='a', b='b'):
      pass
      
func()
func('a','b')
func(a='a',b='b')
func('a',b='b')

# all the same

packing

함수를 구현함에 있어 입력값의 개수가 고정값이 아닐 수 있다. 

파이썬은 이런 경우를 대비해 packing을 제공한다.

def func(*args):
	print(args)
    
func(1,2,3,4)
# (1, 2, 3, 4) tuple

 

매개변수 앞에 *(asterisk)를 붙여 사용하는데 입력된 모든 위치인자 값들을 하나의 tuple 객체로 묶어준다.

def func(**kwargs):
	print(kwargs)
    
func(a=1, b=2, c=3)
# {a:1, b:2, c:3} dict

매개변수 앞에 **를 붙이는 경우는 입력된 모든 키워드 인자값들을 하나의 dict 객체로 묶어준다.

def func(*args, **kwargs):
	pass

두 경우를 혼합하여 사용할수도 있다.

 

unpacking

반대로 여러객체가 하나로 묶인 객체를 반대로 풀어주는 방법도 있다. 이 경우는 함수의 매개변수가 아니라 묶여있는 인자 앞에 위치인자인 경우 *, 키워드 인자인 경우 **를 붙여 해제하면 된다.

data = [1,2,3]
sum(data) # error
sum(*data) # 6
sum(*[1,2,3]) # same as above

해제할 수 있는 변수 타입은 container면 전부 가능하다.

container에 값이 없는 경우 무시하고 아무것도 일어나지 않기 때문에 자유롭게 pythonic하게 코드를 구현할 수 있다.

728x90

'Computer Science > Programming Language' 카테고리의 다른 글

[Python] decorator  (0) 2023.03.04
[Python] lambda  (0) 2023.03.04
[Python] mutable vs immutable  (0) 2023.03.03
[Python] Container, Sequence  (0) 2023.03.03
Comments