Kể từ Python 2.6, với việc giới thiệu các lớp cơ sở trừu tượng, isinstance
(được sử dụng trên ABC, không phải lớp bê tông) hiện được coi là hoàn toàn chấp nhận được. Cụ thể là:
from abc import ABCMeta, abstractmethod
class NonStringIterable:
__metaclass__ = ABCMeta
@abstractmethod
def __iter__(self):
while False:
yield None
@classmethod
def __subclasshook__(cls, C):
if cls is NonStringIterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
Đây là một bản sao chính xác (chỉ thay đổi tên lớp) của Iterable
theo quy định tại _abcoll.py
(một chi tiết thi hành collections.py
) ... lý do này làm việc như bạn muốn, trong khi collections.Iterable
không , là sau này đi thêm dặm để đảm bảo chuỗi được coi là có thể lặp lại, bằng cách gọi Iterable.register(str)
một cách rõ ràng ngay sau tuyên bố class
này.
Tất nhiên thật dễ dàng để tăng thêm __subclasshook__
bằng cách trả lại False
trước cuộc gọi any
cho các lớp khác mà bạn muốn loại trừ cụ thể khỏi định nghĩa của mình.
Trong mọi trường hợp, sau khi bạn đã nhập khẩu mô-đun mới này như myiter
, isinstance('ciao', myiter.NonStringIterable)
sẽ False
và isinstance([1,2,3], myiter.NonStringIterable)
sẽ True
, cũng giống như bạn yêu cầu - và bằng Python 2.6 và sau này được coi là cách thích hợp để thể hiện như thế kiểm tra ... xác định một lớp cơ sở trừu tượng và kiểm tra isinstance
trên đó.
Nguồn
2009-06-28 19:11:24
Phiên bản nào của Python? Tôi tin rằng câu trả lời là khác nhau giữa 2. * và 3 –
Tôi đang sử dụng phiên bản 2.5 – priestc
Bạn được cho biết không chính xác, việc khôi phục không phải là hành vi không tốt. –