搜索
首页后端开发Python教程Python中定义和使用抽象类

Python中定义和使用抽象类

Mar 01, 2017 pm 01:49 PM
python抽象类

提起Java的抽象类大家都比较熟悉,Python中我们可以使用abc模块来构建抽象类,这里就为大家讲解在Python中定义和使用抽象类的方法

像java一样python也可以定义一个抽象类。

在讲抽象类之前,先说下抽象方法的实现。

抽象方法是基类中定义的方法,但却没有任何实现。在java中,可以把方法申明成一个接口。而在python中实现一个抽象方法的简单的方法是:

class Sheep(object):
  def get_size(self):
    raise NotImplementedError

任何从Sheep继承下来的子类必须实现get_size方法。否则就会产生一个错误。但这种实现方法有个缺点。定义的子类只有调用那个方法时才会抛错。这里有个简单方法可以在类被实例化后触发它。使用python提供的abc模块。

import abc
class Sheep(object):
  __metaclass__ = abc.ABCMeta
  
  @abc.absractmethod
  def get_size(self):
    return


这里实例化Sheep类或任意从其继承的子类(未实现get_size)时候都会抛出异常。

因此,通过定义抽象类,可以定义子类的共同method(强制其实现)。

如何使用抽象类

import abc 

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def load(self, input):
    return 

  @abc.abstractmethod
  def save(self, output, data):
    return

通过ABCMeta元类来创建一个抽象类, 使用abstractmethod装饰器来表明抽象方法

注册具体类

class B(object):
  
  def load(self, input):
    return input.read()

  def save(self, output, data):
    return output.write(data)

A.register(B)

if __name__ == '__main__':
  print issubclass(B, A)   # print True
  print isinstance(B(), A)  # print True

从抽象类注册一个具体的类

子类化实现

class C(A):

  def load(self, input):
    return input.read()

  def save(self, output, data):
    return output.write(data)
    
if __name__ == '__main__':
  print issubclass(C, A)   # print True
  print isinstance(C(), A)  # print True

可以使用继承抽象类的方法来实现具体类这样可以避免使用register. 但是副作用是可以通过基类找出所有的具体类

for sc in A.__subclasses__():
  print sc.__name__

# print C

如果使用继承的方式会找出所有的具体类,如果使用register的方式则不会被找出

使用__subclasshook__

使用__subclasshook__后只要具体类定义了与抽象类相同的方法就认为是他的子类

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def say(self):
    return 'say yeah'

  @classmethod
  def __subclasshook__(cls, C):
    if cls is A:
      if any("say" in B.__dict__ for B in C.__mro__):
        return True
    return NotTmplementd

class B(object):
  def say(self):
    return 'hello'

print issubclass(B, A)   # True
print isinstance(B(), A)  # True
print B.__dict__      # {&#39;say&#39;: <function say at 0x7f...>, ...}
print A.__subclasshook__(B) # True

不完整的实现

class D(A):
  def save(self, output, data):
    return output.write(data)

if __name__ == &#39;__main__&#39;:
  print issubclass(D, A)   # print True
  print isinstance(D(), A)  # raise TypeError

如果构建不完整的具体类会抛出D不能实例化抽象类和抽象方法

具体类中使用抽象基类

import abc 
from cStringIO import StringIO

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def retrieve_values(self, input):
    pirnt &#39;base class reading data&#39;
    return input.read()


class B(A):

  def retrieve_values(self, input):
    base_data = super(B, self).retrieve_values(input)
    print &#39;subclass sorting data&#39;
    response = sorted(base_data.splitlines())
    return response

input = StringIO("""line one
line two
line three
""")

reader = B()
print reader.retrieve_values(input)

打印结果

base class reading data
subclass sorting data
[&#39;line one&#39;, &#39;line two&#39;, &#39;line three&#39;]

可以使用super来重用抽象基类中的罗辑, 但会迫使子类提供覆盖方法.

抽象属性

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractproperty
  def value(self):
    return &#39;should never get here.&#39;

class B(A):
  
  @property
  def value(self):
    return &#39;concrete property.&#39;

try:
  a = A()
  print &#39;A.value&#39;, a.value
except Exception, err:
  print &#39;Error: &#39;, str(err)

b = B()
print &#39;B.value&#39;, b.value

打印结果,A不能被实例化,因为只有一个抽象的property getter method.

Error: ...
print concrete property

定义抽象的读写属性

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  def value_getter(self):
    return &#39;Should never see this.&#39;

  def value_setter(self, value):
    return 

  value = abc.abstractproperty(value_getter, value_setter)

class B(A):
  
  @abc.abstractproperty
  def value(self):
    return &#39;read-only&#39;

class C(A):
  _value = &#39;default value&#39;

  def value_getter(self):
    return self._value

  def value_setter(self, value):
    self._value = value

  value = property(value_getter, value_setter)

try:
  a = A()
  print a.value
except Exception, err:
  print str(err)

try:
  b = B()
  print b.value
except Exception, err:
  print str(err)

c = C()
print c.value

c.value = &#39;hello&#39;
print c.value

打印结果, 定义具体类的property时必须与抽象的abstract property相同。如果只覆盖其中一个将不会工作.

error: ...
error: ...
print &#39;default value&#39;
print &#39;hello&#39;

使用装饰器语法来实现读写的抽象属性, 读和写的方法应该相同.

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractproperty
  def value(self):
    return &#39;should never see this.&#39;

  @value.setter
  def value(self, _value):
    return 

class B(A):
  _value = &#39;default&#39;

  @property
  def value(self):
    return self._value

  @value.setter
  def value(self, _value):
    self._value = _value

b = B()
print b.value    # print &#39;default&#39;

b.value = &#39;hello&#39;
print b.value    # print &#39;hello&#39;


更多Python中定义和使用抽象类相关文章请关注PHP中文网!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
您如何切成python列表?您如何切成python列表?May 02, 2025 am 12:14 AM

SlicingaPythonlistisdoneusingthesyntaxlist[start:stop:step].Here'showitworks:1)Startistheindexofthefirstelementtoinclude.2)Stopistheindexofthefirstelementtoexclude.3)Stepistheincrementbetweenelements.It'susefulforextractingportionsoflistsandcanuseneg

在Numpy阵列上可以执行哪些常见操作?在Numpy阵列上可以执行哪些常见操作?May 02, 2025 am 12:09 AM

numpyallowsforvariousoperationsonArrays:1)basicarithmeticlikeaddition,减法,乘法和division; 2)evationAperationssuchasmatrixmultiplication; 3)element-wiseOperations wiseOperationswithOutexpliitloops; 4)

Python的数据分析中如何使用阵列?Python的数据分析中如何使用阵列?May 02, 2025 am 12:09 AM

Arresinpython,尤其是Throughnumpyandpandas,weessentialFordataAnalysis,offeringSpeedAndeffied.1)NumpyArseNable efflaysenable efficefliceHandlingAtaSetSetSetSetSetSetSetSetSetSetSetsetSetSetSetSetsopplexoperationslikemovingaverages.2)

列表的内存足迹与python数组的内存足迹相比如何?列表的内存足迹与python数组的内存足迹相比如何?May 02, 2025 am 12:08 AM

列表sandnumpyArraysInpyThonHavedIfferentMemoryfootprints:listSaremoreFlexibleButlessMemory-效率,而alenumpyArraySareSareOptimizedFornumericalData.1)listsStorReereReereReereReereFerenceStoObjects,withoverHeadeBheadaroundAroundaroundaround64bytaround64bitson64-bitsysysysyssyssyssyssyssyssysssys2)

部署可执行的Python脚本时,如何处理特定环境的配置?部署可执行的Python脚本时,如何处理特定环境的配置?May 02, 2025 am 12:07 AM

toensurepythonscriptsbehavecorrectlyacrycrossdevelvermations,登台和生产,USETHESTERTATE:1)Environment varriablesforsimplesettings,2)configurationFilesForefilesForcomPlexSetups,3)dynamiCofforAdaptapity.eachmethodofferSuniquebeneiquebeneiquebeneniqueBenefitsaniqueBenefitsandrefitsandRequiresandRequireSandRequireSca

您如何切成python阵列?您如何切成python阵列?May 01, 2025 am 12:18 AM

Python列表切片的基本语法是list[start:stop:step]。1.start是包含的第一个元素索引,2.stop是排除的第一个元素索引,3.step决定元素之间的步长。切片不仅用于提取数据,还可以修改和反转列表。

在什么情况下,列表的表现比数组表现更好?在什么情况下,列表的表现比数组表现更好?May 01, 2025 am 12:06 AM

ListSoutPerformarRaysin:1)DynamicsizicsizingandFrequentInsertions/删除,2)储存的二聚体和3)MemoryFeliceFiceForceforseforsparsedata,butmayhaveslightperformancecostsinclentoperations。

如何将Python数组转换为Python列表?如何将Python数组转换为Python列表?May 01, 2025 am 12:05 AM

toConvertapythonarraytoalist,usEthelist()constructororageneratorexpression.1)intimpthearraymoduleandcreateanArray.2)USELIST(ARR)或[XFORXINARR] to ConconverTittoalist,请考虑performorefformanceandmemoryfformanceandmemoryfformienceforlargedAtasetset。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器