Python第八週 學習筆記(1)

繼承


  • 基本概念個體繼承自父母,繼承了父母的一部分特徵,但也可以有自己的個性
  • 子類繼承了父類,就直接擁有了父類的屬性和方法,也可以定義自己的屬性、方法,甚至對父類的屬性、方法進行重寫

Python繼承實現

  • class Cat(Animal) 括號中爲該類的父類列表

  • 如果類定義時沒有父類列表,則只繼承object類
  • object類是所有類的祖先類

類的特殊屬性與方法

  • base
    • 類的基類
  • bases
    • 類的基類的元組
  • mro
    • 方法解析時的類的查找順序,返回元組
  • mro()
    • 作用同上,返回列表
  • subclasses()
    • 返回類的子類的列表

Python繼承中的注意事項

  • 屬於父類的私有成員,子類即使與父類存在繼承關係也不可直接訪問(可通過改名後的屬性名訪問,但慎用)
  • 例子:

class Animal:
    __count=100
    heigtht=0

    def showcount3(self):
        print(self.__count)

class Cat(Animal):
    name='cat'
    __count=200

c=Cat()
c.showcount3()

結果爲100

因爲子類調用了父類獲取父類私有變量的方法 self.count的count作用域是在父類下的,其真正調用的self._Animal__count,而這個屬性只有父類有

  • 解決的辦法:自己私有的屬性,用自己的方法讀取和修改,不要藉助其他類的方法,即使是父類或派生類的方法

屬性查找順序

  • 實例dict -> 類dict -> 父類dict

多繼承

Mixin

  • 本質是多繼承
  • 體現的是一種組合的設計模式

Mixin類使用原則

  • 類中不應該顯示的出現init初始化方法
  • 通常不能獨立工作,因爲它是準備混入別的類中的部分功能實現
    其祖先類也應是Mixin類

  • 使用Mixin時,其通常在繼承列表的第一個位置

  • 裝飾器實現

def printable(cls):
    def _print(self):
        print(self.content, 'decorator')

    cls.print = _print
    return cls

class Document:
    def __init__(self, content):
        self.content = content

class Word(Document):
    pass

class Pdf(Document):
    pass

@printable
class PrintableWord(Word): pass

print(PrintableWord.__dict__)
print(PrintableWord.mro())

pw = PrintableWord('test string')
pw.print()

@printable
class PrintablePdf(Word):
    pass
  • 優點:
    • 簡單方便,在需要的地方動態增加,直接使用裝飾器

Mixin實現


class Document:
    def __init__(self, content):
        self.content = content

class Word(Document):
    pass

class Pdf(Document):
    pass

class PrintableMixin:
    def print(self):
        print(self.content, 'Mixin')

class PrintableWord(PrintableMixin, Word):
    pass

print(PrintableWord.__dict__)
print(PrintableWord.mro())

pw = PrintableWord('test string')
pw.print()

class SuperPrintableMixin(PrintableMixin):
    def print(self):
        print('~' * 20)
        super().print()
        print('~' * 20)

class SuperPrintablePdf(SuperPrintableMixin, Pdf):
    pass

print(SuperPrintablePdf.__dict__)
print(SuperPrintablePdf.mro())

spp = SuperPrintablePdf('super print pdf')

spp.print()

Mixin類和裝飾器

  • 這兩種方式都可以使用,看個人喜好
  • 如果還需要繼承就得使用Mixin類

二分法


  • 序列必須有序
  • 時間複雜度O(logn)

lst = [37, 99, 73, 48, 47, 40, 40, 25, 99, 51]

lst.sort()

def bi_insert(lst, value):
    high = len(lst)
    low = 0
    while low < high:
        mid = (low + high) // 2

        if value > lst[mid]:
            low = mid + 1
        else:
            high = mid - 1

    lst.insert(low, value)

bi_insert(lst, 100)
bi_insert(lst, 40)
print(lst)

bisect模塊

  • bisect.bisect_left(a, x, lo=0, hi=len(a))

    • 查找在有序列表a中插入x的index,lo和hi用於指定列表的區間,默認是整個列表
    • 如果x已經存在,在其左邊插入,返回值爲index
  • bisect.bisect_right(a, x, lo=0, hi=len(a))

    • 與bisect_right類似,如果x已經存在,在其右邊插入
  • bisect.insort_left(a, x, lo=0, hi=len(a))

    • 在有序列表a中插入x
  • bisect.insort_right(a, x, lo=0, hi=len(a))
    • 和insort_left函數類似,如果x已經存在,在其右邊插入

習題

  • 判斷學生成績,成績等級A-E,90分以上爲A,80-89爲B,70-79爲C,60-69爲D,60以下爲E

import bisect

def get_grade(score):
    breakpoints =  [60, 70, 80, 90]
    grades = 'EDCBA'

    return grade[bisect.bisect(breakpoints, score)]

for x in (50,60,69,79,85,100):
    print('{} -> {}'.format(x,get_grade(x)))

魔術方法


dir

  • 返回類或者對象的所有成員名稱列表。
  • dir()就是調用dir()
  • 如果提供dir(),則返回屬性列表,否則會盡量從dict屬性中收集信息

  • dir()對於不同類型的對象具有不同的行爲:
    • 如果對象是模塊對象,返回的列表包含模塊的屬性名
    • 如果對象是類型或者類對象,返回的列表包含類的屬性名,及它的基類屬性名
    • 否則,返回列表包含對象的屬性名、它的類的屬性名和類的基類的屬性名

魔術方法分類

1.創建、初始化與銷燬

  • initdel

2.hash

  • 內建函數hash()調用的返回值,返回一個整數。
  • 如果定義這個方法,則該類的實例可hash

eq

  • 對應==,判斷兩個對象是否相等,返回bool類型

  • 對象去重時

    • 先判斷hash值,如果hash值相等(hash衝突),再調用eq方法判斷
  • 去重一定需要t提供eq方法

  • list、bytesarray,dict等不可hash的實例是因爲他們的類的封裝裏有 hash = None

習題

  • 設計二維座標類Point,使其成爲可hash類型,並比較兩個座標實例是否相等

3.bool

  • 內建函數bool(),或者對象放在邏輯表達式的位置,返回bool類型
  • 如果沒有定義bool(),就找len()返回長度,非0爲True。
  • 如果len()也沒有定義,那麼所有實例都返回True

4.可視化

repr

  • 內建函數repr()對一個對象獲取字符串表達
  • 返回字符串
  • 如果沒有定義,就直接返回object的repr()

str

  • str()、format()、print()調用,返回字符串
  • 如果沒有定義,就調用repr方法,如果__repr_沒有定義,直接返回對象內存地址信息

bytes

  • bytes()調用,返回bytes類型

5.運算符重載

  • <,<=,==,>,>=,!=

    • lt,le,eq,gt,ge,ne
  • +,-,*,/,%,//,**,divmod

    • add,sub,mul,truediv,mod,floordiv,pow,divmod
  • +=,-=,*=,/=,%=,//=,**=

    • iadd,isub,imul,itruediv,imod,ifloordiv,ipow
  • 一般只實現eq;lt,gt實現其一,le,ge實現其一 即可

習題 完成Point類,實現判斷點相等,並完成向量加法

6.容器和大小

len

  • len()會調用此方法
  • bool()調用時,如果沒有bool方法,則調用len,返回非0爲True

iter

  • 迭代時調用,返回迭代器對象

contains

  • in 調用,如果沒實現,就調用iter遍歷

getitem

  • 實現self[key]

setitem

  • getitem類似

missing

  • dict類調用getitem時 key不存在,調用此方法

習題 改造購物車類成方便操作的容器類

7.可調用對象

call

  • 在類中定義此方法後,實例可調用

習題 實現斐波那契類,對象可調用

class Fibonacci:
    def __init__(self):
        self.lst = [0, 1, 1]

    def __call__(self, index):
        if index < 0:
            raise Exception()
        self.generator(index)
        return self[index]

    def __len__(self):
        return len(self.lst)

    def __iter__(self):
        # yield from self.lst
 return iter(self.lst)

    def __getitem__(self, item):
        return self.lst[item]

    def generator(self, index):
        for i in range(len(self), index + 1):
            self.lst.append(self[i - 1] + self[i - 2])

8.上下文管理

  • with ... as語法

  • 實現enterexit方法,就屬於上下文管理對象

    enter

  • 如果存在該方法,with語法會把該方法的返回值作爲綁定到as子句中指定的變量上

exit(self, exc_type, exc_value, traceback)

  • 退出上下文時調用
  • exc_type 異常類型
  • exc_value 異常描述
  • traceback 異常追蹤信息
  • exit返回值爲等效True的值,則壓制異常

  • 應用場景:
    • 增強功能
    • 資源管理
    • 權限驗證

contextlib.contextmanager

  • 裝飾器

習題 爲函數執行計時

9.反射

  • 運行時,區別於編譯時,指程序被加載到內存中執行的時候
  • 運行時獲取類型信息

10.描述器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章