시리즈 이전글입니다.
2021/01/31 - [파이썬/주식 자동매매] - Python 키움API 자동매매프로그램 개발-22.Python 기초편 클래스(1) 들여쓰기, 인스턴스화
04.self의 등장
robot1이라는 객체를 만들어 fly 함수를 사용해보았습니다.
그런데 잘 살펴보면 이상한 점이 있습니다.
class Robot:
def move(self, direction):
print("{}쪽으로 움직입니다.".format(direction))
def fly(self):
print("날아갑니다.")
fly함수를 호출하는 robot1.fly() 코드에는 함수의 매개변수인 self를 전달하지 않고 사용했지만 아무 문제가 되지 않았습니다.
그게 가능했던 이유는 self가 우리가 전달해야하는 단순한 매개변수가 아니라 클래스 내에 존재하는 함수라는 반드시 첫번째로 선언해야 하는 변수이기 때문입니다.
또 함수를 사용할 때는 Python 내에서 자동으로 self를 전달하기에 프로그래머가 따로 할일이 있지 않았습니다.
따라서 fly 함수를 호출할 때는 self가 자동으로 전달되니 따로 전달해야하는 매개변수 없이 다음처럼 사용이 가능했습니다.
robot1.fly()
하지만 move 함수는 self를 제외한 direction이라는 사용자 매개변수를 선언했으므로 사용할 때 전달되어야 하는 값입니다.
robot1.move("Left")
05.self의 의미
클래스 내부에 함수들은 모두 self라는 매개변수를 제일 첫번째로 선언해야 하고
객체를 이용해 함수를 호출할 때는 또 자동으로 전달되니 신경 쓸 것이 없다고 하지만 설명은 없고 그저 이렇게 해라는 식인 것 같아 답답하실 수 있을 것입니다.
self에 대해 간략하게 설명드리면 self란 클래스의 인스턴스를 가리키는 변수입니다.
무슨 말인지 더 헤깔리실테니 조금의 배경설명을 해보겠습니다.
먼저 동일한 클래스를 통해 만든 두 변수 robot1과 robot2을 만들어 보겠습니다.
robot1 = Robot()
robot2 = Robot()
print(id(robot1))
print(id(robot2))
여기서 robot1과 robott2는 같은 클래스로 생성됐다는 점에서 서로 연관이 있을 것 같아 보이지만 서로 아무 관계가 없는 별개의 객체입니다.
우리가 변수를 만들게 되면 변수마다 컴퓨터 내에 고유한 메모리 주소에 저장됩니다.
즉 변수마다 저장되는 자신만의 메모리가 있고 메모리에는 주소가 있습니다.
이 주소를 확인하는 id()라는 함수를 사용하면 변수가 저장된 주소를 알 수 있습니다.
print(id(robot1)) # 22174352
print(id(robot2)) # 24370128
출력해보면 서로 다른 값이 나오며 둘은 서로 다른 변수라는 것을 의미합니다.
(실행시마다 할당 주소가 달라지므로 값이 계속 변경됩니다.)
클래스를 통해 생성되는 객체끼리는 서로 상관이 없다는 것을 이해하셨다면
다음으로 클래스를 조금 변형해 예를 들어 보겠습니다.
class Robot:
def move(self, direction):
print("{}쪽으로 움직입니다.".format(direction))
def move_left(self):
self.move("Left")
def fly(self):
print("날아갑니다.")
move_left 라는 함수는 같은 클래스 내에 move 함수를 이용하는데 self라는 키워드를 이용해서 move를 호출하고 있습니다.
그러면 여기서 move를 호출할 때 self가 붙는 이유가 뭘까요?
그건 클래스를 통해 생성되는 객체가 다 다르기 때문입니다.
만약 robot1에서 move_left를 호출한다면 self.move(“Left”) 즉 robot1.move(“Left”)가 호출될 것이고 robot2에서 move_left를 호출한다면 self.move(“Left”), robot2.move(“Left”)가 호출될 것입니다.
결국 self는 클래스를 통해 생성될 객체 자신을 가리키는 이름 그대로의 의미를 가지고 있습니다.
이해가 덜 되셨거나 이 설명으로 더 혼란스러우신 분은 self는 그냥 객체 자기 자신이다.
클래스에서 사용하는 변수, 함수에는 self를 이용한 접근이 필요하다고 간단히 생각해주시길 바랍니다.
덧붙여 제 개인 블로그에 self의 의미에 대해서 적은 글이 있으니 더 궁금하신 분들은
이 글을 참고해 주시길 바랍니다.
06.__init__
클래스는 객체화 되는 순간에 호출되는 초기화 함수가 있습니다.
예를 들어 다음처럼 robot1이 만들어질 때 초기화 함수가 호출되며 이 함수를 생성자(Constructor)라고도 합니다.
robot1 = Robot()
하지만 우리가 실행되는 과정을 확인할 수 없었던 이유는 초기화 함수에서 수행하는 것을 따로 만들지 않았기 때문입니다.
초기화 함수를 만드는 방법은 다음처럼 클래스에 __init__ 이라는 함수를 만듭니다.
주의하셔야할 것은 앞뒤로 언더스코프(_)가 두 개씩, 총 4개가 있습니다.
class Robot:
def __init__(self):
print("robot 객체가 만들어집니다.")
def move(self, direction):
print("{}쪽으로 움직입니다.".format(direction))
def move_left(self):
self.move("Left")
def fly(self):
print("날아갑니다.")
이제 초기화 함수를 만들어두었으니 초기화 함수가 잘 실행되는지 확인해보겠습니다.
robot1 = Robot()
객체가 생성되는 순간에 다음처럼 __init__ 함수 안에 코드가 실행됩니다.
robot 객체가 만들어집니다.
여기서 알 수 있는 사실은 __init__ 함수는 클래스 내에 만들어두면 따로 호출을 하지 않아도 자동으로 실행된다는 것입니다.
또 한가지 __init__의 중요한 역할은 객체 생성시 변수를 입력 받을 수 있도록 설정할 수 있습니다.
지금까지는 따로 초기화 함수를 만들지 않았어서 다음처럼 아무 값도 전달하지 않아도
객체를 생성할 수 있었습니다.
robot1 = Robot()
하지만 다음처럼 초기화 함수를 만들 때 name이라는 변수를 입력받도록 한다면
class Robot:
def __init__(self, name):
print("robot 객체 {}이(가) 만들어집니다.".format(name))
객체를 생성할 때 name으로 사용할 값을 전달해야 객체를 생성할 수 있습니다.
robot1 = Robot("첫로봇")
하지만 객체 생성시 name을 입력받기로 해놓고 전달하지 않으면 에러가 발생합니다.
robot1 = Robot()
# TypeError: __init__() missing 1 required positional argument: 'name'
name을 입력받기로 했지만 그렇다고 항상 전달해야 하는 것은 아닙니다.
함수를 배울 때 매개변수 기본값을 설정할 수 있었듯이 name을 필수적으로 전달하지 않아도 되게 만들 수 있습니다.
class Robot:
def __init__(self, name="로봇"):
print("robot 객체 {}(가) 만들어집니다.".format(name))
같이 보시면 좋을 글
2021/02/10 - [파이썬/주식 자동매매] - 주식매매프로그램 개발 노하우, 소스를 담은 전자책이 발간되었습니다.
2021/02/02 - [파이썬/주식 자동매매] - Python 키움API 자동매매프로그램 개발-24.Python 기초편 클래스(3) 속성, 인스턴스 확인
'파이썬 > 주식 자동매매' 카테고리의 다른 글
Python 키움API 자동매매프로그램 개발-25.Python 기초편 클래스(4) 상속 (0) | 2021.02.03 |
---|---|
Python 키움API 자동매매프로그램 개발-24.Python 기초편 클래스(3) 속성, 인스턴스 확인 (0) | 2021.02.02 |
Python 키움API 자동매매프로그램 개발-22.Python 기초편 클래스(1) 들여쓰기, 인스턴스화 (0) | 2021.01.31 |
Python 키움API 자동매매프로그램 개발-21.Python 기초편 함수(4)매개변수, 호출순서 (0) | 2021.01.31 |
Python 키움API 자동매매프로그램 개발-20.Python 기초편 함수(3)유효범위 (2) | 2021.01.29 |
댓글