class ListBasedSet(collections.Set):
"""Alternate set implementation favoring space over speed
and not requiring the set elements to be hashable.
"""
def __init__(self, iterable):
self.elements = lst = []
for value in iterable:
if value not in lst:
lst.append(value)
def __iter__(self):
return iter(self.elements)
def __contains__(self, value):
return value in self.elements
def __len__(self):
return len(self.elements)
s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2
class Effable(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def __str__(self):
raise NotImplementedError('users must define __str__ to use this base class')
或者在Python 3中,元类声明有一点变化:
class Effable(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def __str__(self):
raise NotImplementedError('users must define __str__ to use this base class')
现在,如果我们尝试在不实现接口的情况下创建一个effable对象:
class MyEffable(Effable):
pass
并尝试将其实例化:
>>> MyEffable()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MyEffable with abstract methods __str__
我们被告知我们还没有完成这项工作。
现在,如果我们通过提供预期的接口来遵守:
class MyEffable(Effable):
def __str__(self):
return 'expressable!'
class Abstract1( object ):
"""Some description that tells you it's abstract,
often listing the methods you're expected to supply."""
def aMethod( self ):
raise NotImplementedError( "Should have implemented this" )
Abstract Base Classes (abbreviated
ABCs) complement duck-typing by
providing a way to define interfaces
when other techniques like hasattr()
would be clumsy. Python comes with
many builtin ABCs for data structures
(in the collections module), numbers
(in the numbers module), and streams
(in the io module). You can create
your own ABC with the abc module.
对象的接口是该对象上的一组方法和属性。
在Python中,我们可以使用抽象基类来定义和实施接口。
使用抽象基类
例如,假设我们要使用
collections
模块中的一个抽象基类:如果我们尝试使用它,就会得到一个
TypeError
,因为我们创建的类不支持集合的预期行为:因此,我们需要至少在实现
__contains__
、__iter__
和__len__
。让我们使用documentation中的这个实现示例:实现:创建抽象基类
通过将元类设置为
abc.ABCMeta
,并在相关方法上使用abc.abstractmethod
装饰符,我们可以创建自己的抽象基类。元类将向__abstractmethods__
属性添加修饰函数,在定义这些函数之前防止实例化。例如,“effable”被定义为可以用文字表达的东西。假设我们想在Python 2中定义一个可实现的抽象基类:
或者在Python 3中,元类声明有一点变化:
现在,如果我们尝试在不实现接口的情况下创建一个effable对象:
并尝试将其实例化:
我们被告知我们还没有完成这项工作。
现在,如果我们通过提供预期的接口来遵守:
然后我们可以使用从抽象类派生的类的具体版本:
我们还可以做其他事情,比如注册已经实现这些接口的虚拟子类,但我认为这超出了这个问题的范围。然而,这里演示的其他方法必须使用
abc
模块来调整此方法。结论
我们已经演示了抽象基类的创建定义了Python中自定义对象的接口。
你有时会看到以下情况:
因为Python没有(也不需要)正式的接口契约,所以抽象和接口之间不存在Java风格的区别。如果有人努力定义一个正式接口,它也将是一个抽象类。唯一的区别在于docstring中声明的意图。
抽象和接口之间的区别是,当你使用duck类型时,这是一件令人毛骨悚然的事情。
Java使用接口,因为它没有多重继承。
因为Python有多个继承,所以您还可能看到如下内容
这使用一种带有mixin的抽象超类来创建不相交的具体子类。
Python>;=2.6有Abstract Base Classes。
还有Zope Interface模块,它被zope以外的项目使用,比如twisted。我不是很熟悉,但是有一个wiki页面here可能会有帮助。
一般来说,您不需要抽象类的概念,也不需要python中的接口(已编辑-请参阅S.Lott的答案了解详细信息)。
相关问题 更多 >
编程相关推荐