Python中抽象类和接口的区别是什么?
当前回答
抽象类是包含一个或多个抽象方法的类。除了抽象方法,抽象类还可以有静态方法、类方法和实例方法。 但在接口的情况下,它将只有抽象的方法没有其他。因此,继承抽象类不是强制性的,但继承接口是强制性的。
其他回答
Python实际上没有这两个概念。
它使用鸭子打字,这就不需要接口了(至少对计算机来说是这样的:-))
Python <= 2.5: 基类显然是存在的,但是没有显式的方法将一个方法标记为“纯虚”,因此类并不是真正抽象的。
Python >= 2.6: 抽象基类确实存在(http://docs.python.org/library/abc.html)。并允许您指定必须在子类中实现的方法。我不太喜欢它的语法,但它的特性是存在的。大多数情况下,从“using”客户端使用duck输入可能更好。
有时你会看到以下情况:
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没有(也不需要)正式的Interface契约,所以抽象和接口之间不存在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
这使用了一种带有mixin的抽象超类来创建分离的具体子类。
Python中抽象类和接口的区别是什么?
对于对象来说,接口是该对象上的一组方法和属性。
在Python中,我们可以使用抽象基类来定义和执行接口。
使用抽象基类
例如,假设我们想使用collections模块中的一个抽象基类:
import collections
class MySet(collections.Set):
pass
如果我们尝试使用它,我们会得到一个TypeError,因为我们创建的类不支持集合的预期行为:
>>> 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__。让我们使用文档中的实现示例:
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来创建自己的抽象基类。并使用abc。摘要方法装饰器的相关方法。元类将把修饰过的函数添加到__abstractmethods__属性中,在定义这些函数之前防止实例化。
import abc
例如,“effable”被定义为可以用文字表达的东西。假设我们想在Python 2中定义一个可描述的抽象基类:
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')
现在,如果我们尝试在不实现接口的情况下创建一个可描述对象:
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中创建抽象基类为自定义对象定义接口。
用更基本的方式解释: 界面有点像一个空的松饼盘。 它是一个类文件,带有一组没有代码的方法定义。
抽象类也是如此,但并非所有函数都需要为空。有些可以有代码。严格来说,它不是空的。
为什么区分: 在Python中没有太大的实际区别,但在大型项目的规划级别上,讨论接口可能更常见,因为没有代码。特别是当您与熟悉这个术语的Java程序员一起工作时。
抽象类是包含一个或多个抽象方法的类。除了抽象方法,抽象类还可以有静态方法、类方法和实例方法。 但在接口的情况下,它将只有抽象的方法没有其他。因此,继承抽象类不是强制性的,但继承接口是强制性的。
推荐文章
- 在Python中锁定文件
- 得到熊猫栏目的总数
- 从pandas DataFrame中删除名称包含特定字符串的列
- Mock vs MagicMock
- 如何阅读一个。xlsx文件使用熊猫库在iPython?
- 如何访问熊猫组由数据帧按键
- Pandas和NumPy+SciPy在Python中的区别是什么?
- 将列表转换为集合会改变元素的顺序
- 如何在matplotlib更新一个情节
- TypeError: ` NoneType `对象在Python中不可迭代
- 如何在Vim注释掉一个Python代码块
- python标准库中的装饰符(特别是@deprecated)
- 如何从外部访问本地Django web服务器
- 删除字符串的最后3个字符
- 在python中执行no-op的标准方法是什么?