파이썬과 루비의 문법 차이로 인한 버그를 당한적은 자주 있었지만 글로 다룰 생각까진 (게을러서) 하지 않았다. 하지만 아래의 글을 읽고 파이썬와 루비의 차이로 인한 버그를 정리해보면 재밌을거라고 생각했다. 그래서 써보기로 했다. Show 루비와 파이썬에서 함수 호출과 함수 참조에 대한 차이 기본 매개변수를 이용해서 낚시를 해보자. (얼마나 낚일지는 모르지만) Default argument 를 남들이 기본 매개변수라고 번역하길래 기본 매개변수라고 적었지만 디폴트 매개변수, 기본 인자 등등으로도 불리는거같다. 용어를 하나로 합치려고 default argument 만을 사용하겠다. 문제1. 다음 코드의 실행 결과는?간단한 파이썬, 루비 코드이다. Default parameter에는 현재 시간이 들어간다. 현재 시간을 찍는 함수를 호출하고 1초 쉬고 다시 현재 시간을 찍는 함수를 부른다. 어떤 실행 결과가 나올지 생각해보자.
파이썬에서는 같은 시간이 2번 찍혔다. 루비에서는 1초 차이나는 시간이 찍혔다. 파이썬에서는 default argument는 미리 계산된 값을 사용하고 루비에서는 함수 호출할때 계산하는거같다. 문제2. 다음 코드의 실행 결과는?함수 기본값은 언제 계산될까? 이를 확인하기 위해서 간단한 코드를 짰다. “foo called” 를 출력하는
함수를 호출한적이 없는데 파이썬에서는 “foo called” 가 찍혔다. 루비는 foo(), bar() 로 인한 출력이 없다. 파이썬에서는 소스를 읽으면서 default argument를 계산하나보다. Language specification“원래 파이썬과 루비는 이렇게 행동하는게 정상입니다” 라고 끝내면 심심하니 언어 스펙을 뒤져보자. Python파이썬 3.5 Language Reference 를 뒤져보면 함수 기본값과 관련된 정보를 찾을 수 있다. 8.6. Function definitions 에 나와있다. https://docs.python.org/3.5/reference/compound_stmts.html#function-definitions
파이썬에서는 Default argument를 Default paramter value 라고 부른다. default paramter value는 함수가 정의될때 평가되서 정해지고 이후 함수 호출에서는 미리 계산된 값을 사용한다. RubyProgramming Languages — Ruby IPA Ruby Standardization WG Draft August 25, 2010 를 참고했다. https://www.ipa.go.jp/files/000011432.pdf 13.3.2 Method parameters , 13.3.3 Method invocation 에서 Default argument와 연관된 것을 찾을 수 있다.
루비에서는 Default argument를 Optional parameter 라고 부른다. 함수 호출 시점에 optional parameter에 대응되는 argument가 넘어오지 않으면 (함수 호출시 기본값을 대신할 값을 넣지 않은 경우) default parameter expression을 평가해서 인자로 사용한다. Python 함수에서 정의된 parameter의 순서와는 다르게 parameter의 이름을 명시해 준다면 순서가 반대로 되어도 값을 전달 해 주는 것이 가능하다
keyword arguments를 명시하면서 함수를 실행하게 되면 가독성도 높아질 수 있고 만일 실수로 값이 바뀌었다 하더라도 어떤 parameter인지 명시적으로 알 수 있기 때문에 관련 오류가 발생했다 하더라도 바로 조치가 가능하다는 장점이 있다. 1-1. positional arguments와 같이 쓸 때 유의할 점keyword arguments는 그 parameter가 확실히 명시되어 있기 때문에 순서가 바뀌어도 상관이 없지만 일반 arguments들(positional arguments)은 어떤 값인지 명시되어 있지 않기 때문에 그 순서가 중요하다. 당연하게도 엉뚱한 곳에 해당 값이 들어가게 되면 원치 않는 결과를 출력하게 되기 때문이다. 이 둘을 같이 사용할 때는 순서를 지켜줘야 하며 그렇게 하지 않으면 에러를 발생시키게 된다.
에러가 나는 이유는 positional argument의 순서가 틀렸기 때문이다(첫번째에 와야 하는데 두번째에 왔다) 실제로 그렇게 되었다고 에러 메세지가 친절히 설명해 준다. 2. Parameter Default Value함수에 parameter 그 자체에 default값을 정의해 줄 수도 있는데 이럴땐 default값이 정의되지 않은 parameter 보다 먼저 위치해서는 안된다. 실제로 syntax error가 발생한다.
2-1. 그렇다면 왜 에러가 나는 것일까 ?아래와 같은 경우를 생각해보자.
만약 * Reference
|