{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Lập trình Hướng đối tượng\n", "\n", "## Lớp và thể hiện của lớp" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "class Coordinate(object):\n", " def __init__(self, x, y):\n", " self.x = x\n", " self.y = y" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "c = Coordinate(3,4)\n", "origin = Coordinate(0,0)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3\n", "0\n" ] } ], "source": [ "print(c.x)\n", "print(origin.x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hàm thành phần" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "class Coordinate(object):\n", " def __init__(self, x, y):\n", " self.x = x\n", " self.y = y\n", " \n", " def distance(self, other):\n", " x_diff_sq = (self.x-other.x)**2\n", " y_diff_sq = (self.y-other.y)**2\n", " return (x_diff_sq + y_diff_sq)**0.5" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5.0\n" ] } ], "source": [ "c = Coordinate(3,4)\n", "origin = Coordinate(0,0)\n", "print(c.distance(origin))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5.0\n" ] } ], "source": [ "print(Coordinate.distance(c, origin))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### print một đối tượng" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "class Coordinate(object):\n", " def __init__(self, x, y):\n", " self.x = x\n", " self.y = y\n", " \n", " def distance(self, other):\n", " x_diff_sq = (self.x-other.x)**2\n", " y_diff_sq = (self.y-other.y)**2\n", " return (x_diff_sq + y_diff_sq)**0.5\n", " \n", " def __str__(self):\n", " return \"<\" + str(self.x) + \",\" + str(self.y) + \">\"" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<3,4>\n" ] } ], "source": [ "c = Coordinate(3,4)\n", "print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### check type of an object" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "print(isinstance(c, Coordinate))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Nạp chồng toán tử" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "class Coordinate(object):\n", " def __init__(self, x, y):\n", " self.x = x\n", " self.y = y\n", " \n", " def distance(self, other):\n", " x_diff_sq = (self.x-other.x)**2\n", " y_diff_sq = (self.y-other.y)**2\n", " return (x_diff_sq + y_diff_sq)**0.5\n", " \n", " def __str__(self):\n", " return \"<\" + str(self.x) + \",\" + str(self.y) + \">\"\n", " \n", " def __sub__(self, other):\n", " return Coordinate(self.x - other.x, self.y - other.y)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<3,4>\n" ] } ], "source": [ "c = Coordinate(3,4)\n", "origin = Coordinate(0,0)\n", "foo = c - origin\n", "print(foo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ví dụ: lớp Fraction" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "class fraction(object):\n", " def __init__(self, numer, denom):\n", " self.numer = numer\n", " self.denom = denom\n", " \n", " def __str__(self):\n", " return str(self.numer) + ' / ' + str(self.denom)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "oneHalf = fraction(1, 2)\n", "twoThirds = fraction(2, 3)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 / 2\n", "2 / 3\n" ] } ], "source": [ "print(oneHalf)\n", "print(twoThirds)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Truy xuất các thành phần dữ liệu" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "class fraction(object):\n", " def __init__(self, numer, denom):\n", " self.numer = numer\n", " self.denom = denom\n", " \n", " def __str__(self):\n", " return str(self.numer) + ' / ' + str(self.denom)\n", " \n", " def getNumer(self):\n", " return self.numer\n", " \n", " def getDenom(self):\n", " return self.denom" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "oneHalf = fraction(1, 2)\n", "twoThirds = fraction(2, 3)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "oneHalf.getNumer()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fraction.getDenom(twoThirds)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Nạp chồng toán tử + và -" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "class fraction(object):\n", " def __init__(self, numer, denom):\n", " self.numer = numer\n", " self.denom = denom\n", " \n", " def __str__(self):\n", " return str(self.numer) + ' / ' + str(self.denom)\n", " \n", " def getNumer(self):\n", " return self.numer\n", " \n", " def getDenom(self):\n", " return self.denom\n", " \n", " def __add__(self, other):\n", " numerNew = other.getDenom() * self.getNumer() \\\n", " + other.getNumer() * self.getDenom()\n", " denomNew = other.getDenom() * self.getDenom()\n", " return fraction(numerNew, denomNew)\n", " \n", " def __sub__(self, other):\n", " numerNew = other.getDenom() * self.getNumer() \\\n", " - other.getNumer() * self.getDenom()\n", " denomNew = other.getDenom() * self.getDenom()\n", " return fraction(numerNew, denomNew)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "oneHalf = fraction(1, 2)\n", "twoThirds = fraction(2, 3)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "7 / 6\n" ] } ], "source": [ "new = oneHalf + twoThirds\n", "print(new)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-1 / 12\n" ] } ], "source": [ "threeQuarters = fraction(3, 4)\n", "secondNew = twoThirds - threeQuarters\n", "print(secondNew)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Chuyển đổi kiểu dữ liệu" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "class fraction(object):\n", " def __init__(self, numer, denom):\n", " self.numer = numer\n", " self.denom = denom\n", " \n", " def __str__(self):\n", " return str(self.numer) + ' / ' + str(self.denom)\n", " \n", " def getNumer(self):\n", " return self.numer\n", " \n", " def getDenom(self):\n", " return self.denom\n", " \n", " def __add__(self, other):\n", " numerNew = other.getDenom() * self.getNumer() \\\n", " + other.getNumer() * self.getDenom()\n", " denomNew = other.getDenom() * self.getDenom()\n", " return fraction(numerNew, denomNew)\n", " \n", " def __sub__(self, other):\n", " numerNew = other.getDenom() * self.getNumer() \\\n", " - other.getNumer() * self.getDenom()\n", " denomNew = other.getDenom() * self.getDenom()\n", " return fraction(numerNew, denomNew)\n", " \n", " def convert(self):\n", " return self.getNumer() / self.getDenom()" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.5" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "oneHalf = fraction(1, 2)\n", "oneHalf.convert()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ví dụ: Lớp chứa tập các số nguyên" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "class intSet(object):\n", " def __init__(self):\n", " self.vals = []\n", " \n", " def insert(self, e):\n", " if not e in self.vals:\n", " self.vals.append(e)\n", " \n", " def member(self, e):\n", " return e in self.vals\n", " \n", " def remove(self, e):\n", " try:\n", " self.vals.remove(e)\n", " except:\n", " raise ValueError(str(e) + ' not found')\n", " \n", " def __str__(self):\n", " self.vals.sort()\n", " result = ''\n", " for e in self.vals:\n", " result = result + str(e) + ','\n", " return '{' + result[:-1] + '}'" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{}\n" ] } ], "source": [ "s = intSet()\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{3,4}\n" ] } ], "source": [ "s.insert(3)\n", "s.insert(4)\n", "s.insert(3)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.member(3)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s.member(5)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{3,4,6}\n" ] } ], "source": [ "s.insert(6)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{4,6}\n" ] } ], "source": [ "s.remove(3)\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "3 not found", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36mremove\u001b[0;34m(self, e)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvals\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mremove\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 15\u001b[0m \u001b[0;32mexcept\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: list.remove(x): x not in list", "\nDuring handling of the above exception, another exception occurred:\n", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ms\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mremove\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mremove\u001b[0;34m(self, e)\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvals\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mremove\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0;32mexcept\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 16\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m' not found'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 17\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__str__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: 3 not found" ] } ], "source": [ "s.remove(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vì sao OOP" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "class Animal(object):\n", " def __init__(self, age):\n", " self.age = age\n", " self.name = None" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "myAnimal = Animal(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Hàm getter và setter" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "class Animal(object):\n", " def __init__(self, age):\n", " self.age = age\n", " self.name = None\n", " \n", " def get_age(self):\n", " return self.age\n", " \n", " def get_name(self):\n", " return self.name\n", " \n", " def set_age(self, newage):\n", " self.age = newage\n", " \n", " def set_name(self, newname=\"\"):\n", " self.name = newname\n", " \n", " def __str__(self):\n", " return \"animal:\"+str(self.name)+\":\"+str(self.age)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:None:3\n" ] } ], "source": [ "myAnimal = Animal(3)\n", "print(myAnimal)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:foobar:3\n" ] } ], "source": [ "myAnimal.set_name('foobar')\n", "print(myAnimal)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "myAnimal.get_age()" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "myAnimal.age" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Che dấu thông tin" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "class Animal(object):\n", " def __init__(self, age):\n", " self.years = age\n", " \n", " def get_age(self):\n", " return self.years" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Phân cấp lớp - Thừa kế" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "class Animal(object):\n", " def __init__(self, age):\n", " self.age = age\n", " self.name = None\n", " \n", " def get_age(self):\n", " return self.age\n", " \n", " def get_name(self):\n", " return self.name\n", " \n", " def set_age(self, newage):\n", " self.age = newage\n", " \n", " def set_name(self, newname=\"\"):\n", " self.name = newname\n", " \n", " def __str__(self):\n", " return \"animal:\"+str(self.name)+\":\"+str(self.age)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "class Cat(Animal):\n", " def speak(self):\n", " print('meow')\n", " \n", " def __str__(self):\n", " return \"cat:\"+str(self.name)+\":\"+str(self.age)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "jelly = Cat(1)\n", "jelly.get_name()" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'JellyBelly'" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "jelly.set_name('JellyBelly')\n", "jelly.get_name()" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cat:JellyBelly:1\n" ] } ], "source": [ "print(jelly)" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:JellyBelly:1\n" ] } ], "source": [ "print(Animal.__str__(jelly))" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:None:1\n" ] } ], "source": [ "blob = Animal(1)\n", "print(blob)" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal::1\n" ] } ], "source": [ "blob.set_name()\n", "print(blob)" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "class Rabbit(Animal):\n", " def speak(self):\n", " print(\"meep\")\n", " \n", " def __str__(self):\n", " return \"rabbit:\"+str(self.name)+\":\"+str(self.age)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "meow\n" ] } ], "source": [ "peter = Rabbit(5)\n", "jelly.speak()" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "meep\n" ] } ], "source": [ "peter.speak()" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "'Animal' object has no attribute 'speak'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mblob\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mspeak\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m: 'Animal' object has no attribute 'speak'" ] } ], "source": [ "blob.speak()" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [], "source": [ "class Person(Animal):\n", " def __init__(self, name, age):\n", " Animal.__init__(self, age)\n", " Animal.set_name(self, name)\n", " self.friends = []\n", " \n", " def get_friends(self):\n", " return self.friends\n", " \n", " def add_friend(self, fname):\n", " if fname not in self.friends:\n", " self.friends.append(fname)\n", " \n", " def speak(self):\n", " print(\"hello\")\n", " \n", " def age_diff(self, other):\n", " # alternate way: diff = self.age - other.age\n", " diff = self.get_age() - other.get_age()\n", " if self.age > other.age:\n", " print(self.name, \"is\", diff, \"years older than\", other.name)\n", " else:\n", " print(self.name, \"is\", -diff, \"years younger than\", other.name)\n", " \n", " def __str__(self):\n", " return \"person:\"+str(self.name)+\":\"+str(self.age)" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "eric = Person('eric', 45)\n", "john = Person('john', 55)" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hello\n" ] } ], "source": [ "eric.speak()" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "eric is 10 years younger than john\n" ] } ], "source": [ "eric.age_diff(john)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "john is 10 years older than eric\n" ] } ], "source": [ "Person.age_diff(john, eric)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [], "source": [ "import random\n", "\n", "class Student(Person):\n", " def __init__(self, name, age, major=None):\n", " Person.__init__(self, name, age)\n", " self.major = major\n", " \n", " def change_major(self, major):\n", " self.major = major\n", " \n", " def speak(self):\n", " r = random.random()\n", " if r < 0.25:\n", " print(\"i have homework\")\n", " elif 0.25 <= r < 0.5:\n", " print(\"i need sleep\")\n", " elif 0.5 <= r < 0.75:\n", " print(\"i should eat\")\n", " else:\n", " print(\"i am watching tv\")\n", " \n", " def __str__(self):\n", " return \"student:\"+str(self.name)+\":\"+str(self.age)+\":\"+str(self.major)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "student:fred:18:Course VI\n" ] } ], "source": [ "fred = Student('fred', 18, 'Course VI')\n", "print(fred)" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i need sleep\n" ] } ], "source": [ "fred.speak()" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i have homework\n" ] } ], "source": [ "fred.speak()" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i am watching tv\n" ] } ], "source": [ "fred.speak()" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i have homework\n" ] } ], "source": [ "fred.speak()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Biến lớp - class variable" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "class Animal(object):\n", " def __init__(self, age):\n", " self.age = age\n", " self.name = None\n", " \n", " def get_age(self):\n", " return self.age\n", " \n", " def get_name(self):\n", " return self.name\n", " \n", " def set_age(self, newage):\n", " self.age = newage\n", " \n", " def set_name(self, newname=\"\"):\n", " self.name = newname\n", " \n", " def __str__(self):\n", " return \"animal:\"+str(self.name)+\":\"+str(self.age)\n", "\n", "class Cat(Animal):\n", " def speak(self):\n", " print(\"meow\")\n", " \n", " def __str__(self):\n", " return \"cat:\"+str(self.name)+\":\"+str(self.age)" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [], "source": [ "class Rabbit(Animal):\n", " tag = 1\n", " \n", " def __init__(self, age, parent1=None, parent2=None):\n", " Animal.__init__(self, age)\n", " self.parent1 = parent1\n", " self.parent2 = parent2\n", " self.rid = Rabbit.tag\n", " Rabbit.tag += 1\n", " \n", " def get_rid(self):\n", " return str(self.rid).zfill(3)\n", " \n", " def get_parent1(self):\n", " return self.parent1\n", " \n", " def get_parent2(self):\n", " return self.parent2\n", " \n", " def __add__(self, other):\n", " # returning object of same type as this class\n", " return Rabbit(0, self, other)\n", " \n", " def __eq__(self, other):\n", " parents_same = self.parent1.rid == other.parent1.rid \\\n", " and self.parent2.rid == other.parent2.rid\n", " parents_opposite = self.parent2.rid == other.parent1.rid \\\n", " and self.parent1.rid == other.parent2.rid\n", " return parents_same or parents_opposite" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:Cottontail:1\n" ] } ], "source": [ "peter = Rabbit(2)\n", "peter.set_name('Peter')\n", "hopsy = Rabbit(3)\n", "hopsy.set_name('Hopsy')\n", "cotton = Rabbit(1, peter, hopsy)\n", "cotton.set_name('Cottontail')\n", "print(cotton)" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:Peter:2\n" ] } ], "source": [ "print(cotton.get_parent1())" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:Peter:2\n" ] } ], "source": [ "mopsy = peter + hopsy\n", "mopsy.set_name('Mopsy')\n", "print(mopsy.get_parent1())" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "animal:Hopsy:3\n" ] } ], "source": [ "print(mopsy.get_parent2())" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "print(mopsy == cotton)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Ví dụ\n", "\n", "## Class Person" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [], "source": [ "import datetime\n", "\n", "class Person(object):\n", " def __init__(self, name):\n", " \"\"\"create a person called name\"\"\"\n", " self.name = name\n", " self.birthday = None\n", " self.lastName = name.split(' ')[-1]\n", "\n", " def getLastName(self):\n", " \"\"\"return self's last name\"\"\"\n", " return self.lastName\n", " \n", " def setBirthday(self,month,day,year):\n", " \"\"\"sets self's birthday to birthDate\"\"\"\n", " self.birthday = datetime.date(year,month,day)\n", " \n", " def getAge(self):\n", " \"\"\"returns self's current age in days\"\"\"\n", " if self.birthday == None:\n", " raise ValueError\n", " return (datetime.date.today() - self.birthday).days\n", " \n", " def __lt__(self, other):\n", " \"\"\"return True if self's ame is lexicographically\n", " less than other's name, and False otherwise\"\"\"\n", " if self.lastName == other.lastName:\n", " return self.name < other.name\n", " return self.lastName < other.lastName\n", " \n", " def __str__(self):\n", " \"\"\"return self's name\"\"\"\n", " return self.name" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [], "source": [ "p1 = Person('Mark Zuckerberg')\n", "p1.setBirthday(5,14,84)\n", "p2 = Person('Drew Houston')\n", "p2.setBirthday(3,4,83)\n", "p3 = Person('Bill Gates')\n", "p3.setBirthday(10,28,55)\n", "p4 = Person('Andrew Gates')\n", "p5 = Person('Steve Wozniak')\n", "\n", "personList = [p1, p2, p3, p4, p5]" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mark Zuckerberg\n" ] } ], "source": [ "print(p1)" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mark Zuckerberg\n", "Drew Houston\n", "Bill Gates\n", "Andrew Gates\n", "Steve Wozniak\n" ] } ], "source": [ "for e in personList:\n", " print(e)" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Andrew Gates\n", "Bill Gates\n", "Drew Houston\n", "Steve Wozniak\n", "Mark Zuckerberg\n" ] } ], "source": [ "personList.sort()\n", "for e in personList:\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lớp MITPerson" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [], "source": [ "class MITPerson(Person):\n", " nextIdNum = 0 # next ID number to assign\n", "\n", " def __init__(self, name):\n", " Person.__init__(self, name) # initialize Person attributes\n", " # new MITPerson attribute: a unique ID number\n", " self.idNum = MITPerson.nextIdNum\n", " MITPerson.nextIdNum += 1\n", "\n", " def getIdNum(self):\n", " return self.idNum\n", "\n", " # sorting MIT people uses their ID number, not name!\n", " def __lt__(self, other):\n", " return self.idNum < other.idNum\n", " \n", " def speak(self, utterance):\n", " return (self.getLastName() + \" says: \" + utterance)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [], "source": [ "m3 = MITPerson('Mark Zuckerberg')\n", "Person.setBirthday(m3,5,14,84)\n", "m2 = MITPerson('Drew Houston')\n", "Person.setBirthday(m2,3,4,83)\n", "m1 = MITPerson('Bill Gates')\n", "Person.setBirthday(m1,10,28,55)\n", "\n", "MITPersonList = [m1, m2, m3]" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bill Gates\n" ] } ], "source": [ "print(m1)" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gates says: hi there\n" ] } ], "source": [ "print(m1.speak('hi there'))" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bill Gates\n", "Drew Houston\n", "Mark Zuckerberg\n" ] } ], "source": [ "for e in MITPersonList:\n", " print(e)" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Mark Zuckerberg\n", "Drew Houston\n", "Bill Gates\n" ] } ], "source": [ "MITPersonList.sort()\n", "\n", "print()\n", "\n", "for e in MITPersonList:\n", " print(e)" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [], "source": [ "p1 = MITPerson('Eric')\n", "p2 = MITPerson('John')\n", "p3 = MITPerson('John')\n", "p4 = Person('John')" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p1\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mp1\u001b[0m\u001b[0;34m<\u001b[0m\u001b[0mp4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36m__lt__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;31m# sorting MIT people uses their ID number, not name!\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__lt__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0midNum\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0midNum\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mspeak\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mutterance\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mAttributeError\u001b[0m: 'Person' object has no attribute 'idNum'" ] } ], "source": [ "p1 list of grades\n", " self.isSorted = True # true if self.students is sorted\n", "\n", " def addStudent(self, student):\n", " \"\"\"Assumes: student is of type Student\n", " Add student to the grade book\"\"\"\n", " if student in self.students:\n", " raise ValueError('Duplicate student')\n", " self.students.append(student)\n", " self.grades[student.getIdNum()] = []\n", " self.isSorted = False\n", "\n", " def addGrade(self, student, grade):\n", " \"\"\"Assumes: grade is a float\n", " Add grade to the list of grades for student\"\"\"\n", " try:\n", " self.grades[student.getIdNum()].append(grade)\n", " except KeyError:\n", " raise ValueError('Student not in grade book')\n", "\n", " def getGrades(self, student):\n", " \"\"\"Return a list of grades for student\"\"\"\n", " try: # return copy of student's grades\n", " return self.grades[student.getIdNum()][:]\n", " except KeyError:\n", " raise ValueError('Student not in grade book')\n", "\n", "\n", " def allStudents(self):\n", " \"\"\"Return a list of the students in the grade book\"\"\"\n", " if not self.isSorted:\n", " self.students.sort()\n", " self.isSorted = True\n", " return self.students[:] \n", " #return copy of list of students" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [], "source": [ "def gradeReport(course):\n", " \"\"\"Assumes: course if of type grades\"\"\"\n", " report = []\n", " for s in course.allStudents():\n", " tot = 0.0\n", " numGrades = 0\n", " for g in course.getGrades(s):\n", " tot += g\n", " numGrades += 1\n", " try:\n", " average = tot/numGrades\n", " report.append(str(s) + '\\'s mean grade is '\n", " + str(average))\n", " except ZeroDivisionError:\n", " report.append(str(s) + ' has no grades')\n", " return '\\n'.join(report)" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Matt Damon's mean grade is 95.0\n", "Ben Affleck's mean grade is 85.0\n", "Drew Houston's mean grade is 75.0\n", "Mark Zuckerberg has no grades\n", "Bill Gates's mean grade is 100.0\n", "Steve Wozniak's mean grade is 25.0\n" ] } ], "source": [ "ug1 = UG('Matt Damon', 2018)\n", "ug2 = UG('Ben Affleck', 2019)\n", "ug3 = UG('Drew Houston', 2017)\n", "ug4 = UG('Mark Zuckerberg', 2017)\n", "g1 = Grad('Bill Gates')\n", "g2 = Grad('Steve Wozniak')\n", "\n", "six00 = Grades()\n", "six00.addStudent(g1)\n", "six00.addStudent(ug2)\n", "six00.addStudent(ug1)\n", "six00.addStudent(g2)\n", "six00.addStudent(ug4)\n", "six00.addStudent(ug3)\n", "\n", "\n", "six00.addGrade(g1, 100)\n", "six00.addGrade(g2, 25)\n", "six00.addGrade(ug1, 95)\n", "six00.addGrade(ug2, 85)\n", "six00.addGrade(ug3, 75)\n", "\n", "print()\n", "\n", "print(gradeReport(six00))" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Matt Damon's mean grade is 87.5\n", "Ben Affleck's mean grade is 80.0\n", "Drew Houston's mean grade is 75.0\n", "Mark Zuckerberg has no grades\n", "Bill Gates's mean grade is 95.0\n", "Steve Wozniak's mean grade is 35.0\n" ] } ], "source": [ "# thêm điểm mới\n", "six00.addGrade(g1, 90)\n", "six00.addGrade(g2, 45)\n", "six00.addGrade(ug1, 80)\n", "six00.addGrade(ug2, 75)\n", "\n", "print()\n", "\n", "print(gradeReport(six00))" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Matt Damon\n", "Ben Affleck\n", "Drew Houston\n", "Mark Zuckerberg\n", "Bill Gates\n", "Steve Wozniak\n" ] } ], "source": [ "for s in six00.allStudents():\n", " print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generator" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def genTest():\n", " yield 1\n", " yield 2\n", " \n", "foo = genTest()\n", "\n", "foo.__next__()" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "foo.__next__()" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "ename": "StopIteration", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfoo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__next__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mStopIteration\u001b[0m: " ] } ], "source": [ "foo.__next__()" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n" ] } ], "source": [ "for n in genTest():\n", " print(n)" ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [], "source": [ "def genFib():\n", " fibn_1 = 1 #fib(n-1)\n", " fibn_2 = 0 #fib(n-2)\n", " while True:\n", " # fib(n) = fib(n-1) + fib(n-2)\n", " next = fibn_1 + fibn_2\n", " yield next\n", " fibn_2 = fibn_1\n", " fibn_1 = next" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib = genFib()\n", "\n", "fib.__next__()" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Matt Damon's mean grade is 95.0\n", "Ben Affleck's mean grade is 85.0\n", "Drew Houston's mean grade is 75.0\n", "Mark Zuckerberg has no grades\n", "Bill Gates's mean grade is 100.0\n", "Steve Wozniak's mean grade is 25.0\n" ] } ], "source": [ "class Grades(object):\n", " \"\"\"A mapping from students to a list of grades\"\"\"\n", " def __init__(self):\n", " \"\"\"Create empty grade book\"\"\"\n", " self.students = [] # list of Student objects\n", " self.grades = {} # maps idNum -> list of grades\n", " self.isSorted = True # true if self.students is sorted\n", "\n", " def addStudent(self, student):\n", " \"\"\"Assumes: student is of type Student\n", " Add student to the grade book\"\"\"\n", " if student in self.students:\n", " raise ValueError('Duplicate student')\n", " self.students.append(student)\n", " self.grades[student.getIdNum()] = []\n", " self.isSorted = False\n", "\n", " def addGrade(self, student, grade):\n", " \"\"\"Assumes: grade is a float\n", " Add grade to the list of grades for student\"\"\"\n", " try:\n", " self.grades[student.getIdNum()].append(grade)\n", " except KeyError:\n", " raise ValueError('Student not in grade book')\n", "\n", " def getGrades(self, student):\n", " \"\"\"Return a list of grades for student\"\"\"\n", " try: # return copy of student's grades\n", " return self.grades[student.getIdNum()][:]\n", " except KeyError:\n", " raise ValueError('Student not in grade book')\n", "\n", "\n", " def allStudents(self):\n", " \"\"\"Return a list of the students in the grade book\"\"\"\n", " if not self.isSorted:\n", " self.students.sort()\n", " self.isSorted = True\n", " for s in self.students:\n", " yield s\n", " \n", "def gradeReport(course):\n", " \"\"\"Assumes: course if of type grades\"\"\"\n", " report = []\n", " for s in course.allStudents():\n", " tot = 0.0\n", " numGrades = 0\n", " for g in course.getGrades(s):\n", " tot += g\n", " numGrades += 1\n", " try:\n", " average = tot/numGrades\n", " report.append(str(s) + '\\'s mean grade is '\n", " + str(average))\n", " except ZeroDivisionError:\n", " report.append(str(s) + ' has no grades')\n", " return '\\n'.join(report)\n", "\n", "ug1 = UG('Matt Damon', 2018)\n", "ug2 = UG('Ben Affleck', 2019)\n", "ug3 = UG('Drew Houston', 2017)\n", "ug4 = UG('Mark Zuckerberg', 2017)\n", "g1 = Grad('Bill Gates')\n", "g2 = Grad('Steve Wozniak')\n", "\n", "six00 = Grades()\n", "six00.addStudent(g1)\n", "six00.addStudent(ug2)\n", "six00.addStudent(ug1)\n", "six00.addStudent(g2)\n", "six00.addStudent(ug4)\n", "six00.addStudent(ug3)\n", "\n", "six00.addGrade(g1, 100)\n", "six00.addGrade(g2, 25)\n", "six00.addGrade(ug1, 95)\n", "six00.addGrade(ug2, 85)\n", "six00.addGrade(ug3, 75)\n", "\n", "print()\n", "\n", "print(gradeReport(six00))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- - -\n", "[Trước: Biệt lệ và xác nhận](http://nbviewer.jupyter.org/github/manleviet/introCSusingPython/blob/master/8%20-%20Bi%E1%BB%87t%20l%E1%BB%87%20v%C3%A0%20x%C3%A1c%20nh%E1%BA%ADn.ipynb) | \n", "[Mục lục](http://nbviewer.jupyter.org/github/manleviet/introCSusingPython/blob/master/index.ipynb) | \n", "[Tiếp: Tìm kiếm và sắp xếp](http://nbviewer.jupyter.org/github/manleviet/introCSusingPython/blob/master/10%20-%20T%C3%ACm%20ki%E1%BA%BFm%20v%C3%A0%20s%E1%BA%AFp%20x%E1%BA%BFp.ipynb)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }