2013-06-13 75 views
5

Cách tốt nhất trong Python để bắt chước các hàm ảo ảo và thuần túy như trong C# là gì?Chức năng ảo Mimic (thuần) ảo như C#

Hiện nay tôi sử dụng một sơ đồ như:

class AbstractClass(object): 
    '''Abstract class''' 
    def __init__(self): 
     assert False, 'Class cannot be instantiated' 

    def _virtual_init(self): 
     print 'Base "constructor"' 

    def pure_virtual_function(self): 
     assert False, 'Pure virtual function should be derived' 

    def virtual_function(self): 
     print 'Base: virtual function' 

class Derived1(AbstractClass): 
    '''All functions derived''' 
    def __init__(self): 
     print 'Derived1: constructor' 
     AbstractClass._virtual_init(self) 

    def pure_virtual_function(self): 
     print 'Derived1: pure virtual function' 

    def virtual_function(self): 
     print 'Derived1: virtual function' 

class Derived2(AbstractClass): 
    '''Pure virtual method missing.''' 
    def __init__(self): 
     print 'Derived2: constructor' 
     AbstractClass._virtual_init(self) 

    def virtual_function(self): 
     print 'Derived3: virtual function' 

class Derived3(AbstractClass): 
    '''Virtual method missing (use base class)''' 
    def __init__(self): 
     print 'Derived3: constructor' 
     AbstractClass._virtual_init(self) 

    def pure_virtual_function(self): 
     print 'Derived3: pure virtual function' 


# ab = AbstractClass() # Gives error -> OK 

print 'DERIVED 1'  
dv1 = Derived1() 
dv1.pure_virtual_function() 
dv1.virtual_function() 

print 'DERIVED 2'  
dv2 = Derived2() 
# dv2.pure_virtual_function() # Gives error: Pure virtual function should be derived -> OK 
dv2.virtual_function() 

print 'DERIVED 3'  
dv3 = Derived3() 
# dv3.pure_virtual_function() # Gives error: Pure virtual function should be derived -> OK 
dv3.virtual_function() 

tôi nhận được như đầu ra:

DERIVED 1 
Derived1: constructor 
Base "constructor" 
Derived1: pure virtual function 
Derived1: virtual function 
DERIVED 2 
Derived2: constructor 
Base "constructor" 
Derived3: virtual function 
DERIVED 3 
Derived3: constructor 
Base "constructor" 
Derived3: pure virtual function 
Base: virtual function 

Tuy nhiên câu hỏi cụ thể của tôi là:

  1. Có một cách thanh lịch hơn để xác định một lớp cơ sở trừu tượng trong Python (2.7)? Giải pháp trên chỉ đưa ra một lỗi tại thời gian chạy (không phải ví dụ với pylint) Không có từ khoá 'trừu tượng' trong Python afaik.
  2. Có cách nào thanh lịch hơn để xác định phương pháp ảo thuần túy bằng Python (2.7) không? Một lần nữa, giải pháp trên chỉ đưa ra lỗi khi chạy.
  3. Có cách nào thanh lịch hơn để xác định phương thức ảo bằng Python (2.7) không? Không cần kiểm tra, nhưng không có từ khóa nào giống như 'ảo' trong Python afaik.

Xin cảm ơn trước.

+1

Tôi không hoàn toàn quen thuộc với các mẫu thiết kế này ... Nhưng việc đọc mã này nhắc tôi về mô-đun 'abc'. Bạn có thể muốn có một cái nhìn ở đó và xem nó cung cấp các chức năng mà bạn đang tìm kiếm. – mgilson

+1

Bạn sẽ không bao giờ gặp nhiều hơn lỗi thời gian chạy. Không có kiểm tra thời gian biên dịch để nói về, ngoài tính hợp lệ của cú pháp.(Mặc dù bạn có thể cố gắng * dạy * pylint để thực hiện các kiểm tra như vậy cho bạn.) Tốt hơn, ** quên ** về tất cả những công cụ thiết kế gọn gàng đó. Cứ làm đi. Xác định một vài lớp với giao diện tương thích nhưng không có kế thừa, vượt qua các trường hợp xung quanh, vv mà không cố gắng để có được máy tính để thực thi các bất biến như vậy. Dường như bạn đang suy nghĩ trong C#/Java. Điều đó dẫn đến kết quả đầu ra khủng khiếp của Python, giống như một tư duy Python sẽ tạo ra mã C#/Java khủng khiếp. – delnan

+0

Tại sao bạn làm điều này? Mỗi ngôn ngữ đều có cách làm riêng. Bạn không cần điều này trong python. – Lanaru

Trả lời

5

Tôi không chắc chắn chính xác những gì bạn có ý nghĩa khi bạn hỏi về phương pháp ảo, như trong Python tất cả các phương pháp là ảo. Và tôi cũng không chắc chắn lý do tại sao bạn đang sử dụng _virtual_init thay vì __init__ ... chỉ cần đổi tên một phương thức mua cho bạn thứ gì đó?

Cập nhật: Ah, tôi có một ý tưởng. Bạn có thể đã làm điều này để ngăn chặn sự khởi tạo của lớp cơ sở của bạn vẫn giữ chức năng khởi tạo trong đó. Câu trả lời ở đây là: buộc mọi thứ không phải là pythonic. Chỉ cần ghi lại rằng lớp này là trừu tượng (và có thể gọi nó là AbstractSmth).

Nói về lỗi thời gian chạy. Python là ngôn ngữ động, vì vậy, tốt, đó là cách hoạt động của ngôn ngữ đó. Một thành ngữ phổ biến đang tăng NotImplementedError trong __init__ để cho thấy rằng lớp của bạn là trừu tượng (và điều này cũng đúng cho các phương thức trừu tượng (thuần ảo)). Bạn cũng có thể có một cái nhìn tại abc như nó làm những gì bạn muốn: nó cấm instantiation của lớp trừu tượng. Nhưng tôi cũng khuyên bạn nên đọc PEP-3119 để hiểu Tóm tắt các lớp cơ sở trừu tượng và những gì chúng không phải là.

AFAIK, nâng cao NotImplementedError là đủ để bạn hiểu rằng lớp/phương pháp của bạn là trừu tượng.

+0

Tôi đang sử dụng _virtual_init thay vì __init__ vì tôi không muốn người dùng khởi tạo trực tiếp lớp trừu tượng. Nhưng mô-đun abc khắc phục được vấn đề này. Tài liệu kém hiệu quả hơn thực thi. Và tôi biết Python là một ngôn ngữ động, NotImplementedError thực sự tốt hơn một khẳng định. Cảm ơn bạn đã liên kết PEP-3119. –

0
class AbstractBaseClass(object): 
    def __init__(self): 
     if self.__class__.__name__ == 'AbstractBaseClass': 
      raise NotImplementedError("Can't instantiate AbstractBaseClass") 

class DerivedClass(AbstractBaseClass): 
    def __init__(self): 
     super().__init__() 
     # ... 

Ví dụ này cho thấy các lớp dẫn xuất (có thành viên __class__.__name__ khác nhau) có thể được khởi tạo và kế thừa các thuộc tính do AbstractBaseClass cung cấp. Nhưng nếu AbstractBaseClass được tạo trực tiếp, ngoại lệ NotImplementedError sẽ bị ném.

+1

Thêm một số nhận xét vào câu trả lời của bạn – HDJEMAI

Các vấn đề liên quan