파이썬(python) 함수 및 스코핑룰(scoping)

함수에 대한 내용이 제어문 다음에 왔어야 했는데, 뜬금없이 파일 입출력에 대한 글을 써버렸네요. 아무튼 이 강의는 애초에 최소 C언어에 대한 기초가 있는 분들을 위한 강의지만, 처음 프로그래밍을 접하는 분들에게도 도움되는 내용이 있을 거라 생각됩니다. 그냥 몰라도 한번 따라 하시면 됩니다. 프로그래밍은 처음에는 머리굴려 생각하는 것 보다 몸으로 체득하는 것이 중요합니다. 다시 본론으로 들어가서 파이썬의 함수나 C/C++에서의 함수나 거기서 거기입니다. C/C++과 약간 차이가 나는 부분만 정리하고 넘어가면 되는 정도, 파이썬이 첫 프로그래밍 언어라면 그냥 그대로 익히시면 됩니다. 그리고 스코핑 룰이라 주제를 첨가했는데, C++의 이름공간과 전역 변수 지역변수의 비슷한 개념이라고 생각하시면 됩니다. 함수와 관련된 내용이라 첨가했습니다.

파이썬으로 간단한 함수 만들어보기

C/C++언어와 차이나는 점은 파이썬은 동적 타입이기 때문에 인수에 타입명이 없다는 것 입니다. 또한 함수선언을 한 후 콜론(:)으로 함수선언의 끝임을 나타냅니다.

C/C++언어의 경우

파이썬의 경우는 a 값에 모든 타입이 들어갈 수 있습니다. 심지어 함수명도 들어갈 수 있습니다.

함수이름은 그대로 함수포인터가 됩니다. C/C++의 경우는 함수포인터에 관한 문법이 쉽지는 않은데, 파이썬은 이것을 그냥 씹어 먹고 있습니다. 매우 간단하네요.

파이썬은 언어적 차원에서 포인터가 없습니다. 따라서 함수명은 함수 레퍼런스가 되어야 겠죠. 함수의 실체(함수객체)는 메모리의 어딘가에 있고 함수 명으로 실체에 접근 하는 겁니다.

이런 식으로 대입하여 temp 또한 함수 레퍼런스가 되어 func 함수명 대신 temp로 사용이 가능합니다. 아래 그림처럼 globals()를 실행하면 현재 전역지역에 생성되어 있는 객체들을 볼 수 있습니다.

레퍼런스 temp와 func 가 가리키는 함수객체의 주소가 동일함을 알 수 있습니다.

 

내장함수

위에서 잠깐 나온 globals()는 내장함수 입니다. 위에 globals()를 실행시키면 위와 같이 사전 형식으로 전역 변수들이 사전형식으로 표시가 됩니다.

'__builtins__' : <module '__builtin__' (built-in)> 이라고 된 부분이 보일 겁니다. __builtins__는 내장함수 리스트를 가진 변수인데

>>>dir(__builtins__)

위와 같이 하면 내장함수를 리스트형으로 확인할 수 있습니다.

>>>dir()이라고 하면 현재 지역의 객체를 리스트 형식으로 보여줍니다.

dir()을 전역에서 그리고 함수 내에서 실행해 보면

전역에서 실행한 경우 : 전역변수들이 보이는데 내장객체들을 저장한 '__builtins__'도 전역 지역에 있습니다. dir()이라고 치면 나오는 객체들은 일종의 폴더라고 생각하면 쉽게 이해할 수 있습니다. 이 폴더 내부에 객체들(함수나 변수)가 있다고 생각하 보길 바랍니다. 이 폴더의 내부를 보고 싶다면 dir(폴더)라고 하면 되겠죠. 비유해서 설명한 것이니 진짜 폴더라고 하지는 말아주세요.(리스트입니다)

아무튼 globals()나 locals()와 dir()은 사실 근본적으로는 같은 정보를 보여주는데, 단지 보여주는 형식만 사전형식과, 리스트형식으로 틀린 것입니다.

 

스코핑(scope) 룰

스코핑 룰은 간단합니다. "LGB" 순서라고 외워두세요. 변수를 찾는 우선순위를 지역->전역->내장 으로 한다는 뜻입니다. C/C++의 경우와 비슷합니다만 ...

예들 들면

위 경우는 전역으로 a=3을 선택했고 test함수 내부에서 a를 리턴 합니다. test 함수 내부 지역 객체 a가 없으므로 전역으로 넘어가서 찾게 됩니다. 전역에서 찾았으므로 3이 출력됩니다. 여기서 test함수를 재선언한 후 내부에 a=5를 선언합니다. 내부 지역 객체에 a가 있으므로 결과는 5를 출력합니다. 전역에 있는 a=3과 전혀 다릅니다.

만약 함수 내에서 외부 객체를 사용하고 싶다면 

global a

a=5

이런식으로 사용하면 외부 객체를 사용하게 됩니다. (C/C++에서는 외부 변수를 사용하고 싶다면 포인터를 사용하는데 말이죠.)

다음은 또 다른 예입니다.

위에서 globals() 가 내장함수임을 알았습니다. 이 또한 함수이므로 globals는 하나의 레퍼런스 객체입니다. 실수로 globals라는 이름의 변수로 4를 대입했다고 치고, 내장 함수 globals()를 사용하려고 하면 에러가 납니다. 현 지역(전역) 객체로 globals=4가 정의 되었으므로 내장함수를 체크하기전에 전역에 globals가 있음을 발견합니다. 전역에 정의된 globals는 함수가 아니므로 에러를 냅니다. del로 현 지역(전역)의 globals 객체를 삭제한 후 다시 함수를 호출 했습니다. 제대로 호출 되는군요. 한가지 더 예를 들어보죠.

이번에는 함수를 정의했습니다. 내장함수와 동일한 함수명이 전역에 있다면 내장 함수는 사용이 안됩니다.

반응형
이 댓글을 비밀 댓글로
    • LeaF
    • 2015.10.20 00:37
    항상 잘 보고있습니다.
    너무 도움이 됩니다.
    책보다 세세한부분도 있고 가끔 건너뛰는 부분도있지만 그건 세세한부분이 더 많은 것 같습니다.
    컴퓨터의 구조와 연계시켜 설명하는 부분을 보면서 새롭게 알아가는 부분도 많습니다.
    • 도움이 되신다니 다행이네요. 이렇게 잘 봐주시는 분들이 계시니 앞으로 좀 더 신경써서 강의를 올려야 겠습니다.^^감사합니다.
    • 익명
    • 2015.11.05 18:51
    비밀댓글입니다
  1. 안녕하세요. 아스키 코드값을 이용하면 됩니다. 리스트를 사용해도 되지만 그럴필요 없죠. 코드도 지져분해지고요.
    ord()함수와 chr()함수를 이용하면되는데,
    각각 문자를 아스키코드로, 아스키 코드를 문자로 변환해줍니다.
    형변환 주의해주시고 다음과 같이 해보세요.

    >>> def coord(x,y):
    return chr(65+x) + str(y+1);

    >>> coord(0,0)
    'A1'
    >>> coord(1,6)
    'B7'

    >>> def invertcoord(x):
    print ("(%d, %d)" % (ord(x[0])-65,int(x[1])-1))


    >>> invertcoord("B7";)
    (1, 6)
      • 2015.11.05 22:57
      비밀댓글입니다
  2. 블로거에게는 댓글과 질문이 힘이됩니다. 그런말씀 마세요. 언제나 환영입니다. ^^
    • 익명
    • 2015.11.06 14:37
    비밀댓글입니다
    • 안녕하세요. isbn 문제라고 하면 제가 모릅니다. ^^;; 어떤기능을 하는 함수를 만들고 싶으신지 정확히 설명해주세요. 그리고 어떤 출력결과를 원하는지도 알려주셔야 ;; (주어진 함수가 무엇을 목적으로 함수인지 파악이 안되네요.)
    • 익명
    • 2015.11.06 19:03
    비밀댓글입니다
    • sISBN의 함수가 어떤 기능을 하는지 파악이 안되네요. 단순히 수식을 계산하는 건지요?
      string의 개수에 따라서 범용적인 함수를 만드는 건지 아니면 위에서 말한 문자가 10개인 경우와 13개인 경우만 만들면 되는건지? 10개인 경우와 13개인 경우 수식이 다르네요. 수식이 어떤의미가 있는지요?
      x13=(10−(x1+x3+x5+x7+x9+x11+3(x2+x4+x6+x8+x10+x12))%10)%10
      이 식은 무엇을 의미하나요?
      질문의 요지가 string의 문자열의 길이가 13인 경우
      x13=(10−(x1+x3+x5+x7+x9+x11+3(x2+x4+x6+x8+x10+x12))%10)%10 이식을
      문자열의 길이가 10개인 경우
      (1*a+2*b+3*c+4*d+5*e+6*f+7*g+8*h+9*i)%11):
      이식을 처리하는 건지요?
      이런 경우 if문으로 len(x)==10
      ...
      elif len(x) == 13
      ...
      이렇게 처리하시면 될거 같은데.
      잘 모르겠네요.10번은 더읽어봣는데 원래 문제가 뭔지를 모르겠네요.
    • 익명
    • 2015.11.06 21:44
    비밀댓글입니다
    • 우선 제가 이 문제를 다 보지 못해서 장담은 못드리겠습니다. 제가 이해한 바로는 x1 부터 x13까지는 각각 ISBN-1부터 ISBN-13까지 의 함수 각각으로 부터 얻어지는 것 같습니다. 맞죠? 그리고 ISBN-1이 TRUE여야 ISBN-2함수가 실행되고 False면 끝나네요. 이렇게 연쇄적으로 ISBN-13까지 실행되는 것이구요.
      code는 각 결과들을 시퀀스자료형으로 이어진 것이고 마지막 요소는 비교값이네요.(이건 패리티 비트 검사 처럼 자료의 마지막 값과 식의 결과를 비교하는 형식 같은데요)

      아무튼 솔루션을 보니 code는 외부 변수로 되어있고, ISBN-10 함수 내부에서 code[9]에 x10= x1+2x2+3x3+4x4+5x5+6x6+7x7+8x8+9x9)%11 의 결과를 대입하는 로직이 있어야하지 않나요? 그럼 해결될듯 한데.

      제가 이해한 바로는 이렇습니다.