什麼是虛擬子類,抽象基類的原理

2021-09-25 08:00:07 字數 3731 閱讀 7494

測試樣本取自 《流暢的python>

先來了解抽象基類

import abc

class tombole(abc.abc):

@abc.abstractmethod

def pick(self):

'''隨機刪除元素,然後將其返回

'''@abc.abstractmethod

def load(self, iterable):

'''從可迭代物件中新增元素

:param iterable:

:return:

'''def inspect(self):

''':return:返回乙個有序陣列,有當前元素構成

'''items =

while true:

try:

except lookuperror:

break

self.load(items)

return tuple(sorted(items))

def loaded(self):

return bool(self.inspect())

抽象基類自定義要繼承 abc.abc, 因為此模組中有 抽象基類註冊的類屬性.

@abc.abstractmethod 是註冊抽象方法,不用實現方法,後續的子類會執行檢查實現. 若沒有實現則會報錯, 可以與其他裝飾器疊加,前提是 @abc.abstractmethod 必須在最內層

抽象類的意思本人理解是為 isinstance( ) issubclass( ) 的型別檢測而準備的, 與c++的虛基類類似, 父類指標可以指向子類,子類指標不可以指向父類, python中也是一樣的道理, 子類從屬於父類, 反之則不成立.

python最著名的鴨子型別, 同型別不必是父子 爺孫從屬關係,只需要實現相同的協議就可以, 協議是約定的特殊方法 比如__len_ _() 就可以在型別檢測中屬於同類, 本人理解 可以在 引數檢測中大量使用.

抽象基類的兩種繼承方法

有時需要進行檢測,務必實現所有協議 介面, 但是有時又不想讓其檢測, 因為抽象基類中必須有抽象方法, 意味著可以有已實現的方法, 就是說可以讓只繼承非抽象方法, 子類不實現抽象方法變得合法

#**接1

import random

class bingocage(tombole):

def __init__(self, items):

self._randomizer = random.systemrandom()

self._items =

self.load(items)

def load(self, items):

self._items.extend(items)

self._randomizer.shuffle(self._items)

def pick(self):

try:

return self._items.pop()

except indexerror:

raise lookuperror('pick from empty bingocage')

def __call__(self):

self.pick()

class lotteryblower(tombole):

def __init__(self, iterable):

self._balls = list(iterable)

def load(self, iterable):

self._balls.extend(iterable)

def pick(self):

try:

position = random.randrange(len(self._balls))

except valueerror:

raise lookuperror('pick from empty lotteryblower')

return self._balls.pop(position)

def loader(self):

return bool(self._balls)

def inspect(self):

return tuple(sorted(self._balls))

@tombole.register

class tombolist(list):

# def pick(self):

# if self:

# position = random.randrange(len(self))

# return self.pop(position)

# else:

# raise lookuperror('pop from empty tombolist')

## load = list.extend

def loaded(self):

return bool(self)

def inspect(self):

return tuple(sorted(self))

if __name__ == '__main__':

a = tombolist([1, 2, 3])

print(a.__dir__())

b = bingocage([1, 2, 3])

print(b.__dir__())

執行結果:

c:\users\lc\pycharmprojects\untitled\venv\scripts\python.exe c:/users/lc/pycharmprojects/untitled/learned/abcmodle_test.py

['_randomizer', '_items', '__module__', '__init__', 'load', 'pick', '__call__', '__doc__', '__abstractmethods__', '_abc_impl', 'inspect', 'loaded', '__dict__', '__weakref__', '__slots__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']

process finished with exit code 0

可以看到 例項a屬性並沒有實現 抽象方法 也能例項化, 而例項b就必須實現 抽象方法, #把實現的方法注釋掉了

檢視類的 父 子孫 類

每個類都有兩個特殊屬性, _subclasses _() _mro _() 分別按列表順序記錄了 子孫類和父類

#**接2

print(tombole.__subclasses__())

print(bingocage.__mro__)

結果:

[, ]

(, , , )

可以看到 子孫類是列表 父類是元組,可能是父類已經是不可變的資料結構了,而子孫因為可擴充套件所以是可變資料結構

什麼是基類,什麼是父類

基類就是父類,派生類就是子類 你可以理解為生活中的父子關係,也就是說兒子繼承了所有的父親的樣貌特徵,但是兒子也有父親所沒有的一些特點 專業點講,就是子類可以繼承並使用父類的屬性和方法,也可以有自己的屬性和方法!不知道這麼說你能理解不?這裡又要講到一些繼承的特性 繼承使用繼承是為了減少 的冗餘,增強 ...

什麼是基類,什麼是父類

基類就是父類,派生類就是子類 你可以理解為生活中的父子關係,也就是說兒子繼承了所有的父親的樣貌特徵,但是兒子也有父親所沒有的一些特點 專業點講,就是子類可以繼承並使用父類的屬性和方法,也可以有自己的屬性和方法!不知道這麼說你能理解不?這裡又要講到一些繼承的特性 繼承使用繼承是為了減少 的冗餘,增強 ...

什麼是基類,什麼是派生類

基類就是父類,派生類就是子類 你可以理解為生活中的父子關係,也就是說兒子繼承了所有的父親的樣貌特徵,但是兒子也有父親所沒有的一些特點 專業點講,就是子類可以繼承並使用父類的屬性和方法,也可以有自己的屬性和方法!不知道這麼說你能理解不?這裡又要講到一些繼承的特性 繼承使用繼承是為了減少 的冗餘,增強 ...