Đọc (read) file JSON với Python
1. JSON (JavaScript Object Notation) là gì? JSON (JavaScript Object Notation) là một định dạng (format)...
Kết quả sẽ mở trong tab mới, giới hạn trong website này.
Truy cập nhanh
Tìm kiếm gần đây
1. Đa kế thừa (multiple inheritance) trong Python Một lớp con có thể kế thừa từ nhiều hơn một lớp cha. Đó gọi là đa kế thừa (multiple inheritance). Tất cả các thuộc tính và phương thức của tất cả lớp cho được kế thừa bởi lớp con. Kết quả Trong ví dụ trên, lớp […]
Một lớp con có thể kế thừa từ nhiều hơn một lớp cha. Đó gọi là đa kế thừa (multiple inheritance). Tất cả các thuộc tính và phương thức của tất cả lớp cho được kế thừa bởi lớp con.
class Base1:
pass
class Base2:
pass
class MultiDerived(Base1, Base2):
pass
class Person:
def info(self):
print("Info of a person.")
class Employee:
def showSalary(self):
print("Salary of an employee.")
class Teacher(Person, Employee):
pass
john = Teacher()
john.info()
john.showSalary()
Info of a person.
Salary of an employee.
Trong ví dụ trên, lớp Teacher kế thừa từ lớp Person và Employee. Lớp Teacher sẽ kế thừa và sử dụng các phương thức info() và showSalary() từ 2 lớp trên.
Có trường hợp các lớp cha có những phương thức cùng tên với nhau và lớp con gọi những phương thức này. Vậy thì phương thức của lớp cha nào sẽ được thực thi khi lớp con gọi đến?
Python sử dụng Method Resolution Order (MRO) để quy định phương thức được gọi trong trường hợp này. MRO chỉ ra một thứ tự lớp nào được ưu tiên tìm và gọi phương thức trước. Chúng ta có thể sử dụng thuộc tính __mro__ hoặc hàm mro() để xem thứ tự này.
class Person:
def info(self):
print("Info of a person.")
def work(self):
print("A person works.")
class Employee:
def work(self):
print("An employee works.")
def showSalary(self):
print("Salary of an employee.")
class Teacher(Person, Employee):
pass
print(Teacher.__mro__)
john = Teacher()
john.work()
(<class '__main__.Teacher'>, <class '__main__.Person'>, <class '__main__.Employee'>, <class 'object'>)
A person works.
Trong ví dụ trên, lớp Person được ưu tiên tìm hàm work() để thực thi trước do thứ tự kế thừa class Teacher(Person, Employee).
class Person:
def info(self):
print("Info of a person.")
def work(self):
print("A person works.")
class Employee:
def work(self):
print("An employee works.")
def showSalary(self):
print("Salary of an employee.")
class Teacher(Employee, Person):
pass
print(Teacher.mro())
john = Teacher()
john.work()
(<class '__main__.Teacher'>, <class '__main__.Employee'>, <class '__main__.Person'>, <class 'object'>)
An employee works.
Trong ví dụ trên, lớp Employee được ưu tiên tìm hàm work() để thực thi trước do thứ tự kế thừa class Teacher(Employee, Person).
Lưu ý: Tất cả các lớp được tạo ra trong Python đều tự động kế thừa từ lớp object.
Chúng ta cũng có thể tạo ra một lớp mới bằng cách kế thừa từ một lớp con. Đó gọi là kế thừa nhiều cấp (multilevel inheritance). Python không giới hạn số cấp kế thừa.
Trong multilevel inheritance, tất cả thuộc tính và phương thức của lớp cha và lớp con sẽ được kế thừa bởi lớp con mới.
class Base:
def methodBase(self):
print("This is a method of Base.")
class Derived1(Base):
def methodDerived1(self):
print("This is a method of Derived1.")
class Derived2(Derived1):
def methodDerived2(self):
print("This is a method of Derived2.")
# create an object of Derived2
obj = Derived2()
# call method inherits from Base
obj.methodBase()
# call method inherits from Derived1
obj.methodDerived1()
# call method of Derived2
obj.methodDerived2()
This is a method of Base.
This is a method of Derived1.
This is a method of Derived2.
Trong ví dụ trên, lớp Derived1 kế thừa lớp Base. Lớp Derived2 kế thừa lớp Derived1. Lớp Derived2 sẽ kế thừa tất cả thuộc tính và phương thức của lớp Base và Derived1.
Trong đa kế thừa trong Python, lớp con sẽ kế thừa hàm __init__() của các lớp cha. Khi tạo một đối tượng của lớp con, hàm __init__() nào sẽ được gọi? Như chúng ta đã biết, Python sẽ sử dụng Method Resolution Order (MRO) để giải quyết vấn đề này. Nhưng khi đó, có một vấn đề xảy ra. Chúng ta cùng xem ví dụ sau đây để thấy rõ vấn đề này.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
class Employee:
def __init__(self, salary):
self.salary = salary
def showSalary(self):
print("salary:", self.salary)
class Teacher(Person, Employee):
pass
print(Teacher.mro())
john = Teacher("John", 35)
# call method inherits from Person
john.info()
# AttributeError: 'Teacher' object has no attribute 'salary'
john.showSalary()
[<class '__main__.Teacher'>, <class '__main__.Person'>, <class '__main__.Employee'>, <class 'object'>]
John, 35 years old.
Traceback (most recent call last):
File "c:\python-examples\main.py", line 20, in <module>
john.showSalary()
File "c:\python-examples\main.py", line 13, in showSalary
print("salary:", self.salary)
AttributeError: 'Teacher' object has no attribute 'salary'
Vấn đề ở đây là hàm __init__() sử dụng để tạo ra một object của lớp Teacher là được kế thừa từ lớp Person. Lúc này, các thuộc tính của đối tượng có được chỉ là name và age được kế thừa từ lớp Person mà không có thuộc tính salary từ lớp Employee. Giải pháp trong những trường hợp này là định nghĩa hàm __init__() cho lớp Teacher.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name + ",", self.age, "years old.")
class Employee:
def __init__(self, salary):
self.salary = salary
def showSalary(self):
print("salary:", self.salary)
class Teacher(Person, Employee):
def __init__(self, name, age, salary):
super().__init__(name, age)
self.salary = salary
# create an object of Teacher with it's __init__() function
john = Teacher("John", 35, "5000000")
# call method inherits from Person
john.info()
# call method inherits from Employee
john.showSalary()
John, 35 years old.
salary: 5000000
Trong ví dụ trên, chúng sử dụng câu lệnh super().__init__(name, age) để gọi hàm khởi tạo của lớp cha Person. Sau đó, chúng ta thêm thuộc tính salary cho các object của Teacher.