当前位置:  开发笔记 > 编程语言 > 正文

Python中抽象类和接口的区别

如何解决《Python中抽象类和接口的区别》经验,为你挑选了6个好方法。

Python中的抽象类和接口有什么区别?



1> S.Lott..:

您有时会看到以下内容:

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" )

因为Python没有(并且不需要)正式的接口契约,所以抽象和接口之间的Java风格区别不存在.如果有人经历了定义正式接口的努力,那么它也将是一个抽象类.唯一的区别在于docstring中声明的意图.

当你打鸭子时,抽象和界面之间的区别是一个分裂的东西.

Java使用接口,因为它没有多重继承.

因为Python有多重继承,你可能也会看到类似的东西

class SomeAbstraction( object ):
    pass # lots of stuff - but missing something

class Mixin1( object ):
    def something( self ):
        pass # one implementation

class Mixin2( object ):
    def something( self ):
        pass # another

class Concrete1( SomeAbstraction, Mixin1 ):
    pass

class Concrete2( SomeAbstraction, Mixin2 ):
    pass

这使用一种带有mixins的抽象超类来创建不相交的具体子类.


`NotImplementedError("类%s没有实现aMethod()"%(self .__ class __.__ name __))`是更有用的错误信息:)
@ L.DeLeo - 你确定你的a-a与is-a的概念是否正确?我通常认为区别为has-a =成员变量与is-a =继承(父类*或*接口).用Java来思考Comparable或List; 这些是一种关系,无论它们是接口还是抽象类.
@Lorenzo a has-a relationship与继承,duck typing,接口和抽象类没有任何关系(所有四个都指的是-a关系).
S. Lott,你的意思是因为鸭子打字,has-a(接口)和is-a(继承)之间的区别是不是很大?
当你打鸭子时,抽象和界面之间的区别是一个分裂的东西.我不知道"实质性"意味着什么.从设计的角度来看,它是"真实的" - 它具有实质性.但从语言角度来看,可能没有任何支持.您可以采用约定来区分Python中的抽象类和接口类定义.

2> Aaron Hall..:
Python中的抽象类和接口有什么区别?

对象的接口是该对象上的一组方法和属性.

在Python中,我们可以使用抽象基类来定义和实施接口.

使用抽象基类

例如,假设我们要使用collections模块中的一个抽象基类:

import collections
class MySet(collections.Set):
    pass

如果我们尝试使用它,我们得到一个TypeError因为我们创建的类不支持集合的预期行为:

>>> MySet()
Traceback (most recent call last):
  File "", line 1, in 
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.ABCMeta并使用abc.abstractmethod装饰器来创建我们自己的抽象基类.元类将装饰函数添加到__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 "", line 1, in 
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模块来调整此方法.

结论

我们已经证明,Abstract Base Class的创建定义了Python中自定义对象的接口.



3> JimB..:

Python> = 2.6具有抽象基类.

抽象基类(缩写为ABC)通过提供一种定义接口的方法来补充鸭子类型,当其他技术如hasattr()将是笨拙的.Python附带了许多用于数据结构(在集合模块中)的内置ABC,数字(在数字模块中)和流(在io模块中).您可以使用abc模块创建自己的ABC.

还有Zope接口模块,由zope之外的项目使用,如twisted.我不是很熟悉,但有一个wiki页面在这里可能会有帮助.

通常,您不需要抽象类的概念,也不需要python中的接口(已编辑 - 请参阅S.Lott的答案以获取详细信息).


在Python中使用ABCs可以获得什么?

4> Douglas Leed..:

Python实际上没有任何一个概念.

它使用duck typing,这消除了对接口的需求(至少对于计算机:-))

Python <= 2.5:基本类显然存在,但没有明确的方法将方法标记为"纯虚拟",因此该类不是真正抽象的.

Python> = 2.6:确实存在抽象基类(http://docs.python.org/library/abc.html).并允许您指定必须在子类中实现的方法.我不太喜欢语法,但功能就在那里.大多数情况下,从'using'客户端使用duck typing可能更好.


Python 3.0确实添加了真正的抽象基类.它们用于集合模块以及其他地方.http://docs.python.org/3.0/library/abc.html

5> SilentSteel..:

用更基本的方式来解释:界面有点像空的松饼盘.它是一个包含一组没有代码的方法定义的类文件.

抽象类是相同的,但并非所有函数都需要为空.有些人可以有代码.它不是严格空的.

为什么要区分:Python中没有太多实际差异,但在大型项目的规划级别上,谈论接口可能更常见,因为没有代码.特别是如果您正在使用习惯于该术语的Java程序员.



6> Lara Dougan..:

通常,接口仅在使用单继承类模型的语言中使用.在这些单继承语言中,如果任何类可以使用特定方法或一组方法,则通常使用接口.同样在这些单继承语言中,除了没有或多个方法之外,抽象类还用于定义类变量,或者利用单继承模型来限制可以使用一组方法的类的范围.

支持多继承模型的语言倾向于仅使用类或抽象基类而不使用接口.由于Python支持多重继承,因此它不使用接口,您可能希望使用基类或抽象基类.

http://docs.python.org/library/abc.html

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有