(13주차) 5월25일
클래스 공부 5단계
-
(1/4) __add__
(1)
-
(2/4) __add__
(2)
-
(3/4) __add__
(3)
-
(4/4) __mul__
import numpy as np
-
지난시간까지 배운것: RPS자료형에 한정해서 print()등의 기능을 조작할 수 있었다. (재정의 할 수 있었다)
-
이번시간에 배울것: 특정자료형에 한정하여 print 이외의 파이썬 내부기능을 조작하여 보자. (재정의하여 보자)
-
아래의 연산구조를 관찰하자.
a=1
b=2
a+b
- a라는 인스턴스와 b라는 인스턴스를 +라는 기호가 연결하고 있다.
-
이번에는 아래의 연산구조를 관찰하자.
a=[1,2]
b=[3,4]
a+b
- a라는 인스턴스와 b라는 인스턴스를 +라는 기호가 연결하고 있다.
-
동작이 다른 이유?
- 클래스를 배우기 이전: int자료형의
+
는 "정수의 덧셈"을 의미하고 list자료형의+
는 "자료의 추가"를 의미한다. - 클래스를 배운 이후: 아마 클래스는
+
라는 연산을 정의하는 숨겨진 메소드가 있을것이다. (print가 그랬듯이) 그리고 int클래스에서는 그 메소드를 "정수의 덧셈"이 되도록 정의하였고 list클래스에서는 그 메소드를 "자료의 추가"를 의미하도록 정의하였다.
-
아래의 결과를 관찰
a=1
b=2
a.__add__(b)
b.__add__(a)
a=[1,2]
b=[3,4]
a.__add__(b)
b.__add__(a)
-
a+b는 사실 내부적으로 a.__add__(b)
의 축약구문이다. 따라서 만약 a.__add__(b)
의 기능을 바꾸면 (재정의하면) a+b의 기능도 바뀔 것이다.
-
학생예제
class Student:
def __init__(self,age=20.0, semester=0):
self.age = age
self.semester = semester
print("입학을 축하합니다. 당신의 나이는 {}이고 현재 학기는 {}학기 입니다.".format(self.age,self.semester))
def __add__(self,val):
# val == 0: 휴학
# val == 1: 등록
if val==0:
self.age=self.age+0.5
elif val==1:
self.age=self.age+0.5
self.semester= self.semester+1
def _repr_html_(self):
html_str = """
나이: {} <br/>
학기: {} <br/>
"""
return html_str.format(self.age,self.semester)
iu= Student()
iu
iu + 1 ## 1학년 1학기 등록
iu
iu + 0 ## 휴학함
iu
-
연산을 연속으로 하고 싶다.
iu + 1 + 0 + 0 + 0 + 0
-
에러의 이유?
(되는코드)
(1+1)+1 # 1+1+1은 이렇게 볼 수 있다
_a = (1+1)
type(_a)
_a+1 # 이 연산은 int인스턴스 + int인스턴스
(안되는코드)
iu+1+1
_a=iu+1
type(_a)
_a+1
-
에러를 해결하는 방법: iu+1의 결과로 Student클래스의 인스턴스가 리턴되면 된다.
class Student:
def __init__(self,age=20.0, semester=0):
self.age = age
self.semester = semester
print("입학을 축하합니다. 당신의 나이는 {}이고 현재 학기는 {}학기 입니다.".format(self.age,self.semester))
def __add__(self,val):
# val == 0: 휴학
# val == 1: 등록
if val==0:
self.age=self.age+0.5
elif val==1:
self.age=self.age+0.5
self.semester= self.semester+1
return self
def _repr_html_(self):
html_str = """
나이: {} <br/>
학기: {} <br/>
"""
return html_str.format(self.age,self.semester)
iu = Student()
iu+1 # __add__의 return에 Student클래스의 인스턴스가 리턴되면서 자동으로 _repr_html_() 실행
iu+1 +0+0+0+0
class RPS:
def __init__(self,candidate=['가위','바위','보']):
self.candidate = candidate
self.actions = list()
self.results = list()
def __mul__(self,other):
self.choose()
other.choose()
if self.actions[-1]=='가위' and other.actions[-1]=='가위':
self.results.append(0)
other.results.append(0)
if self.actions[-1]=='가위' and other.actions[-1]=='바위':
self.results.append(-1)
other.results.append(1)
if self.actions[-1]=='가위' and other.actions[-1]=='보':
self.results.append(1)
other.results.append(-1)
if self.actions[-1]=='바위' and other.actions[-1]=='가위':
self.results.append(1)
other.results.append(-1)
if self.actions[-1]=='바위' and other.actions[-1]=='바위':
self.results.append(0)
other.results.append(0)
if self.actions[-1]=='바위' and other.actions[-1]=='보':
self.results.append(-1)
other.results.append(1)
if self.actions[-1]=='보' and other.actions[-1]=='가위':
self.results.append(-1)
other.results.append(1)
if self.actions[-1]=='보' and other.actions[-1]=='바위':
self.results.append(1)
other.results.append(-1)
if self.actions[-1]=='보' and other.actions[-1]=='보':
self.results.append(0)
other.results.append(0)
def choose(self):
self.actions.append(np.random.choice(self.candidate))
def _repr_html_(self):
html_str = """
낼 수 있는 패: {} <br/>
액션: {} <br/>
승패: {}
"""
return html_str.format(self.candidate,self.actions,self.results)
a=RPS()
b=RPS()
a
b
a*b
a
b
for i in range(5):
a*b
a
b
for i in range(50000):
a*b
sum(a.results)/len(a.results)
sum(b.results)/len(a.results)
RPS클래스에서 player a와 player b를 만들어라. Player a는 ['가위','보'] 중에 하나를 낼 수 있다. 그리고 Player b는 ['가위','바위'] 중에 하나를 낼 수 있다. 두 player는 가지고 있는 패를 (같은확률로) 랜덤으로 낸다. (즉 player a가 가위만 내거나 보만 내는 경우는 없다.)
(1) 누가 더 유리한가? 이유를 스스로 생각해보라. (이유를 정리하여 숙제로 제출할 필요 없음)
(2) 50000번의 시뮬레이션을 해보고 결과를 분석해보라.