測試樣本取自 《流暢的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__)
結果:
[, ]
(, , , )
可以看到 子孫類是列表 父類是元組,可能是父類已經是不可變的資料結構了,而子孫因為可擴充套件所以是可變資料結構 什麼是基類,什麼是父類
基類就是父類,派生類就是子類 你可以理解為生活中的父子關係,也就是說兒子繼承了所有的父親的樣貌特徵,但是兒子也有父親所沒有的一些特點 專業點講,就是子類可以繼承並使用父類的屬性和方法,也可以有自己的屬性和方法!不知道這麼說你能理解不?這裡又要講到一些繼承的特性 繼承使用繼承是為了減少 的冗餘,增強 ...
什麼是基類,什麼是父類
基類就是父類,派生類就是子類 你可以理解為生活中的父子關係,也就是說兒子繼承了所有的父親的樣貌特徵,但是兒子也有父親所沒有的一些特點 專業點講,就是子類可以繼承並使用父類的屬性和方法,也可以有自己的屬性和方法!不知道這麼說你能理解不?這裡又要講到一些繼承的特性 繼承使用繼承是為了減少 的冗餘,增強 ...
什麼是基類,什麼是派生類
基類就是父類,派生類就是子類 你可以理解為生活中的父子關係,也就是說兒子繼承了所有的父親的樣貌特徵,但是兒子也有父親所沒有的一些特點 專業點講,就是子類可以繼承並使用父類的屬性和方法,也可以有自己的屬性和方法!不知道這麼說你能理解不?這裡又要講到一些繼承的特性 繼承使用繼承是為了減少 的冗餘,增強 ...