2018-01-19 TIL WPS 10.파이썬- 함수

파이썬

함수

함수는 return 값이 없으면 none을 반환한다.


Asterist 이해하기

파이썬의 Asterisk(*) 이해하기

여기서 몰랐던 건 3번과 4번.

3. 가변인자 (variadic Parameters)를 사용하고자 할 때

가변인자를 필요로 할 때는 들어오는 인자의 갯수를 모른다거나, 어떤 인자라도 모두 받아서 처리를 해야하는 때.

인자의 종류는 두 가지인데 한 가지는 positional arguments이고 keyword arguments이다.

Positional arguments

  • 생략이 불가능 하며 갯수대로 정해진 위치에 인자를 전달해야함
  • *args는 임의의 갯수의 positional arguments를 받음을 의미
  • args라는 list에 저장
def save_ranking(*args):
    print(args)
    
save_ranking('ming', 'alice', 'tom', 'wilson', 'roy')

Keyword arguments

  • 선언시 디폴트 값을 설정할 수 있으며, 인자를 생략할 시 디폴트 값으로 인자의 값으로 들어간다.
  • kwargs라는 dict에 저장
def save_ranking(**kwargs):
    print(kwargs)
    
save_ranking(first='ming', second='alice', fourth='wilson', third='tom', fifth='roy')

생략이 가능하므로 positioinal arguments 이전에 선언 될 수 없다.

에러가 되는 코드

def save_ranking(first, second=None, third, fourth=None):
    ...

만약에 아래와 같이 positional arguments 2개, keyword arguments 2개가 함수의 파라미터로 정의 되었고, 인자의 형태가 positional arguments 3개, keword argument 1개가 입력되면

def save_ranking(first, second, third=None, fourth=None):
...

save_ranking('alice', 'ming', 'mike', fourth='jim')

keyword arguments의 경우 선언된 위치만 동일할 경우 자동으로 3번째 positional argument는 third의 키로 전달됨

-

4. 컨테이너 타입의 데이터를 unpacking 할 때

컨테이너 타입의 데이터(list, tuple, dict)를 unpacking하는 경우에 사용 가능하다.

def func1(*args):
	...

func1(*list) #리스트 언패킹
func1(*tuple) #튜플 언패킹


def func2(**kwargs):
	...
func2(**dict) #딕셔너리 언패킹

스코프(Scope)

각 함수는 별개의 로컬 스코프를 가진다.

글로벌, 로컬 변수

글로벌 변수와 로컬 변수의 이름이 같더라도 id를 확인해보면 다른 객체임을 확인할 수 있다.

함수 내부에 지역 변수가 없다면 글로벌 변수를 참조해서 값을 집어넣지만 함수 내부에 로컬 변수가 선언되어 있다면 일단 로컬 변수를 참조하려고 한다. 따라서 아래 코드에서 지역 변수 champion이 선언 되기 전에 작성된 프린트문은 에러를 일으킨다.

champion = 'Lux'

def show_global_champion():
    print('show_global_champion : {}'.format(champion))

def change_global_champion():
    print('before change_global_champion : {}'.format(champion))
    champion = 'Ahri'
    print('after change_global_champion : {}'.format(champion))

show_global_champion()
change_global_champion()

내부함수에서의 로컬 스코프(nonlocal)

champion = 'Lux'

def print_champion():
	print(f'global champion: {champion}')

def local1():
	champion = 'Ahri'
	print(f'local1 champion: {champion}')
	
	def loca2():
		nonlocal champion
		champion = 'Ezreal'
		print(f'local2 champion: {champion}')
	local2()

print_champion()
local1()
print_champion()

nonlocal은 자식의 변수가 가까운 부모의 변수를 대체함(?), 이 부분이 제일 이해가 되지 않음. 설명에서는 자신의 바로 바깥 영역의 로컬 스코프의 데이터를 참조한다고 했는데 반대로 자식의 변수가 부모의 변수를 참조하는 것 아닌가?

공식문서의 설명은 이렇다

To rebind variables found outside of the innermost scope, the nonlocal statement can be used

가장 안쪽의 스코프의 바깥쪽에서 찾은 변수를 다시 바인딩하려면 nonlocal문이 사용될 수 있다.

안쪽의 nonlocal변수 선언이 바로 바깥쪽에서 발견된 변수를 다시 묶는다(재설정한다)라고 해석하면 될 것 같다.

클로저

함수가 정의된 환경, 파이썬의 파일 하나는 모듈을 의미하고 각 모듈은 독립적이다. 독립된 환경은 각자의 영역을 전역 영역으로 사용한다. 따라서 글로벌 변수는 모듈 영역에서만 통한다는 뜻!

내부함수의 클로저

level = 0
	def outer():
		level = 50
		def inner():
			nonlocal level
			level += 3
			print(level)
		return inner

func = outer()

outer함수를 호출했을 때 process를 살펴보면

  1. 지역변수 level = 50이 선언되고,
  2. inner()함수가 실행된다.
  3. nonlocal문으로 인해 inner의 level이 outer의 level과 rebind된다.
  4. 3이 더해지고 출력되며 inner 함수는 종료된다.
  5. 다시 outer함수로 돌아와 inner함수를 반환한다.

nonlocal로 inner()와 outer()의 level이 바인딩되어있고 func()함수 내부에 level 변수가 계속 유지되어 inner함수가 실행되어 값이 추가될 수 있는 것이다.

클로저란 개념은 해당 모듈이나 아니면 해당 로컬 스코프가 해당 스코프와 동작하기 위한 모든 영역들을 자신의 영역들을 갖는다.

라고 강사님께서 말씀하셨는데 이해가 아직안된다.

좀더 내용을 찾아보았다

school of web (클로저)

클로저는 어떤 함수를 함수 자신이 가지고 있는 환경과 함께 저장한 레코드이다. 또한 함수가 가진 프리변수(free variable)*를 클로저가 만들어지는 당시의 값과 레퍼런스에 맵핑하여 주는 역할을 한다.

*프리변수 : 파이썬에서 프리변수는 코드블럭안에서 사용은 되었지만, 그 코드블럭안에서 정의되지 않은 변수를 뜻함.

def outer_func(): #1
	message = 'Hi' #3
	
	def inner_func(): #4
		print(message) #6
	return inner_func() #5

outer_func() #2
  • 1에서 정의된 함수 outer_func를 #2에서 호출을 합니다. 물론 outer_func는 어떤 인수도 받지 않습니다.
  • outer_func가 실행된 후, 가장 먼저 하는 것은 messge 라는 변수에 ‘Hi’라는 문자열을 할당합니다. #3입니다.
  • 4번에서 inner_func를 정의하고 #5번에서 inner_func를 호출하며 동시에 리턴합니다.
  • 6에서 message 변수를 참조하여 출력합니다. 여기서 message는 inner_func 안에서 정의되지는 않았지만, inner_func 안에서 사용되기 때문에 프리변수라고 부릅니다.

innder_func는 outer_func의 로컬변수인 message를 참조하는데 클로저가 어딘가에 함수의 프리변수를 저장했기 때문이다. 어디에 저장되어있는지는 위 참조 사이트에 자세히 나와있다.

클로저 응용

def outer_func(tag):  #1
    text = 'Some text'  #5
    tag = tag  #6

    def inner_func():  #7
        print '<{0}>{1}<{0}>'.format(tag, text)  #9

    return inner_func  #8

h1_func = outer_func('h1')  #2
p_func = outer_func('p')  #3

h1_func()  #4
p_func()  #10

데코레이터(decorator)

함수를 받아 다른 함수를 반환하는 함수. 장식하듯이 이름처럼 기존 코드에 여러가지 기능을 추가하는 파이썬 구문.

제네레이터(generator)

제네레이터는 함수는 파이썬의 시퀀스 데이터를 생성하는데 사용된다. 실제 시퀀스 데이터와 다른 점은, 시퀀스 전체를 가지고 있는 것이 아니라 시퀀스 데이터를 생성하기 위한 어떠한 루틴만을 가지고 있는 것이다.

Comments