1. 程式人生 > >Python面向物件進階

Python面向物件進階

二分

  • 二分的前提是有序
  • 時間複雜度為O(log n)

bisect模組

  • bisect系,用於查詢index
    • bisect.bisect_left
    • bisect.bisect_right
  • insort系,用於實際插入
    • bisect.insort_left
  • 預設重複時從右邊插入

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

類的多繼承

  • 用途:在子類上實現對基類的增強、實現多型
  • OCP原則:多用繼承,少修改

在這裡插入圖片描述

Mixin類

  • 將其他類混合,同時帶來類的屬性和方法
  • Mixin類可以繼承,本質是多繼承實現的
  • 使用規則:
    • Mixin類中不顯式出現__init__初始化方法
    • 混入其他類中實現部分功能,無法獨立工作
    • Mixin
      類的祖先類也是Mixin
    • Mixin類通常在繼承列表中的第一個位置

在這裡插入圖片描述

在這裡插入圖片描述

魔術方法

在這裡插入圖片描述

在這裡插入圖片描述

  • hash值相同只是hash值衝突,物件不一定相等,使用set並不一定去重
  • 去重需要提供__eq__方法
  • list類例項原始碼中有__hash__ = None,則其不可hash

容器相關方法

  • __len__
    • 返回物件的長度,若無__bool__方法則檢視__len()__方法是否存在,存在返回非0為真;空字典空元組空集合空列表空字串長度為0,等效False
  • __iter__
    • 迭代容器,返回一個新的迭代器物件
  • __contains__
    • in成員運算子,未實現則呼叫__iter__
      方法遍歷
  • __getitem__
    • 實現self[key]訪問,keyhashable,不存在則KeyError異常
  • __setitem__
    • 設定值的方法
  • __missing__
    • 字典或其子類使用__getitem()__呼叫時,key不存在則執行此方法

可呼叫物件

  • __call__
    • 類中定義該方法,例項化得到其例項,則例項可像函式一樣呼叫
 # 定義fib數列的類

class Fib:
    def __init__(self):
        self.item = [0, 1, 1]
    def __call__(self, index):
        if index < 0:
            raise IndexError('Wrong Index')
        if index < len(self.item):
            return self.item[index]

        for i in range(3, index + 1):
            self.item.append(self.item[i-1] + self.item[i-2])
        return self.item[index]

print(Fib()(100))

上下文管理

# 將類作為裝飾器,使用上下文管理方法顯示函式執行時長

import time, datetime
from functools import wraps, update_wrapper

class TimeIt:
    '''This is A Class'''
    def __init__(self, fn):
        self.fn = fn
        # 把函式物件的文件字串賦值給類
        # self.__doc__ = fn.__doc__
        # update_wrapper(self, fn)
        wraps(fn)(self)
    def __enter__(self):
        self.start = datetime.datetime.now()
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.delta = (datetime.datetime.now() - self.start).total_seconds()
        print('{} took {} second(s).context'.format(self.fn.__name__,self.delta))
    def __call__(self, *args, **kwargs):
        self.start = datetime.datetime.now()
        ret = self.fn(*args, **kwargs)
        self.delta = (datetime.datetime.now() - self.start).total_seconds()
        print('{} took {} second(s).call'.format(self.fn.__name__,self.delta))
        return ret
@TimeIt
def add(x, y):
    '''This is add function'''
    time.sleep(3)
    return x + y
print(add(4, 5))
print(add.__doc__)
print(TimeIt(add).__doc__)

反射

  • 定義:通過一個物件,找出其type,class,attribute,method的能力
  • 反射能力的函式:type()isinstance()callable()dir()getattr()

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

描述器

在這裡插入圖片描述

在這裡插入圖片描述

  • 屬性查詢順序
    • 例項的__dict__優先於非資料描述器
    • 資料描述器優先於例項的__dict__
# 類staticmethod裝飾器

class StaticMethod:
    def __init__(self,fn):
        self.fn=fn
    def __get__(self, instance, owner):
        return self.fn
class A:
    @staticmethod
    def cmd():
        print('static method')
A.cmd() # static method
A().cmd() # static method
# 類staticmethod裝飾器

class StaticMethod:
    def __init__(self,fn):
        self.fn=fn
    def __get__(self, instance, owner):
        return self.fn
class A:
    @staticmethod
    def cmd():
        print('static method')
A.cmd()
A().cmd()
# 類classmethod裝飾器

class ClassMethod:
    def __init__(self, fn):
        self.fn = fn
    def __get__(self, instance, owner):
        ret = self.fn(owner)
        return ret
class A:
    @ClassMethod
    def clscmd(cls):
        print(cls.__name__)
print(A.__dict__)
A.clscmd