python学习-6-面向对象

类与实例

  • 创建类的格式:
class Student(object): # class 类名(继承)
    pass
  • init()方法就是java中的构造器
  • 类中的self相当于java中的this,java不用显示声明,python中需要在参数列表中声明
    • 第一个参数一定是self

访问限制

  • 私有属性用双下划线__开头,只有内部可访问 (private)
    • 访问需要类提供get方法,这和java一样
      _ 修改就需要set方法
    • 实际上,并不是私有的,只是python解释器给属性改了一个名,变为._类名__属性名
  • python中双下划线开头与结尾的,都是特殊变量,一般不能用
  • 发现个好玩的,即使类中没有的属性,也是可以xx.xx = xx进行设置的,然后就可以使用了

继承

  • 继承会引发多态
    • 子类是父类,父类不是子类
    • 调用方只管调用,不管细节,无需知道子类型,从而尽可能满足开闭原则
  • java是静态语言,它在进行编译的时候就要来检查传入对象的类型是否合法
  • Python是动态语言,不需要保证类型完全,只需要它有本方法中需要的方法和属性就ok了
    • 鸭子类型,无需严格继承,只要 看起来像鸭子,走起来也像鸭子 就ok

对象信息

  • type(obj) 类型,指向函数
    • type(obj)
    • if type(xxx) == type(已知类型)
    • if type(xxx) == types.FunctionType 判断是否是函数…
  • instance(obj,已知类型) 判断类型是否相等
    • 返回True or False
    • 可用于继承
    • 判断是否是其中一种 instance(obj,(xxx,xxx))
  • dir(obj) 将所有方法 属性 字符串列表返回
  • len(obj) 获取对象的长度
    • 自动调用__len__()方法
    • 可以被复写
  • hasattr(obj,“xxx”) 是否拥有某种属性
    • 注意是字符串
  • getattr(obj,“xxx”,404) 最后一个参数是默认值,防止不存在报错
    • 方法和属性都是一样的,都用这个
  • setattr(obj,“xxx”,xx)
  • 结合上面的鸭子类型,可以使用对象信息来判断是否像鸭子
    • if hasattr(obj,“xxx”): …

实例属性与类属性

  • 实例可以任意绑定属性
    • 类没有定义name属性,但我可以 实例.name=xxx,然后用

slots

  • 作为动态语言,python可以给实例绑定方法与属性
  • 而给类动态的绑定,则可以对每个实例都适用,具体操作和实例的绑定一样
  • 为了限制绑定,需要__slots__
    • 其作为一个变量,可以定义 允许绑定的 属性名称
    • 其他属性是不能够绑定的
    • 对继承的子类无效

@property

  • 一般的属性都是不对外暴露的,所以需要getter方法,setter方法
    • 这样使用起来就很麻烦
  • 所以实际上可以使用 @property 来让get方法变成属性,然后使用 @属性.setter 注解setter方法
class Stu(Object):
    @property
    def score(self): # 该注解下就是属性名称
        return self.__score
    
    @score.setter
    def score(self,val):
        self.__score = val
  • 此时就可以直接 xx.属性 进行赋值与调用,不用写get赋值了,方便很多
    xx = Stu()
    xx.score = css
    print(xx.score)
  • 原理是装饰器
  • 注意 属性的方法名不要与 实际的属性名 相同
    • 如果相同,会发生 自环,从而导致无限递归,最终栈溢出
  • 注意这里的无论啥方法,名称都要统一,也就是你 注解定义了score,那么所有的方法也得叫score

多重继承

  • 多个类别交叉时,就会造成 类的层次复杂
  • 这点区别于java,java是单继承,然后使用接口来进行扩展
class Bat(Mammal,FlyableMixIn,XxxMinIn):
    pass
  • 同时继承多个父类的功能
  • 我们可以把继承的第一个类叫做主线,其他额外混入的类,称为MixIn

定制类

  • str() 打印实例信息,直接print即可,可自定义
  • repr() 打印实例信息,为调试服务
  • iter() 实现该方法,返回一个迭代对象,该类可用于 for…in,变成一个Iterable对象
    • 一般还要搭配一个__next__()方法来
  • getitem()可以将类当成list来使用,按下边访问元素
  • getattr()当有属性找不到时,python解释器就会调用该方法
  • call(),把实例对象当方法使用 xxx() 将对象看做是函数

枚举类

from enum import Enum

@unique #检查有无重复值
class Weekday(Enum):
    Sun = 0
    Mon = 1
    ...

print(Weekday.Mon) # 1

元类

from hello import Hello
h = Hello()
h.hello()
  • 其中,Hello是一个class,它的类型是type
  • h是Hello的实例,它的类型是Hello
  • type()可以返回一个实例的类型: type(obj)
  • type()也可以创建新的类型,此时就不需要再 class Hello(object)之类的麻烦定义
  • type(class名称,基继承的父类集合(tuple,),方法名)
def function(self): # 这里的self必须要有,因为要建类
    print("ok")

Hello = type("Hello",(object,),dict(hello=function))
h = Hello()
h.hello()
  • metaclass 元类
    • 对于类,首先我们定义类,然后创建实例
    • metacalss是类的元,先定义metaclass,然后创建类,然后创建实例
    • 类是metaclass的实例
    • 基本不会用,这个太抽象了,魔术代码