2013-12-15 13 views
9

Mục đích của việc kiểm tra self.__class__ là gì? Tôi đã tìm thấy một số mã tạo lớp giao diện trừu tượng và sau đó kiểm tra xem chính mã đó có phải là số self.__class__ hay không, ví dụ:Mục đích của việc tự kiểm tra là gì .__ class__? - python

class abstract1 (object): 
    def __init__(self): 
    if self.__class__ == abstract1: 
     raise NotImplementedError("Interfaces can't be instantiated") 

Mục đích của việc này là gì? Có phải để kiểm tra xem lớp học có phải là loại của chính nó không?

Mã này là từ http://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability-pysrc.html#ProbDistI

+1

Tôi nghĩ điều này đòi hỏi nhiều ngữ cảnh hơn. Bạn đã "tìm" mã này ở đâu? Nó cơ bản bị hỏng. – Iguananaut

+1

@Iguananaut: Tại sao nó bị hỏng? Nó hoạt động * tốt * khi được sử dụng như dự định; như một lớp cơ sở trừu tượng. –

+1

Tôi khá chắc chắn trước đó nó là một cái gì đó khác nhau? Tôi không biết - Tôi đồng ý, những gì trên đó bây giờ không bị hỏng. – Iguananaut

Trả lời

15

self.__class__ là tham chiếu đến loại loại của phiên bản hiện tại.

Đối với trường hợp của abstract1, mà muốn được là abstract1 lớp tự, đó là những gì bạn không muốn có một lớp trừu tượng. lớp trừu tượng chỉ có nghĩa là để được subclassed, không để tạo ra các trường hợp trực tiếp:

>>> abstract1() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in __init__ 
NotImplementedError: Interfaces can't be instantiated 

Đối với một thể hiện của một lớp con của abstract1, self.__class__ sẽ là một tham chiếu đến lớp con cụ thể:

>>> class Foo(abstract1): pass 
... 
>>> f = Foo() 
>>> f.__class__ 
<class '__main__.Foo'> 
>>> f.__class__ is Foo 
True 

Việc ném một ngoại lệ ở đây giống như sử dụng câu lệnh assert ở nơi khác trong mã của bạn, nó bảo vệ bạn khỏi những sai lầm ngớ ngẩn.

Lưu ý rằng pythonic cách để kiểm tra cho các loại một thể hiện là sử dụng type() function thay vào đó, cùng với một sắc thử nghiệm với is điều hành:

class abstract1(object): 
    def __init__(self): 
     if type(self) is abstract1: 
      raise NotImplementedError("Interfaces can't be instantiated") 

Có rất ít điểm trong bằng cách sử dụng một bài kiểm tra bình đẳng ở đây như đối với các lớp tùy chỉnh, __eq__ về cơ bản được triển khai như một bài kiểm tra nhận dạng.

Python cũng bao gồm thư viện chuẩn để xác định các lớp cơ sở trừu tượng, được gọi là abc. Nó cho phép bạn đánh dấu các phương thức và thuộc tính là trừu tượng và sẽ từ chối tạo các cá thể của bất kỳ lớp con nào chưa định nghĩa lại các tên đó.

1

Mã NLTK rằng bạn được đăng có một không-op; self.__class__ == c1 không phải là một phần của điều kiện để boolean được đánh giá nhưng không có gì được thực hiện với kết quả.

Bạn có thể cố gắng tạo lớp cơ sở trừu tượng để kiểm tra xem liệu self.__class__ có tương đương với lớp trừu tượng không trái với một đứa trẻ giả định (thông qua câu lệnh if) để ngăn chặn sự khởi tạo của lớp cơ sở trừu tượng do lỗi nhà phát triển.

+1

Mặc dù đối với các phiên bản mới hơn của Python, bạn chỉ nên sử dụng lớp cơ sở trừu tượng bằng cách sử dụng 'abc.ABCMeta'. – Iguananaut

+0

Một ABC vẫn có thể được khởi tạo trực tiếp. –

1

Tôi muốn nói rằng một số sẽ làm gì:

class Foo(AbstractBase): 
    def __init__(self): 
     super(Foo, self).__init__() 
     # ... 

Ngay cả khi cơ sở là trừu tượng, bạn sẽ không muốn của __init__ cơ sở để ném NotImplementedError. Hey, có lẽ nó thậm chí còn làm một cái gì đó hữu ích?

+0

Bạn đang nói rằng 'siêu (Foo, tự) .__ init __()' sẽ không hoạt động? Bởi vì điều đó không đúng; nó sẽ hoạt động * tốt thôi *. '__init__' của cơ sở sẽ * chỉ * ném ngoại lệ khi bản thân là một thể hiện của' AbstractBase', và không phải khi nó là một thể hiện của một lớp con như 'Foo'. –

0

Các đầu mối nằm trong tên của lớp, "abstract1" và trong lỗi. Đây là một lớp trừu tượng, có nghĩa là một lớp được dự định là lớp con. Mỗi phân lớp sẽ cung cấp hành vi riêng của nó. Bản thân lớp trừu tượng phục vụ để ghi lại giao diện, tức là các phương thức và đối số mà các lớp thực hiện giao diện được mong đợi có. Nó không có nghĩa là được tự khởi tạo, và phép thử được sử dụng để cho biết liệu chúng ta có ở trong chính lớp đó hay một lớp con.

Xem phần về Lớp học trừu tượng trong số article bởi Julien Danjou này.

1

Mục đích của điều đó là gì? Là nó để kiểm tra xem các lớp học là một loại của chính nó?

Có, nếu bạn cố gắng xây dựng một đối tượng kiểu Abstract1 nó sẽ ném ngoại lệ đó cho bạn biết rằng bạn không được phép làm như vậy.

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