Chapter 10 Object Oriented Programming
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import math # 用math.mathfunction:non vectorized function
from numpy.random import default_rng
# 8.8 randon number generator
g_rv = default_rng() # to initiate a generator object
from scipy.linalg import inv, solve, det, eig
Class and instance
Attributes
Instance method and static method
10.1 Basic concept
想定義「黃色方形」物件類別:
這類物件有什麼共通屬性:黃色
各別物件有什麼基本屬性:height, width, center.
對它有什麼想運用的操作:算它的面積
class YellowRectangle:
""" A Python object that describes the properties of a yellow rectangle """
color="yellow"
def __init__(self, width, height):
self.width = width
self.height = height
def __repr__(self):
return "Rectangle(width={w}, height={h})".format(h=self.height, w=self.width)
def compute_area(self):
return self.width * self.height
10.2 Class and Instance
判斷class或instance:
YR=YellowRectangle # YR is a class object
yr1=YR(5,10) # yr1 is an instance
yr2=YellowRectangle(1,3)
## True
## False
## True
## True
10.3 Class attributes and instance attributes
透過
def __init__(self,...)
定義的attribute為instance attributes.其他
def __init__(self,...)
以外定義的object都會成為class attributes.class attribute自然會是instance attribute
以下何者為class attr?何者為instance attr?
在一個父姓社會,定義linFamily這個class,每個instance是一個人:
所有的instance一定姓“林”:即
self.surname="林"
每個instance有自己的名:即
self.firstname
因人而異每個instance有自己的性別:即
self.gender
因人而異每個instance print時會顯示“我叫XXX, 性別Y”
10.4 Instance method
- Instance method:
def ...(self,...)
: 第一個arg為self.self
代表了instance本身。
An instance method is defined whenever a function definition is specified within the body of a class. This may seem trivial but there is still a significant nuance that must be cleared up, which is that ‘self’ is the defacto first-argument for any instance method.
When you call an instance method (e.g. func) from an instance object (e.g. inst), Python automatically passes that instance object as the first argument, in addition to any other arguments that were passed in by the user.
因此每個class body裡的def最好都加上
self
成第一個input。
在Basic concept範例裡,指出當中的instance method/static method。
class H5rectangle:
height=5 # 所有H5rectangle族群高都是5
def __init__(self,width): #旅群內的寬每個人都不同,有自己self的寬
self.width=width
def area(self): # 每個人都可以用area method來算自己的面積
return self.width*self.height
延續linFamily class。
- 每個林家人有marry method,即
instance.marry(spouse)
。此method會增加instance.spouse
屬性。
child1=linFamily("小明","男")
wife=wife={"surname": "陳", "familyname": "小美", "gender": "女"}
child1.marry(wife)
child1.spouse
## {'surname': '陳', 'familyname': '小美', 'gender': '女'}
10.4.1 範例
抽出
Sample size: 100個觀測值
Model: 來自\(y=0.1x+0.33\epsilon\).
Distribution: 分配\(x\perp\epsilon,\ x,\epsilon\sim N(0,1)\)
產生一組樣本牽涉到以上3個元素。從OOP角度來看,「產生一組樣本」這類(class)的事,需要有Sample size, model, 及distribution三個屬性(attributes)來定義。
從OOP角度定義「產生一組來自\(y=0.1x+0.33\epsilon\)且\(x,y\)服從標準常態分配」這類的事:
- 屬性只有Sample size
from numpy.random import default_rng
class mySample:
g_rv=default_rng()
def __init__(self,sampleSize):
self.sampleSize=sampleSize
(self.x,self.e)=\
self.g_rv.standard_normal(
size=(2,self.sampleSize))
self.y=0.1*self.x+0.33*self.e
對於:
假設\(y=X\beta+\epsilon\),其中\(X,\epsilon\)為獨立標準常態分配隨機變數。若以\(f(X)=X\beta\)為預測模型去預測\(y\),並使用OLS來選\(\beta\)參數,其預測準確度會不會受不同真實\(\beta\)值影響
這類的事情,你需要的元素有:
beta, sample size:
data:
split data: training set, test set
fit: model fitting, 即estimation
predict
class linearRegression:
def __init__(self,beta_coefficients,sampleSize):
self.beta_coefficients=beta_coefficients
self.sampleSize=sampleSize
def dataGen(self):
beta_coefficients=self.beta_coefficients
sampleSize=self.sampleSize
g_rv=default_rng()
eX=g_rv.standard_normal(\
size=(1+beta_coefficients.shape[0],\
sampleSize)) # 產生1+numBeta x sampleSize的rv matrix
e=eX[0,:]
X=eX[1:,:]
beta=beta_coefficients.reshape(
1,beta_coefficients.shape[0])
y=beta@X+e
self.data=(y,X)
def split(self,testSize):
(y,X)=self.data
sampleSize=y.shape[1]
index=np.arange(sampleSize)
np.random.shuffle(index)
cutOff=round(testSize*sampleSize)
testIndex=index[:cutOff]
trainIndex=index[cutOff:]
y_test=y[:,testIndex]
y_train=y[:,trainIndex]
X_test=X[:,testIndex]
X_train=X[:,trainIndex]
test_data=(y_test,X_test)
train_data=(y_train,X_train)
self.testSize=testSize
self.test_data=test_data
self.train_data=train_data
請完成fit及predict method
10.5 class method
cls
as the first argumentdeclare
@classmethod
class Flower:
collection=dict({})
def __init__(self, name, petal_width):
self.name=name
self.petal_width=petal_width
self.__class__.collection[name]=petal_width
@classmethod
def totalcollection(cls):
return len(cls.collection)
## {'iris': 5, 'tulips': 7}
## 2
10.6 Static method
- static method:
def ...(....)
: 沒有用self(或cls,以後會講class method)在arg裡。
A static method is simply a method whose arguments must all be passed explicitly by the user. That is, Python doesn’t pass anything to a static method automatically.
A static method is simply a method whose arguments must all be passed explicitly by the user. That is, Python doesn’t pass anything to a static method automatically. The built-in decorator @staticmethod
is used to distinguish a method as being static rather than an instance method.
10.7 Some tricks
10.7.1 Add/modify an attribute of an instance
You can add or modify an attribute to an instance via:
instance.variable = value
Example
為instance新增或修改的attribute不會增加或修改到其他instance。
10.7.2 Add/modify an attribute of a class
inst1=Example()
inst2=Example(2)
inst1.v0
inst2.v0
Example.v0=0 # 修改class的attribute
inst1.v0
inst2.v0
inst1.v0=2 # 修改instance的attribute
inst1.v0
inst2.v0
你可以為class事後加attribute(含method),但很難為instance事後加method: