{
    "componentChunkName": "component---src-templates-blog-post-js",
    "path": "/19-12-08-namespace-and-scope/",
    "result": {"data":{"site":{"siteMetadata":{"title":"irrationnelle","author":"irrationnelle","siteUrl":"https://dev.rase.blog","comment":{"disqusShortName":"","utterances":"irrationnelle/devlog"},"sponsor":{"buyMeACoffeeId":""}}},"markdownRemark":{"id":"9d3389b3-1673-578c-a68c-b8e252cae170","excerpt":"…","html":"<p>원래는 <code class=\"language-text\">return</code> 의 사용목적에 대해서 쓰고 있었으나 내용이 길어지고 여러가지 개념들이 혼재되는 것 같아서</p>\n<p>네임스페이스 부분을 잘라내어 따로 포스팅한다.</p>\n<p><code class=\"language-text\">return</code> 에 대한 언급이 간간히 나오는데 수정하지 않고 냅둔 것은,</p>\n<p><code class=\"language-text\">return</code> 의 사용에 대해 어렴풋이 느끼고 생각해볼 수 있는 기회라고 여겨서이다.</p>\n<h1 id=\"네임스페이스-이해하\" style=\"position:relative;\"><a href=\"#%EB%84%A4%EC%9E%84%EC%8A%A4%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%9D%B4%ED%95%B4%ED%95%98\" aria-label=\"네임스페이스 이해하 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>네임스페이스 이해하</h1>\n<p>의자 바꾸기 함수에는 <code class=\"language-text\">return</code> 이 없었다. 하지만 함수를 호출하고 나면 의자가 바뀐 것을 알 수 있었다.</p>\n<p>여기서 알 수 있는 점은 <code class=\"language-text\">return</code> 문을 사용하지 않아도 <em>함수 바깥의 값을 변하게 할 수 있다</em> 는 것이다.</p>\n<p>게다가 <em>더 충격적인 것은</em> 사실 인자를 전달하지 않더라도</p>\n<p>함수 외부의 값을 접근하여 값을 수정하는 것이 가능한 경우도 있다.</p>\n<p>다음 코드를 보자.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">add_five</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    result <span class=\"token operator\">=</span> num <span class=\"token operator\">+</span> <span class=\"token number\">5</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span>\n\nadd_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>아마 <code class=\"language-text\">num 을 정의하지 않았습니다</code> 등의 에러를 예상할지 모르지만, 위의 코드를 실행하면 <code class=\"language-text\">15</code> 라는 값이 나온다.</p>\n<blockquote>\n<p>분명 함수 내부와 함수 바깥은 스코프가 다르기 때문에 서로 다른 변수라고 했었는데?</p>\n</blockquote>\n<p>이제 네임스페이스라는 개념을 이해할 때가 왔다.</p>\n<p>위의 코드를 조금 변경해서 다음과 같은 코드가 있다고 하자</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">add_five</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    result <span class=\"token operator\">=</span> num <span class=\"token operator\">+</span> <span class=\"token number\">5</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span>\n\nadd_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>이 코드를 실행하면 이번에는 <code class=\"language-text\">num</code> 매개변수에 인자 전달을 하지 않았다면서</p>\n<p>이 함수에는 1개의 인자를 필요로 한다는 에러가 뜬다.</p>\n<p>그래서 인자를 던져주자</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">add_five</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    result <span class=\"token operator\">=</span> num <span class=\"token operator\">+</span> <span class=\"token number\">5</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span>\n\nadd_five<span class=\"token punctuation\">(</span><span class=\"token number\">20</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>이러면 당연히 <code class=\"language-text\">25</code> 가 나온다. <code class=\"language-text\">num</code> 은 10 이기도 하고 20 이기도 한걸까?</p>\n<p>일단 이런 의문을 가진 채 이번에는 함수 바깥에 있는 변수값을 수정하는 코드를 보자</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">to_be_five</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    num <span class=\"token operator\">=</span> <span class=\"token number\">5</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span>\n\nto_be_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span></code></pre></div>\n<p>결과를 예측해보자.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token number\">5</span>\n<span class=\"token number\">10</span></code></pre></div>\n<p>이 경우 함수 정의에서 매개변수의 이름으로 <code class=\"language-text\">num</code> 을 지어주지 않았어도,</p>\n<p>함수 내부에서 사용하는 <code class=\"language-text\">num</code> 은 함수 외부에서 사용하는 <code class=\"language-text\">num</code> 과 다른 것으로 간주한다.</p>\n<p>이를 두고 함수 내부의 <code class=\"language-text\">num</code> 은 로컬(local) 네임스페이스를 가진다고 하고,</p>\n<p>함수 바깥의 <code class=\"language-text\">num</code> 은 글로벌(global) 네임스페이스를 가진다고 한다. 참고사항으로 한가지 알아둘 것은 함수 바깥에 또 함수가 있는 것이 아닌 코드 실행 최상단이기 때문에 글로벌이라고 한다는 점이다.</p>\n<p>이와 같이 여기서는 우리가 기존에 알고 있듯 함수 내부의 스코프와 함수 바깥의 스코프가 다르게 작동한다.</p>\n<p>하지만 위와 비슷하지만 다르게 작동하는 코드를 보자.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">to_be_five</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span> <span class=\"token comment\"># 딱 이부분만 추가되었다</span>\n    num <span class=\"token operator\">=</span> <span class=\"token number\">5</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span>\n\nto_be_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span></code></pre></div>\n<p>그럼 이번에는 다음과 같은 <em>에러</em>가 발생한다. 응? 어째서 에러?</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">Traceback <span class=\"token punctuation\">(</span>most recent call last<span class=\"token punctuation\">)</span>:\n  File <span class=\"token string\">\"test04.py\"</span>, line <span class=\"token number\">8</span>, <span class=\"token keyword\">in</span> <span class=\"token operator\">&lt;</span>module<span class=\"token operator\">></span>\n    to_be_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  File <span class=\"token string\">\"test04.py\"</span>, line <span class=\"token number\">4</span>, <span class=\"token keyword\">in</span> to_be_five\n    print<span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span> <span class=\"token comment\"># 딱 이부분만 추가되었다</span>\nUnboundLocalError: <span class=\"token builtin class-name\">local</span> variable <span class=\"token string\">'num'</span> referenced before assignment</code></pre></div>\n<p>바로 추가된 부분인 <code class=\"language-text\">print(num)</code> 이 문제이다. 앞서 봤던 코드 중 이런 게 있었다.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">add_five</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    result <span class=\"token operator\">=</span> num <span class=\"token operator\">+</span> <span class=\"token number\">5</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>result<span class=\"token punctuation\">)</span>\n\nadd_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>여기서 결과가 <code class=\"language-text\">15</code> 가 나온 것을 기억한다면</p>\n<p>함수 정의 때 함수 내부에 있는 <code class=\"language-text\">num</code> 은 함수 외부에 있는 <code class=\"language-text\">num</code> 을 가리키는 것을 알 수 있다.</p>\n<p>정확히는 <em>함수 정의 당시에 가장 가까운 위치의 네임스페이스를 가진 변수</em> 를 가리키는 것이지만</p>\n<p>어쨌든 함수 내부에 있는 <code class=\"language-text\">num</code> 은 함수 바깥의 그 녀석이다.</p>\n<p>그럼 다시 에러가 난 코드를 보자.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">to_be_five</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span> <span class=\"token comment\"># 딱 이부분만 추가되었다</span>\n    num <span class=\"token operator\">=</span> <span class=\"token number\">5</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span>\n\nto_be_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span></code></pre></div>\n<p>이 코드에서도 마찬가지인데, 함수 내부에서 <code class=\"language-text\">num</code> 을 선언하지 않았기 때문에</p>\n<p><code class=\"language-text\">print(num)</code> 을 호출하는 상황에서 <code class=\"language-text\">num</code> 은 글로벌 네임스페이스의 <code class=\"language-text\">num</code> 이게 된다.</p>\n<p>그런데 그 밑에서 <code class=\"language-text\">num</code> 을 수정하려고 한다. 아니다 말이 잘못 되었다. 수정이 아니라 <em>할당을 하려고 한다</em></p>\n<p>그래서 다음과 같이 에러를 말하는 것이다.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">UnboundLocalError: <span class=\"token builtin class-name\">local</span> variable <span class=\"token string\">'num'</span> referenced before assignment</code></pre></div>\n<p>로컬 네임스페이스의 변수인 <code class=\"language-text\">num</code> 은 할당 이전에 이미 참조된 값이라고.</p>\n<p>즉 로컬 네임스페이스의 변수로 <code class=\"language-text\">num</code> 을 <code class=\"language-text\">할당</code> 하려고 하는데, 이미 <code class=\"language-text\">num</code> 이라는 변수명이 글로벌 네임스페이스를 가지는 것이다.</p>\n<p>그래서 오해할 수도 있지만 이것은 글로벌 네임스페이스를 가진 변수 <code class=\"language-text\">num</code> 을 <em>수정하기 때문</em>이 아니라,</p>\n<p>로컬 네임스페이스를 가진 변수 <code class=\"language-text\">num</code> 으로 할당하려고 하기 때문에 발생하는 에러이다.</p>\n<p>여기서 알 수 있는 것은 두 가지이다.</p>\n<blockquote>\n<ol>\n<li>글로벌 네임스페이스를 가진 변수는 수정할 수 없다</li>\n<li>글로벌 네임스페이스를 가진 변수를 다시 또 로컬 네임스페이스에서 <code class=\"language-text\">할당</code> 하는 것은 불가능하다.</li>\n</ol>\n</blockquote>\n<h1 id=\"global-키워드\" style=\"position:relative;\"><a href=\"#global-%ED%82%A4%EC%9B%8C%EB%93%9C\" aria-label=\"global 키워드 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>global 키워드</h1>\n<p>엄밀히 말해 글로벌 네임스페이스를 가진 변수는 수정이 가능하다. 하지만 그런 방법은 파이썬에서 권장하는 방식이 아니며,</p>\n<p>보다 명확하고 직관적인 코드 이해를 위해서 파이썬은 글로벌 네임스페이스를 가진 변수를 수정할 수 있도록</p>\n<p><code class=\"language-text\">global</code> 키워드를 제공한다.</p>\n<p><code class=\"language-text\">global</code> 키워드를 사용하여 위의 코드는 아래와 같이 하면 에러없이 사용이 가능하다.</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">num <span class=\"token operator\">=</span> <span class=\"token number\">10</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">to_be_five</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">global</span> num <span class=\"token comment\"># num 네임스페이스가 글로벌 네임스페이스라는 것을 명시적으로 나타낸다</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span>\n    num <span class=\"token operator\">=</span> <span class=\"token number\">5</span> <span class=\"token comment\"># global 키워드를 통해 글로벌 네임스페이스의 num 이라는 것을 알고 할당이 아닌 재정의를 한다.</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span>\n\nto_be_five<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>num<span class=\"token punctuation\">)</span></code></pre></div>\n<p>추가적으로 <code class=\"language-text\">global</code> 키워드 뿐만 아니라 <code class=\"language-text\">nonlocal</code> 키워드도 사용이 가능하다. 두 키워드의 차이점은 공식문서를 살펴보자.</p>\n<p>하지만 이 방식은 파이썬에서 권장하는 방식이 아니다.</p>\n<p>매개변수로 전달한 인자도 아닐뿐더러, <code class=\"language-text\">return</code> 도 없는 함수이기 때문에</p>\n<p>대다수의 개발자들은 이 함수의 정의를 직접 살펴보고 어떤 값을 변화시키는지 확인해야 하기 때문이다.</p>\n<h1 id=\"마치며\" style=\"position:relative;\"><a href=\"#%EB%A7%88%EC%B9%98%EB%A9%B0\" aria-label=\"마치며 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>마치며</h1>\n<p>네임스페이스를 통해 함수가 함수 외부의 값에도 접근하어 값을 변경할 수 있다는 것을 알게 되었다.</p>\n<p>하지만 이 방법은 되도록 지양하는 것이 좋으며, 함수는 매개변수에 인자를 전달하고 <code class=\"language-text\">return</code> 으로 값을 반환하는 것이</p>\n<p>좀 더 바람직하다. 다음 포스팅에서는 왜 그러한지 알아보도록 하자.</p>","frontmatter":{"title":"네임스페이스와 함수","date":"December 08, 2019"}}},"pageContext":{"slug":"/19-12-08-namespace-and-scope/","previous":{"fields":{"slug":"/19-11-29-iimmutable-and-mutable2/"},"frontmatter":{"title":"의자 바꾸기로 생각하는 인자 전달","category":"Python","draft":false}},"next":{"fields":{"slug":"/19-12-09-why-use-return-statement/"},"frontmatter":{"title":"return 을 사용하는 이유","category":"Python","draft":false}}}},
    "staticQueryHashes": ["3128451518","3474900066"]}