# 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
1. Class and instance

2. Attributes

3. 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

YR=YellowRectangle # YR is a class object
yr1=YR(5,10) # yr1 is an instance
yr2=YellowRectangle(1,3)
YR is YellowRectangle # is: 判斷是否為某class object
## True
isinstance(YR,YellowRectangle) # isinstance: 判斷是否為某class下的instance
## False
isinstance(yr1,YellowRectangle)
## True
isinstance(yr2,YR)
## True

## 10.3 Class attributes and instance attributes

• 透過def __init__(self,...)定義的attribute為instance attributes.

• 其他def __init__(self,...)以外定義的object都會成為class attributes.

class attribute自然會是instance attribute

yr1.color
yr1.height
yr1.width

• 所有的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.

# instance method
def functionName(self,...): 

class H5rectangle:
height=5 # 所有H5rectangle族群高都是5
def __init__(self,width): #旅群內的寬每個人都不同，有自己self的寬
self.width=width
def area(self): # 每個人都可以用area method來算自己的面積
return self.width*self.height

• 每個林家人有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)$$

• 屬性只有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

• 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
beta_coefficients = np.array(
[0.2,0.3,-1.8]
)
sampleSize=500
lr1=linearRegression(beta_coefficients,sampleSize) # 創新instance
lr1.dataGen() # 使用dataGen instance method給予此instance data attribute
lr1.split(0.3)

## 10.5 class method

• cls as the first argument

• declare @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)
fl1=Flower("iris",5)
fl2=Flower("tulips",7)
Flower.collection
## {'iris': 5, 'tulips': 7}
Flower.totalcollection()
## 2
def gradient():
return ...

def optimization():
return ...


## 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.

@staticmethod
def functionName(...):
class Dummy:

@staticmethod
def static_func():
""" A static method defined to always returns
the string 'hi'"""
return 'hi'
inst=Dummy()
inst.static_func()

## 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

class Example:
v0=2
def __init__(self,v1=0):
self.v1=v1
inst1=Example()
inst2=Example(2)
inst1.v1
inst1.v1=4
inst1.v1

inst1.v3=5
inst1.v3

inst2.v3

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
def m0(self):
return self.v0+self.v1

Example.m0=m0

inst1.m0()
inst2.m0()

inst1.m1=m0
inst1.m1()