Python中的抽象类和接口有什么区别?
发布于 2008-12-16 17:59:23
您有时会看到以下内容:
class Abstract1:
"""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")因为Python没有(也不需要)正式的接口契约,所以抽象和接口之间不存在Java风格的区别。如果有人努力定义一个正式的接口,它也将是一个抽象类。唯一的区别是文档字符串中声明的意图不同。
当你有鸭子类型时,抽象和接口之间的区别是令人费解的事情。
Java使用接口,因为它没有多重继承。
由于Python具有多重继承,因此您可能还会看到如下所示的内容
class SomeAbstraction:
pass # lots of stuff - but missing something
class Mixin1:
def something(self):
pass # one implementation
class Mixin2:
def something(self):
pass # another
class Concrete1(SomeAbstraction, Mixin1):
pass
class Concrete2(SomeAbstraction, Mixin2):
pass这使用了一种带有混合的抽象超类来创建互不相交的具体子类。
发布于 2015-07-16 03:15:20
中抽象类和接口的区别是什么?
对象的接口是该对象上的一组方法和属性。
在Python中,我们可以使用抽象基类来定义和执行接口。
使用抽象基类
例如,假设我们想要使用collections模块中的一个抽象基类:
import collections
class MySet(collections.Set):
pass如果我们尝试使用它,我们会得到一个TypeError,因为我们创建的类不支持sets的预期行为:
>>> MySet()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class MySet with abstract methods
__contains__, __iter__, __len__因此,我们至少需要实现__contains__、__iter__和__len__。让我们使用documentation中的这个实现示例
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实现:创建抽象基类
我们可以通过将元类设置为abc.ABCMeta并在相关方法上使用abc.abstractmethod装饰器来创建我们自己的抽象基类。元类将把修饰过的函数添加到__abstractmethods__属性中,在定义这些函数之前阻止实例化。
import abc例如,"effable“被定义为可以用语言表达的东西。假设我们想要定义一个抽象基类,在Python2中是可以表达的:
class Effable(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def __str__(self):
raise NotImplementedError('users must define __str__ to use this base class')或者在Python3中,对元类声明做了一些细微的更改:
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!'然后,我们可以使用从抽象类派生的具体版本:
>>> me = MyEffable()
>>> print(me)
expressable!我们还可以用它来做其他事情,比如注册已经实现这些接口的虚拟子类,但我认为这超出了这个问题的范围。但是,这里演示的其他方法必须使用abc模块来调整此方法。
结论
我们已经演示了抽象基类的创建为Python中的自定义对象定义了接口。
发布于 2008-12-16 17:51:35
Python >= 2.6有Abstract Base Classes。
hasattr抽象基类(
Abstract Base,简称ABC)通过提供一种方法来定义接口,从而补充了鸭子类型,而其他技术如hasattr()可能会很笨拙。Python附带了许多用于数据结构(在集合模块中)、数字(在数字模块中)和流(在io模块中)的内置ABC。您可以使用ABC模块创建自己的abc。
还有Zope Interface模块,它被zope之外的项目使用,比如twisted。我对它不是很熟悉,但是有一个维基页面的here可能会有帮助。
一般来说,您不需要抽象类的概念,也不需要python中的接口(编辑过的-详细信息请参阅S.Lott的回答)。
https://stackoverflow.com/questions/372042
复制相似问题