Python第八周 学习笔记(1)

发布时间:2019-09-07 08:12:04编辑:auto阅读(1518)

    继承


    • 基本概念个体继承自父母,继承了父母的一部分特征,但也可以有自己的个性
    • 子类继承了父类,就直接拥有了父类的属性和方法,也可以定义自己的属性、方法,甚至对父类的属性、方法进行重写

    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.描述器

关键字