Preface
This module provides the infrastructure for defining abstract base classes (ABCs) in Python, as outlined in PEP 3119; see the PEP for why this was added to Python. (See also PEP 3141 and the numbers module regarding a type hierarchy for numbers based on ABCs.)
The collections module has some concrete classes that derive from ABCs; these can, of course, be further derived. In addition the collections module has some ABCs that can be used to test whether a class or instance provides a particular interface, for example, is it hashable or a mapping.
This module provides the following class:
class abc.ABCMeta
Classes created with a metaclass of ABCMeta have the following method:
- register(subclass)
- __subclasshook__(subclass)
For a demonstration of these concepts, look at this example ABC definition:
- from abc import *
- class Foo(object):
- def __init__(self, *values):
- self.values = []
- for val in values:
- self.values.append(val)
- def __getitem__(self, index):
- return self.values[index]
- def __len__(self):
- return len(self.values)
- def get_iterator(self):
- return iter(self)
- class Foo2(object):
- def __init__(self, *values):
- self.values = []
- for val in values:
- self.values.append(val)
- def __iter__(self):
- return iter(self.values)
- class MyIterable:
- __metaclass__ = ABCMeta
- @abstractmethod
- def __iter__(self):
- while False:
- yield None
- def get_iterator(self):
- return self.__iter__()
- @classmethod
- def __subclasshook__(cls, C):
- if cls is MyIterable:
- if any("__iter__" in B.__dict__ for B in C.__mro__):
- return True
- return NotImplemented
- MyIterable.register(Foo)
- #assert issubclass(Foo, MyIterable)
- #assert isinstance(Foo().get_iterator(), MyIterable)
- foo = Foo(1,2,3,4,5,'a','b','c')
- foo2 = Foo2(1,2,3,4,5,'a','b','c')
- for iter_obj in [foo, foo2]:
- print("\t[Info] Iterate %s object:" % iter_obj.__class__.__name__)
- for v in iter_obj:
- print("\t%s" % v)
- assert issubclass(Foo, MyIterable)
- assert issubclass(Foo2, MyIterable)
The __subclasshook__() class method defined here says that any class that has an __iter__() method in its __dict__ (or in that of one of its base classes, accessed via the __mro__ list) is considered a MyIterable too.
Finally, the line MyIterable.register(Foo) makes Foo a virtual subclass of MyIterable, even though it does not define an __iter__() method (it uses the old-style iterable protocol, defined in terms of __len__() and __getitem__()). Note that this will not make get_iterator available as a method of Foo, so it is provided separately. Also even through Foo2 doesn't get registered in MyIterable, because it has an __iter__() method, it will pass issubclass(Foo2, MyIterable) check.
From abc module, it also provides the following decorators:
abc.abstractmethod(function)
abc.abstractproperty([fget[, fset[, fdel[, doc]]]])
Below are sample code:
- # -*- coding: utf-8 -*-
- from abc import *
- class C:
- __metaclass__ = ABCMeta
- def __init__(self):
- print("Initialization of C...")
- #self.name='Test'
- def getname(self):
- return self.name
- def setname(self, value):
- self.name = value
- name = abstractproperty(getname, setname)
- class D(C):
- # Comment out below property will cause Error:
- # TypeError: Can't instantiate abstract class D with abstract methods name
- name = 'Test'
- def __init__(self):
- C.__init__(self)
- self.age=35
- print("Initialization of D...")
- d = D()
- print("Name=%s" % d.name)
- print("Age=%s" % d.age)
Supplement
* Python 3.1 快速導覽 - 函數 不定個數參數
* Build-in Types - Iterator Types
* The Definitive Guide on How to Use Static, Class or Abstract Methods in Python
沒有留言:
張貼留言