- Published on
[Python] 파이썬의 def 오버로딩에 대해
- Authors
- Name
- Almer Minified
[Python] 파이썬의 def 오버로딩에 대해
파이썬의 def 오버로딩에 대해 알아보기
같은 이름의 함수가 오버로드되면 파이썬은 특정 오류 메시지를 표시하지 않고 마지막으로 정의된 함수 이름에 따라 마음대로 처리한다. 예를 들어보면
def init_function():
print('init_function')
def init_function(arg=5):
print('init_function:',arg)
init_function()
init_function(1)
이 경우에
>>> init_function: 5
init_function: 1
위의 경우, 나중에 정의하는 init_function(arg=5) 함수가 호출되어 연산을 수행했다. 그래서 다음처럼 순서를 바꿔보자.
def init_function(arg=5):
print('init_function:', arg)
def init_function():
print('init_function')
init_function() # 일반 호출
init_function(1) # 오류 발생
이렇게하면 트레이스백이 발생할 것이다.
>>> TypeError: init_function() takes 0 positional arguments but 1 was given
나중에 정의된 "init_function()"를 유효한 함수로 간주하기 떄문에 "init_function(1)"을 호출할 때 예외가 발생하는 것이다. 이런 규칙은 instance나 static 함수에도 적용된다. 예를 들어 다음과 유사한 instance나 static 함수를 정의해보자
class MyType(object): @staticmethod def init_function(arg): # 같은 이름의 함수가 뒤에 정의되었으므로 이건 무시된다
print('static init_function')
def init_function(self, arg): # 이게 실질적으로 작동하는 함수이다
print('instance init_function:', arg)
get_type = MyType()
get_type.init_function(6) # 성공적으로 인스턴스 함수를 호출할 것이다
MyType.init_function(5) # 스태틱 함수는 무시되었으므로 제대로 호출되지 않는다
이제 어떻게 되는 것인지 알겠는가?
class MyType(object):
def init_function(self, arg): # 작동안함
print('instance init_function:', arg)
@staticmethod def init_function(arg): # 이게 작동한다
print('static init_function')
get_type = MyType()
get_type.init_function(6) # 스태틱 함수 실행
MyType.init_function(5) # 스태틱 함수 실행
이러면 에러는 발생하지 않는다 둘다 staticmethod를 호출하기 때문이다. 근데 파이썬의 내재적인 관점에서 보면 클래스 내에서 instance나 static 함수는 아무런 차이가 없다. 정적 함수에 붙여진 데코레이터 @staticmethod는 임의로 만든 데코레이터 클래스에 불과하다. 더 근본적으로 파이썬은 모든 형을 딕셔너리 데이터형으로 취급한다. 그래서 결국 키/값일 뿐입니다. 따라서 다음과 같이 하면,
def name_test():
print('name_test')
async def name_test(arg):
print('name_test async def',arg)
item = None
func = None
for item in globals().keys():
func = globals()[item].isinstance(func, types.FunctionType) is False:
continue print(func)
>>> function name_test 함수의 위치
파이썬 딕셔너리의 키도 str이다. 그래서 함수 이름만 포함하고 있고, 기술적으로는 "def name_test()"와 "async def name_test()"는 모두 "name_test" 키를 사용하기 떄문에 구별할 방법이 없게 된다. 또한 이 제한 때문에 같은 이름의 함수와 클래스를 정의할 수 없는 것이다.
def name_test(): # 나중에 정의된 같은 이름의 테스트 클래스가 있으므로 안쓰게 된다
print('name_test')
class name_test(object):
# 클래스 유형을 마지막으로 정의된 "name_test" 키의 값으로 정의하게 된다 나중에 정의됐으므로.
pass
v = name_test()
# 함수를 호출하는게 클래스 인스턴스를 생성하는 것과 동일한 구문을 가진다.
# "name_test"라는 이름의 마지막 정의가 클래스였다. 그러므로
# 클래스 객체를 생성한다.
print(v)
>>> [파일명].name_test 오브젝트 at 함수위치 # 이게 출력 결과이다.
결국 파이썬의 __dict__에는 전역 변수, 함수, 클래스 및 포함된 import 모듈에 대한 정보가 포함되어 있다. 게다가 이 모든 것이 "name" 키 아래에 등록되어 있으므로 마지막으로 정의한 것만 사용되게 된다.
init_function = 'name_test' # 변수가 유효하지 않음: init_function 함수가 나중에 정의되었기 때문.
def init_function(): # 유효: 이전 init_function 변수를 재정의.
print('do-func') module =
importlib.import_module(__name__) item = None for
module.__dict__.keys() if item == 'init_function': print(item,
module.__dict__[item])
>>> init_function 함수 init_function at 위치