# Lập trình Hướng đối tượng¶

## Lớp và thể hiện của lớp¶

In [1]:
class Coordinate(object):
def __init__(self, x, y):
self.x = x
self.y = y

In [2]:
c = Coordinate(3,4)
origin = Coordinate(0,0)

In [3]:
print(c.x)
print(origin.x)

3
0


## Hàm thành phần¶

In [4]:
class Coordinate(object):
def __init__(self, x, y):
self.x = x
self.y = y

def distance(self, other):
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5

In [5]:
c = Coordinate(3,4)
origin = Coordinate(0,0)
print(c.distance(origin))

5.0

In [6]:
print(Coordinate.distance(c, origin))

5.0

In [7]:
class Coordinate(object):
def __init__(self, x, y):
self.x = x
self.y = y

def distance(self, other):
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5

def __str__(self):
return "<" + str(self.x) + "," + str(self.y) + ">"

In [8]:
c = Coordinate(3,4)
print(c)

<3,4>


### check type of an object¶

In [9]:
print(isinstance(c, Coordinate))

True


### Nạp chồng toán tử¶

In [10]:
class Coordinate(object):
def __init__(self, x, y):
self.x = x
self.y = y

def distance(self, other):
x_diff_sq = (self.x-other.x)**2
y_diff_sq = (self.y-other.y)**2
return (x_diff_sq + y_diff_sq)**0.5

def __str__(self):
return "<" + str(self.x) + "," + str(self.y) + ">"

def __sub__(self, other):
return Coordinate(self.x - other.x, self.y - other.y)

In [11]:
c = Coordinate(3,4)
origin = Coordinate(0,0)
foo = c - origin
print(foo)

<3,4>


## Ví dụ: lớp Fraction¶

In [12]:
class fraction(object):
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom

def __str__(self):
return str(self.numer) + ' / ' + str(self.denom)

In [13]:
oneHalf = fraction(1, 2)
twoThirds = fraction(2, 3)

In [14]:
print(oneHalf)
print(twoThirds)

1 / 2
2 / 3


### Truy xuất các thành phần dữ liệu¶

In [15]:
class fraction(object):
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom

def __str__(self):
return str(self.numer) + ' / ' + str(self.denom)

def getNumer(self):
return self.numer

def getDenom(self):
return self.denom

In [16]:
oneHalf = fraction(1, 2)
twoThirds = fraction(2, 3)

In [17]:
oneHalf.getNumer()

Out[17]:
1
In [18]:
fraction.getDenom(twoThirds)

Out[18]:
3

### Nạp chồng toán tử + và -¶

In [19]:
class fraction(object):
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom

def __str__(self):
return str(self.numer) + ' / ' + str(self.denom)

def getNumer(self):
return self.numer

def getDenom(self):
return self.denom

numerNew = other.getDenom() * self.getNumer() \
+ other.getNumer() * self.getDenom()
denomNew = other.getDenom() * self.getDenom()
return fraction(numerNew, denomNew)

def __sub__(self, other):
numerNew = other.getDenom() * self.getNumer() \
- other.getNumer() * self.getDenom()
denomNew = other.getDenom() * self.getDenom()
return fraction(numerNew, denomNew)

In [20]:
oneHalf = fraction(1, 2)
twoThirds = fraction(2, 3)

In [21]:
new = oneHalf + twoThirds
print(new)

7 / 6

In [22]:
threeQuarters = fraction(3, 4)
secondNew = twoThirds - threeQuarters
print(secondNew)

-1 / 12


### Chuyển đổi kiểu dữ liệu¶

In [23]:
class fraction(object):
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom

def __str__(self):
return str(self.numer) + ' / ' + str(self.denom)

def getNumer(self):
return self.numer

def getDenom(self):
return self.denom

numerNew = other.getDenom() * self.getNumer() \
+ other.getNumer() * self.getDenom()
denomNew = other.getDenom() * self.getDenom()
return fraction(numerNew, denomNew)

def __sub__(self, other):
numerNew = other.getDenom() * self.getNumer() \
- other.getNumer() * self.getDenom()
denomNew = other.getDenom() * self.getDenom()
return fraction(numerNew, denomNew)

def convert(self):
return self.getNumer() / self.getDenom()

In [24]:
oneHalf = fraction(1, 2)
oneHalf.convert()

Out[24]:
0.5

## Ví dụ: Lớp chứa tập các số nguyên¶

In [25]:
class intSet(object):
def __init__(self):
self.vals = []

def insert(self, e):
if not e in self.vals:
self.vals.append(e)

def member(self, e):
return e in self.vals

def remove(self, e):
try:
self.vals.remove(e)
except:

def __str__(self):
self.vals.sort()
result = ''
for e in self.vals:
result = result + str(e) + ','
return '{' + result[:-1] + '}'

In [26]:
s = intSet()
print(s)

{}

In [27]:
s.insert(3)
s.insert(4)
s.insert(3)
print(s)

{3,4}

In [28]:
s.member(3)

Out[28]:
True
In [29]:
s.member(5)

Out[29]:
False
In [30]:
s.insert(6)
print(s)

{3,4,6}

In [31]:
s.remove(3)
print(s)

{4,6}

In [32]:
s.remove(3)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-25-ae5ab2e4f873> in remove(self, e)
13         try:
---> 14             self.vals.remove(e)
15         except:

ValueError: list.remove(x): x not in list

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-32-b06e0f5ff900> in <module>()
----> 1 s.remove(3)

<ipython-input-25-ae5ab2e4f873> in remove(self, e)
14             self.vals.remove(e)
15         except:
17
18     def __str__(self):

ValueError: 3 not found

## Vì sao OOP¶

In [33]:
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None

In [34]:
myAnimal = Animal(3)


### Hàm getter và setter¶

In [35]:
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None

def get_age(self):
return self.age

def get_name(self):
return self.name

def set_age(self, newage):
self.age = newage

def set_name(self, newname=""):
self.name = newname

def __str__(self):
return "animal:"+str(self.name)+":"+str(self.age)

In [36]:
myAnimal = Animal(3)
print(myAnimal)

animal:None:3

In [37]:
myAnimal.set_name('foobar')
print(myAnimal)

animal:foobar:3

In [38]:
myAnimal.get_age()

Out[38]:
3
In [39]:
myAnimal.age

Out[39]:
3

### Che dấu thông tin¶

In [40]:
class Animal(object):
def __init__(self, age):
self.years = age

def get_age(self):
return self.years


## Phân cấp lớp - Thừa kế¶

In [41]:
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None

def get_age(self):
return self.age

def get_name(self):
return self.name

def set_age(self, newage):
self.age = newage

def set_name(self, newname=""):
self.name = newname

def __str__(self):
return "animal:"+str(self.name)+":"+str(self.age)

In [42]:
class Cat(Animal):
def speak(self):
print('meow')

def __str__(self):
return "cat:"+str(self.name)+":"+str(self.age)

In [43]:
jelly = Cat(1)
jelly.get_name()

In [44]:
jelly.set_name('JellyBelly')
jelly.get_name()

Out[44]:
'JellyBelly'
In [45]:
print(jelly)

cat:JellyBelly:1

In [46]:
print(Animal.__str__(jelly))

animal:JellyBelly:1

In [47]:
blob = Animal(1)
print(blob)

animal:None:1

In [48]:
blob.set_name()
print(blob)

animal::1

In [49]:
class Rabbit(Animal):
def speak(self):
print("meep")

def __str__(self):
return "rabbit:"+str(self.name)+":"+str(self.age)

In [50]:
peter = Rabbit(5)
jelly.speak()

meow

In [51]:
peter.speak()

meep

In [52]:
blob.speak()

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-52-94bb5e7b33ae> in <module>()
----> 1 blob.speak()

AttributeError: 'Animal' object has no attribute 'speak'
In [53]:
class Person(Animal):
def __init__(self, name, age):
Animal.__init__(self, age)
Animal.set_name(self, name)
self.friends = []

def get_friends(self):
return self.friends

if fname not in self.friends:
self.friends.append(fname)

def speak(self):
print("hello")

def age_diff(self, other):
# alternate way: diff = self.age - other.age
diff = self.get_age() - other.get_age()
if self.age > other.age:
print(self.name, "is", diff, "years older than", other.name)
else:
print(self.name, "is", -diff, "years younger than", other.name)

def __str__(self):
return "person:"+str(self.name)+":"+str(self.age)

In [54]:
eric = Person('eric', 45)
john = Person('john', 55)

In [55]:
eric.speak()

hello

In [56]:
eric.age_diff(john)

eric is 10 years younger than john

In [57]:
Person.age_diff(john, eric)

john is 10 years older than eric

In [58]:
import random

class Student(Person):
def __init__(self, name, age, major=None):
Person.__init__(self, name, age)
self.major = major

def change_major(self, major):
self.major = major

def speak(self):
r = random.random()
if r < 0.25:
print("i have homework")
elif 0.25 <= r < 0.5:
print("i need sleep")
elif 0.5 <= r < 0.75:
print("i should eat")
else:
print("i am watching tv")

def __str__(self):
return "student:"+str(self.name)+":"+str(self.age)+":"+str(self.major)

In [59]:
fred = Student('fred', 18, 'Course VI')
print(fred)

student:fred:18:Course VI

In [60]:
fred.speak()

i need sleep

In [61]:
fred.speak()

i have homework

In [62]:
fred.speak()

i am watching tv

In [63]:
fred.speak()

i have homework


## Biến lớp - class variable¶

In [64]:
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None

def get_age(self):
return self.age

def get_name(self):
return self.name

def set_age(self, newage):
self.age = newage

def set_name(self, newname=""):
self.name = newname

def __str__(self):
return "animal:"+str(self.name)+":"+str(self.age)

class Cat(Animal):
def speak(self):
print("meow")

def __str__(self):
return "cat:"+str(self.name)+":"+str(self.age)

In [65]:
class Rabbit(Animal):
tag = 1

def __init__(self, age, parent1=None, parent2=None):
Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2
self.rid = Rabbit.tag
Rabbit.tag += 1

def get_rid(self):
return str(self.rid).zfill(3)

def get_parent1(self):
return self.parent1

def get_parent2(self):
return self.parent2

# returning object of same type as this class
return Rabbit(0, self, other)

def __eq__(self, other):
parents_same = self.parent1.rid == other.parent1.rid \
and self.parent2.rid == other.parent2.rid
parents_opposite = self.parent2.rid == other.parent1.rid \
and self.parent1.rid == other.parent2.rid
return parents_same or parents_opposite

In [66]:
peter = Rabbit(2)
peter.set_name('Peter')
hopsy = Rabbit(3)
hopsy.set_name('Hopsy')
cotton = Rabbit(1, peter, hopsy)
cotton.set_name('Cottontail')
print(cotton)

animal:Cottontail:1

In [67]:
print(cotton.get_parent1())

animal:Peter:2

In [68]:
mopsy = peter + hopsy
mopsy.set_name('Mopsy')
print(mopsy.get_parent1())

animal:Peter:2

In [69]:
print(mopsy.get_parent2())

animal:Hopsy:3

In [70]:
print(mopsy == cotton)

True


# Ví dụ¶

## Class Person¶

In [71]:
import datetime

class Person(object):
def __init__(self, name):
"""create a person called name"""
self.name = name
self.birthday = None
self.lastName = name.split(' ')[-1]

def getLastName(self):
"""return self's last name"""
return self.lastName

def setBirthday(self,month,day,year):
"""sets self's birthday to birthDate"""
self.birthday = datetime.date(year,month,day)

def getAge(self):
"""returns self's current age in days"""
if self.birthday == None:
raise ValueError
return (datetime.date.today() - self.birthday).days

def __lt__(self, other):
"""return True if self's ame is lexicographically
less than other's name, and False otherwise"""
if self.lastName == other.lastName:
return self.name < other.name
return self.lastName < other.lastName

def __str__(self):
"""return self's name"""
return self.name

In [72]:
p1 = Person('Mark Zuckerberg')
p1.setBirthday(5,14,84)
p2 = Person('Drew Houston')
p2.setBirthday(3,4,83)
p3 = Person('Bill Gates')
p3.setBirthday(10,28,55)
p4 = Person('Andrew Gates')
p5 = Person('Steve Wozniak')

personList = [p1, p2, p3, p4, p5]

In [73]:
print(p1)

Mark Zuckerberg

In [74]:
for e in personList:
print(e)

Mark Zuckerberg
Drew Houston
Bill Gates
Andrew Gates
Steve Wozniak

In [75]:
personList.sort()
for e in personList:
print(e)

Andrew Gates
Bill Gates
Drew Houston
Steve Wozniak
Mark Zuckerberg


## Lớp MITPerson¶

In [76]:
class MITPerson(Person):
nextIdNum = 0 # next ID number to assign

def __init__(self, name):
Person.__init__(self, name) # initialize Person attributes
# new MITPerson attribute: a unique ID number
self.idNum = MITPerson.nextIdNum
MITPerson.nextIdNum += 1

def getIdNum(self):
return self.idNum

# sorting MIT people uses their ID number, not name!
def __lt__(self, other):
return self.idNum < other.idNum

def speak(self, utterance):
return (self.getLastName() + " says: " + utterance)

In [77]:
m3 = MITPerson('Mark Zuckerberg')
Person.setBirthday(m3,5,14,84)
m2 = MITPerson('Drew Houston')
Person.setBirthday(m2,3,4,83)
m1 = MITPerson('Bill Gates')
Person.setBirthday(m1,10,28,55)

MITPersonList = [m1, m2, m3]

In [78]:
print(m1)

Bill Gates

In [79]:
print(m1.speak('hi there'))

Gates says: hi there

In [80]:
for e in MITPersonList:
print(e)

Bill Gates
Drew Houston
Mark Zuckerberg

In [81]:
MITPersonList.sort()

print()

for e in MITPersonList:
print(e)

Mark Zuckerberg
Drew Houston
Bill Gates

In [82]:
p1 =  MITPerson('Eric')
p2 = MITPerson('John')
p3 = MITPerson('John')
p4 = Person('John')

In [83]:
p1<p2

Out[83]:
True
In [84]:
p1<p4

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-84-e4b6153c0891> in <module>()
----> 1 p1<p4

<ipython-input-76-fa92103c453e> in __lt__(self, other)
13     # sorting MIT people uses their ID number, not name!
14     def __lt__(self, other):
---> 15         return self.idNum < other.idNum
16
17     def speak(self, utterance):

AttributeError: 'Person' object has no attribute 'idNum'
In [85]:
p4<p1

Out[85]:
False

## Các lớp Student¶

In [86]:
class UG(MITPerson):
def __init__(self, name, classYear):
MITPerson.__init__(self, name)
self.year = classYear

def getClass(self):
return self.year

def speak(self, utterance):
return MITPerson.speak(self, " Dude, " + utterance)

pass

def isStudent(obj):

In [87]:
s1 = UG('Matt Damon', 2017)
s2 = UG('Ben Affleck', 2017)
s3 = UG('Lin Manuel Miranda', 2018)

studentList = [s1, s2, s3, s4]

In [88]:
print(s1)

Matt Damon

In [89]:
print(s1.getClass())

2017

In [90]:
print(s1.speak('where is the quiz?'))

Damon says:  Dude, where is the quiz?

In [91]:
print(s2.speak('I have no idea'))

Affleck says:  Dude, I have no idea

In [92]:
class Student(MITPerson):
pass

class UG(Student):
def __init__(self, name, classYear):
MITPerson.__init__(self, name)
self.year = classYear

def getClass(self):
return self.year

def speak(self, utterance):
return MITPerson.speak(self, " Dude, " + utterance)

pass

class TransferStudent(Student):
pass

def isStudent(obj):
return isinstance(obj,Student)

In [93]:
s1 = UG('Matt Damon', 2017)
s2 = UG('Ben Affleck', 2017)
s3 = UG('Lin Manuel Miranda', 2018)
s5 = TransferStudent('Robert deNiro')

studentList = [s1, s2, s3, s4, s5]

In [94]:
print(s1)
print(s1.getClass())
print(s1.speak('where is the quiz?'))
print(s2.speak('I have no clue!'))

Matt Damon
2017
Damon says:  Dude, where is the quiz?
Affleck says:  Dude, I have no clue!


## Lớp Professor¶

In [95]:
class Professor(MITPerson):
def __init__(self, name, department):
MITPerson.__init__(self, name)
self.department = department

def speak(self, utterance):
newUtterance = 'In course ' + self.department + ' we say '
return MITPerson.speak(self, newUtterance + utterance)

def lecture(self, topic):
return self.speak('it is obvious that ' + topic)

In [96]:
faculty = Professor('Doctor Arrogant', 'six')

In [97]:
print(m1.speak('hi there'))

Gates says: hi there

In [98]:
print(s1.speak('hi there'))

Damon says:  Dude, hi there

In [99]:
print(faculty.speak('hi there'))

Arrogant says: In course six we say hi there

In [100]:
print(faculty.lecture('hi there'))

Arrogant says: In course six we say it is obvious that hi there

In [101]:
class MITPerson(Person):
nextIdNum = 0 # next ID number to assign

def __init__(self, name):
Person.__init__(self, name) # initialize Person attributes
# new MITPerson attribute: a unique ID number
self.idNum = MITPerson.nextIdNum
MITPerson.nextIdNum += 1

def getIdNum(self):
return self.idNum

# sorting MIT people uses their ID number, not name!
def __lt__(self, other):
return self.idNum < other.idNum

def speak(self, utterance):
return (self.name + " says: " + utterance)

In [102]:
print(m1.speak('hi there'))
print(s1.speak('hi there'))
print(faculty.speak('hi there'))
print(faculty.lecture('hi there'))

Gates says: hi there
Matt Damon says:  Dude, hi there
Doctor Arrogant says: In course six we say hi there
Doctor Arrogant says: In course six we say it is obvious that hi there

In [103]:
class Student(MITPerson):
pass

class UG(Student):
def __init__(self, name, classYear):
MITPerson.__init__(self, name)
self.year = classYear

def getClass(self):
return self.year

def speak(self, utterance):
return MITPerson.speak(self, " Yo Bro, " + utterance)

pass

class TransferStudent(Student):
pass

def isStudent(obj):
return isinstance(obj,Student)

In [104]:
print(m1.speak('hi there'))
print(s1.speak('hi there'))
print(faculty.speak('hi there'))
print(faculty.lecture('hi there'))

Gates says: hi there
Matt Damon says:  Dude, hi there
Doctor Arrogant says: In course six we say hi there
Doctor Arrogant says: In course six we say it is obvious that hi there


In [105]:
class Grades(object):
"""A mapping from students to a list of grades"""
def __init__(self):
self.students = []  # list of Student objects
self.isSorted = True # true if self.students is sorted

"""Assumes: student is of type Student
if student in self.students:
raise ValueError('Duplicate student')
self.students.append(student)
self.isSorted = False

try:
except KeyError:
raise ValueError('Student not in grade book')

"""Return a list of grades for student"""
try:    # return copy of student's grades
except KeyError:
raise ValueError('Student not in grade book')

def allStudents(self):
"""Return a list of the students in the grade book"""
if not self.isSorted:
self.students.sort()
self.isSorted = True
return self.students[:]
#return copy of list of students

In [106]:
def gradeReport(course):
"""Assumes: course if of type grades"""
report = []
for s in course.allStudents():
tot = 0.0
tot += g
try:
report.append(str(s) + '\'s mean grade is '
+ str(average))
except ZeroDivisionError:
report.append(str(s) + ' has no grades')
return '\n'.join(report)

In [107]:
ug1 = UG('Matt Damon', 2018)
ug2 = UG('Ben Affleck', 2019)
ug3 = UG('Drew Houston', 2017)
ug4 = UG('Mark Zuckerberg', 2017)

print()


Matt Damon's mean grade is 95.0
Ben Affleck's mean grade is 85.0
Drew Houston's mean grade is 75.0
Bill Gates's mean grade is 100.0
Steve Wozniak's mean grade is 25.0

In [108]:
# thêm điểm mới

print()


Matt Damon's mean grade is 87.5
Ben Affleck's mean grade is 80.0
Drew Houston's mean grade is 75.0
Bill Gates's mean grade is 95.0
Steve Wozniak's mean grade is 35.0

In [109]:
for s in six00.allStudents():
print(s)

Matt Damon
Ben Affleck
Drew Houston
Mark Zuckerberg
Bill Gates
Steve Wozniak


## Generator¶

In [110]:
def genTest():
yield 1
yield 2

foo = genTest()

foo.__next__()

Out[110]:
1
In [111]:
foo.__next__()

Out[111]:
2
In [112]:
foo.__next__()

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-112-5d994c17f9ca> in <module>()
----> 1 foo.__next__()

StopIteration: 
In [113]:
for n in genTest():
print(n)

1
2

In [114]:
def genFib():
fibn_1 = 1 #fib(n-1)
fibn_2 = 0 #fib(n-2)
while True:
# fib(n) = fib(n-1) + fib(n-2)
next = fibn_1 + fibn_2
yield next
fibn_2 = fibn_1
fibn_1 = next

In [115]:
fib = genFib()

fib.__next__()

Out[115]:
1
In [116]:
class Grades(object):
"""A mapping from students to a list of grades"""
def __init__(self):
self.students = []  # list of Student objects
self.isSorted = True # true if self.students is sorted

"""Assumes: student is of type Student
if student in self.students:
raise ValueError('Duplicate student')
self.students.append(student)
self.isSorted = False

try:
except KeyError:
raise ValueError('Student not in grade book')

"""Return a list of grades for student"""
try:    # return copy of student's grades
except KeyError:
raise ValueError('Student not in grade book')

def allStudents(self):
"""Return a list of the students in the grade book"""
if not self.isSorted:
self.students.sort()
self.isSorted = True
for s in self.students:
yield s

"""Assumes: course if of type grades"""
report = []
for s in course.allStudents():
tot = 0.0
tot += g
try:
report.append(str(s) + '\'s mean grade is '
+ str(average))
except ZeroDivisionError:
report.append(str(s) + ' has no grades')
return '\n'.join(report)

ug1 = UG('Matt Damon', 2018)
ug2 = UG('Ben Affleck', 2019)
ug3 = UG('Drew Houston', 2017)
ug4 = UG('Mark Zuckerberg', 2017)


Matt Damon's mean grade is 95.0