(IPPA233277) w08-w09-c06 - Class (Done)
(IPPA233277) w08-w09-c06 - Class (Done)
CLASS
MỤC TIÊU BÀI HỌC
1. Dẫn nhập
2. Khai báo class, instance
3. Thuộc tính của lớp và thuộc tính đối tượng
4. Các phép toán trên đối tượng
5. Phạm vi truy cập thuộc tính và phương thức
6. OOP trong python
7. Hủy đối tượng
• Python là một ngôn ngữ đa mô hình (multiparadigm) hỗ trợ lập trình hướng đối tượng (OOP) thông qua các lớp
(class) để xác định dữ liệu và hành vi của một đối tượng cụ thể được mô hình hóa.
• Thuật ngữ attributes (thuộc tính) để chỉ những thuộc tính hoặc dữ liệu được liên kết với đối tượng cụ thể của một
lớp. Thuộc tính được định nghĩa trong một lớp với mục đích lưu trữ tất cả dữ liệu cần thiết cho lớp hoạt động.
• Thuật ngữ method (phương thức) để chỉ những hành vi khác nhau của đối tượng. Phương thức được định nghĩa
trong một lớp.
• Thuật ngữ instance (thể hiện) là một đối tượng thể hiện cụ thể của lớp.
• Ngoài ra, cách thức tổ chức các lớp cũng được xây dựng dựa trên hệ thống phân cấp hay kế thừa nhằm sử dụng
lại các đoạn mã và loại bỏ sự lặp lại mã nguồn trong chương trình
• Mỗi lớp python đều có các thuộc tính được xây dựng sẵn:
• __dict__ : là dictionary chứa namespace của lớp
• __doc__ : được sử dụng để truy cập document string
• __name__ : là tên lớp
• __module__ : là tên module trong đó lớp được định nghĩa
• __bases__ : là một tuple chứa các lớp cơ sở
• Sử dụng dấu chấm (.) và phép gán để thêm các thuộc tính và phương thức mới vào một lớp hoặc dùng các
phương thức để tạo thêm thuộc tính:
✓ Hàm getattr(obj, name[, default]) : để truy cập thuộc tính của đối tượng.
✓ Hàm hasattr(obj,name) : để kiểm tra xem một thuộc tính có tồn tại hay không.
✓ Hàm setattr(obj,name,value) : để thiết lập một thuộc tính. Nếu thuộc tính không tồn tại, thì nó sẽ được tạo.
✓ Hàm delattr(obj, name) : để xóa một thuộc tính.
• Thuộc tính lớp (class attribute) là các biến mà được khai báo trực tiếp trong lớp nhưng nằm ngoài phương thức.
Các thuộc tính này gắn với lớp, không gắn với đối tượng cụ thể của lớp
• Tất cả các đối tượng được tạo từ lớp đều có chung thuộc tính lớp với cùng giá trị ban đầu
class ObjectCounter:
num_instances = 0 # thuộc tính lớp
def __init__(self):
type(self).num_instances += 1
• Thuộc tính đối tượng (instance attribute) là các biến được gắn với một đối tượng cụ thể của một lớp nhất định. Giá trị
của một thuộc tính instance được gắn vào chính đối tượng đó, dành riêng cho thể hiện chứa nó.
• Các thuộc tính này thường được khai báo trong instance method thường là phương thức nhận self làm tham số đầu
tiên, thường dùng là __init__()
Ví dụ:
# car.py
class Car:
def __init__(self, model, color):
self.model = model
self.color = color
self.started = False Thuộc tính đối tượng
self.speed = 0
self.max_speed = 200
• Trong python cả lớp và đối tượng đều có một thuộc tính đặc biệt là __dict__ chứa các thuộc tính và phương thức
của lớp đó.
• Khi truy xuất thành phần của lớp hoặc đối tượng, python tìm tên thành phần này trong __dict__, nếu không có sẽ
trả về lỗi AttributeError hoặc NameError
# sample_dict.py
class SampleClass: print(SampleClass.class_attr)
class_attr = 100 print(SampleClass.__dict__)
def __init__(self, instance_attr): print(SampleClass.__dict__["class_attr"])
self.instance_attr = instance_attr
def method(self):
print(f"Class attribute: {self.class_attr}")
print(f"Instance attribute: {self.instance_attr}")
• Getter là một phương thức cho phép truy cập một thuộc tính trong một lớp nhất định
• Setter là một phương thức cho phép thay đổi giá trị của mộ thuộc tính trong một lớp
• Nên được thiết lập cho những thuộc tính cần ràng buộc điều kiện khi muốn gán hoặc truy xuất giá trị, các thuộc
tính này thường được sử dụng nội bộ trong lớp.
• Các phép toán số học +, -, *, / tương tứng với các magic method __add__(), __sub__(), __mul__(), __div__(). Phép toán
âm (-) dương (+) tương tứng với __pos__(), __neg__().
• Do đó, để định nghĩa cách thức xử lý cho các phép toán này, cần định nghĩa (ghi đè) magic method tương ứng.
class Vector: # định nghĩa lại toán tử cách thức xử lý của vector
"""A class for vector"""
def __init__(self, x:float, y:float): def __sub__(self, v):
self.x = x; self.y = y x = self.x - v.x; y = self.y - v.y
def __str__(self):
return Vector(x, y)
return f'({self.x}, {self.y})'
def __mul__(self, n):
def __repr__(self):
x = self.x * n; y = self.y * n
return f'({self.x}, {self.y})’
def __add__(self, v): return Vector(x, y)
x = self.x + v.x; y = self.y + v.y def __neg__(self):
return Vector(x, y) return Vector(self.x * -1, self.y * -1)
• Kế thừa là cách thức tạo ra một lớp mới mà sử dụng lại các thành phần của một lớp hiện có.
• Lớp mới hình thành được gọi là lớp dẫn xuất – derived class (hoặc lớp con, subclass), lớp được kế thừa là lớp cơ
sở - base class (hoặc lớp cha, superclass)
Cú pháp:
class DerivedClassName(BaseClassName):
<statement-1>
...
<statement-N>
Nếu lớp cơ sở định nghĩa ở module khác
class DerivedClassName(modname.BaseClassName):
Đa kế thừa
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
...
<statement-N>
Nhập môn lập trình Python (IPPA23327)
OOP TRONG PYTHON – KẾ THỪA (INHERITANCE)
• Hạn chế quyền truy cập phương thức và thuộc tính trong lớp từ đó giúp cho việc che giấu dữ liệu (data hiding)
• Nên thiết lập các thành phần của lớp ở chế độ private (riêng tư) thông qua dấu gạch dưới (_) hoặc (__)
• Các thuộc tính và phương thức private sẽ không thể được sử dụng bên ngoài lớp chứa chúng
Ví dụ: david = Person()
class Person: print("Age of david: ", end='')
def __init__(self): david.showAge()
self.__age = 20 david.__age = 99
def showAge(self): print("Age of david after david.__age = 99: ", end='')
print(self.__age) david.showAge()
def setAge(self, age): david.setAge(99)
self.__age = age print("Age of david after david.setAge(99): ", end='')
david.showAge()
• Các đối tượng và phương thức giống nhau có thể có các hành vi khác nhau tùy vào từng tình huống khác nhau
• Cho phép định nghĩa các phương thức ở lớp con cùng tên với phương thức ở lớp cha
• Nếu phương thức lớp con giống hoàn toàn với lớp cha thì gọi là ghi đè (override) phương thức lớp cha
class Bird: obj_bird = Bird()
def intro(self):
obj_eag = Eagle()
print("This is bird")
def flight(self): obj_haw = Hawks()
print("Flying method") obj_bird.intro() # This is bird
class Eagle(Bird): obj_bird.flight() # Flying method
def flight(self):
obj_eag.intro() # This is bird
print("Eagle Flying")
obj_eag.flight() # Eagle Flying
class Hawks(Bird):
def flight(self): obj_haw.intro() # This is bird
print("Hawks Flying") obj_haw.flight() # Hawks Flying
• Lớp trừu tượng là một lớp không được khởi tạo trực tiếp và được sử dụng như một lớp cơ sở cho các lớp khác.
• Phương thức trừu tượng được khai báo trong lớp trừu tượng nhưng không được cài đặt cụ thể, công việc này sẽ
dành cho các lớp con kế thừa triển khai.
Ví dụ:
from abc import ABC, abstractmethod
class MyAbstractClass(ABC):
@abstractmethod
def my_abstract_method(self):
pass
• Python sẽ hủy các đối tượng mà không cần dùng đến (các kiểu hoặc instance) một cách tự động để giải phóng
không gian bộ nhớ, tiến trình này được gọi là Garbage Collection được thực hiện bởi Garbage Collector
• Trình dọn rác của Python chạy trong khi thực thi chương trình và được kích hoạt khi số tham chiếu của đối tượng
tiến về 0.
• Số tham chiếu thay đổi khi số alias mà trỏ đến nó thay đổi. Số tham chiếu tăng khi được gán một tên mới hoặc đặt
trong một container mới (list, tuple, dictionary,…) và giảm khi nó bị xóa bởi lệnh del, tham chiếu của nó được tái
gán, hoặc thoát ra khỏi phạm vi
• Lớp có một phương thức __del__(), còn gọi là destructor được gọi khi instance chuẩn bị được hủy
Ví dụ:
a = 40 # Create object <40>
b = a # Increase ref. count of <40>
c = [b] # Increase ref. count of <40>
del a # Decrease ref. count of <40>
b = 100 # Decrease ref. count of <40>
c[0] = -1 # Decrease ref. count of <40>
__del__() destructor này in tên lớp của một instance mà chuẩn bị được hủy.
class Point: pt1 = Point()
def __init__( self, x=0, y=0): pt2 = pt1
self.x = x pt3 = pt1
self.y = y # prints the ids of the objects
def __del__(self): print id(pt1), id(pt2), id(pt3)
class_name = self.__class__.__name__ del pt1
print class_name, "destroyed" del pt2
del pt3
Kết quả sau:
3083401324 3083401324 3083401324
Point destroyed
1. Điền … để khai báo một lớp với tên my_class? 3. Điền … để sử dụng cls1 in ra giá trị của x?
… my_class: class my_class:
x = 5 x = 5
[class] cls1 = my_class()
2. Điền … để tạo một đối tượng của lớp my_class với tên print(…)
cls1: [cls1.x]
class my_class: 4. Điền … để gán hàm “init” cho một lớp?
x = 5 class Person:
… = … def … (self, name, age):
[cls1] [my_class()] self.name = name
self.age = age
[__init__]
5. Điền … để tạo một lớp Student kế thừa từ lớp Person: 6. Sử dụng lớp Student tạo ra đối tượng với tên std. Điền
class … : cú pháp vào … thích hợp để in ra tên của đối tượng std?
[Student(Person)] class Person:
def __init__(self, fname):
self.firstname = fname
def printname(self):
print(self.firstname)
class Student(Person):
pass
x = Student("Mike")
[…]
[std.printname()]