Như đã giải thích trong các câu trả lời khác, có, bạn có thể sử dụng các lớp trừu tượng trong Python bằng abc
mô-đun . Dưới đây tôi đưa ra một ví dụ thực tế sử dụng trừu tượng @classmethod
, @property
và @abstractmethod
(sử dụng Python 3.6+). Đối với tôi thường dễ dàng hơn để bắt đầu với các ví dụ tôi có thể dễ dàng sao chép & dán; Tôi hy vọng câu trả lời này cũng hữu ích cho những người khác.
Trước tiên chúng ta hãy tạo một lớp cơ sở gọi là Base
:
from abc import ABC, abstractmethod
class Base(ABC):
@classmethod
@abstractmethod
def from_dict(cls, d):
pass
@property
@abstractmethod
def prop1(self):
pass
@property
@abstractmethod
def prop2(self):
pass
@prop2.setter
@abstractmethod
def prop2(self, val):
pass
@abstractmethod
def do_stuff(self):
pass
Base
Lớp của chúng ta sẽ luôn có a from_dict
classmethod
, a property
prop1
(chỉ đọc) và a property
prop2
(cũng có thể được đặt) cũng như một hàm được gọi do_stuff
. Bất cứ lớp nào được xây dựng dựa trên Base
sẽ phải thực hiện tất cả các lớp này cho các phương thức / thuộc tính. Xin lưu ý rằng để một phương thức trở nên trừu tượng, cần có hai trang trí - classmethod
và trừu tượng property
.
Bây giờ chúng ta có thể tạo một lớp A
như thế này:
class A(Base):
def __init__(self, name, val1, val2):
self.name = name
self.__val1 = val1
self._val2 = val2
@classmethod
def from_dict(cls, d):
name = d['name']
val1 = d['val1']
val2 = d['val2']
return cls(name, val1, val2)
@property
def prop1(self):
return self.__val1
@property
def prop2(self):
return self._val2
@prop2.setter
def prop2(self, value):
self._val2 = value
def do_stuff(self):
print('juhu!')
def i_am_not_abstract(self):
print('I can be customized')
Tất cả các phương thức / thuộc tính bắt buộc được triển khai và tất nhiên chúng ta có thể - cũng thêm các hàm bổ sung không phải là một phần của Base
(ở đây i_am_not_abstract
:).
Bây giờ chúng ta có thể làm:
a1 = A('dummy', 10, 'stuff')
a2 = A.from_dict({'name': 'from_d', 'val1': 20, 'val2': 'stuff'})
a1.prop1
# prints 10
a1.prop2
# prints 'stuff'
Theo mong muốn, chúng tôi không thể đặt prop1
:
a.prop1 = 100
sẽ trở lại
AttributionError: không thể đặt thuộc tính
Ngoài ra from_dict
phương pháp của chúng tôi hoạt động tốt:
a2.prop1
# prints 20
Nếu bây giờ chúng ta định nghĩa một lớp thứ hai B
như thế này:
class B(Base):
def __init__(self, name):
self.name = name
@property
def prop1(self):
return self.name
và cố gắng khởi tạo một đối tượng như thế này:
b = B('iwillfail')
chúng tôi sẽ nhận được một lỗi
TypeError: Không thể khởi tạo lớp B trừu tượng bằng các phương thức trừu tượng do_ ware, from_dict, prop2
liệt kê tất cả những điều được xác định trong Base
đó chúng tôi đã không thực hiện trong B
.