성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 제가 큰 실수를 했군요. ^^; Delegate를 통한 Bein...
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>파이썬 - 함수 오버로딩 미지원</h1> <p> 파이썬은 (같은 이름의) 동일한 함수가 재정의(overload)된 경우 딱히 오류 메시지 없이 마지막에 정의한 함수 이름을 기준으로 처리합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > def do_func(): print('do_func') def do_func(arg=5): print('do_func:', arg) do_func() do_func(1) """ 출력 결과 do_func: 5 do_func: 1 """ </pre> <br /> 위의 경우, 나중에 정의한 do_func(arg=5) 함수가 호출돼 동작을 한 건데요, 따라서 다음과 같이 순서를 바꾸는 경우에는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > def do_func(arg=5): print('do_func:', arg) def do_func(): print('do_func') do_func() # 정상 호출 do_func(1) # 오류 발생 """ Traceback (most recent call last): File "/work/test.py", line 11, in <module> do_func(1) TypeError: do_func() takes 0 positional arguments but 1 was given """ </pre> <br /> 나중에 정의한 "do_func()"를 유효한 함수로 처리하므로 "do_func(1)"로 호출했을 때 예외가 발생한 것입니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이런 규칙은 instance/static 함수에도 적용됩니다. 가령 다음과 같이 동일한 이름을 정의하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class MyType(object): @staticmethod def do_func(arg): # 이후 동일한 이름의 함수가 정의되므로 무효 print('static do_func') def do_func(self, arg): # 유효 print('instance do_func:', arg) inst = MyType() inst.do_func(6) # 인스턴스 함수 호출 성공 MyType.do_func(5) # [타입].[함수] 형식으로 호출하면 "self"를 전달하지 않으므로, # 전달한 "5" 값이 인스턴스 함수의 self에 매칭되고, 결국 argument 불일치로 에러 발생 - TypeError: MyType.do_func() missing 1 required positional argument: 'arg' </pre> <br /> 오류가 발생합니다. 반면 이렇게 정의하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > class MyType(object): def do_func(self, arg): # 무효 print('instance do_func:', arg) @staticmethod def do_func(arg): # 유효 print('static do_func') inst = MyType() inst.do_func(6) # 정적 함수 실행 MyType.do_func(5) # 정적 함수 실행 """ 출력 결과 static do_func static do_func """ </pre> <br /> 오류는 발생하지 않지만 정적 함수가 호출되는 것이므로 자칫 인스턴스 함수가 정상 실행된 경우로 착각해 프로그램에 버그가 발생할 수 있습니다.<br /> <br /> 사실, 파이썬 입장에서는 class의 instance/static 함수에 대한 구분이 없습니다. 실제로 static 함수라고 표시하는 @staticmethod는 임의로 만들어진 decorator 클래스에 불과합니다. 게다가 더욱 근본적인 문제는, 파이썬은 모든 형식이 key/value에 불과한 dictionary 자료형으로 처리한다는 점입니다.<br /> <br /> 따라서 다음과 같은 식으로 코드를 수행하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > import types def test(): print('test') async def test(arg): print('test-async', arg) item = None func = None for item in globals().keys(): func = globals()[item] if isinstance(func, types.FunctionType) is False: continue print(func) """ 출력 결과 test <function test at 0x7fe7303fdc60> """ </pre> <br /> 화면에는 "test" 라인 하나만 출력되는 것을 확인할 수 있습니다. dictionary의 키 자체도 함수의 이름만 담고 있는 "str" 타입이어서 엄밀히 "def test()"와 "async def test()"가 모두 "test" 키를 공유하기 때문에 구분할 방법이 없는 것입니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이러한 제약은 동일한 이름의 함수와 클래스를 정의하는 것도 막게 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > def test(): # 이후에 정의한 같은 이름의 test 클래스로 인해 무효 print('test') class test(object): # 마지막에 정의한 "test" 키의 값으로 class 타입 정의 pass v = test() # 함수 호출과 클래스 인스턴스 생성의 구문이 동일 # "test"라는 이름으로 마지막에 정의한 것이 class이므로 클래스의 개체 생성 print(v) # 출력 결과 <[파일이름].test object at 0x7ff7d86816d0> </pre> <br /> 클래스 역시 module에 등록하는 키 값은 str 타입의 클래스 이름이기 때문에 기존의 함수를 덮어쓰는 것입니다. 이쯤 되면 눈치채셨겠지만, module의 __dict__에는 전역 변수, 함수, 클래스, 그 모듈에서 포함한 (import) 모듈 정보들이 모두 '이름' 키로 등록되기 때문에 그 모든 것들이 가장 나중에 정의한 것만 유효하게 됩니다.<br /> <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > import importlib do_func = 'test' # 변수 무효: 이후 do_func 함수가 정의되므로. def do_func(): # 유효: 이전의 do_func 변수를 덮어씀. print('do-func') module = importlib.import_module(__name__) item = None for item in module.__dict__.keys(): if item == 'do_func': print(item, module.__dict__[item]) """ 출력 결과 do_func <function do_func at 0x7f00ba8ef100> """ </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
7326
(왼쪽의 숫자를 입력해야 합니다.)