|
思想:角色的抽象、创建类、创建角色(实例化),操作这些实例。
面向对象的关键字:
class 类名:
静态属性 = ‘aaa’
def __init__(self):pass
类名.静态属性 #存储在类的命名空间里
对象=类名() # 实例化,创造了一个self对象,执行__init__方法,返回self对象给外部
对象.属性
对象.方法 # 绑定方法
对象可以使用静态变量,类不可以使用对象里的属性
组合:一个类的对象是另外一个类的属性,即什么是什么的关系
继承:什么有什么的关系,比如人有武器。
class A: def __init__(self): self.name = 'egon' class B: def __init__(self): self.year = 2018 self.month = 1 b=B() a=A() a.birth = b #只有当一个对象做了别人的属性的时候才叫做组合 print(a.birth.year)
面向对象的三大特性:继承、多态、封装
继承是一种创建新的类的方式,新创建的叫子类,继承的叫父类、超类、基类
特点:子类可以使用父类的属性(特征、技能)
继承是类与类之间的关系,一个类可以被多个类继承,一个类也可以继承多个父类——python类,使用__bases__方法可以获取子类继承的类。
class A:pass # 父类,基类,超类 class A(object):pass class B:pass # 父类,基类,超类 class A_son(A,B):pass # 子类,派生类 class AB_son(A):pass print(A_son.__bases__) print(AB_son.__bases__) print(A.__bases__) # python3 新式类 没有继承父类默认继承object ''' (<class '__main__.A'>, <class '__main__.B'>) (<class '__main__.A'>,) (<class 'object'>,) '''
减少代码冗余、提高重用性
继承了object的类以及该类的子类,都是新式类。在python3中如果一个类没有继承任何类,则默认继承object类。因此python3中都是新式类
没有继承object的类以及该类的子类,都是经典类。在python2中如果一个类没有继承任何类,不会继承object类,因此,只有篇python2中有经典类
概念:派生就是在子类继承父类的属性的基础上,派生出自己的属性。子类有不同于父类的属性,这个子类叫做派生类。通常情况下,子类和派生类是同一个概念,因为子类都是有不同于父类的属性,如果子类和父类属性相同,就没必要创建子类了。
class Animal: def __init__(self, name, hp, aggr): self.name = name self.hp = hp self.aggr = aggr def eat(self): print('吃药回血') class Dog(Animal): def __init__(self, name, hp, aggr, kind): Animal.__init__(self, name, hp, aggr) # self.kind = kind #派生属性 class Person(Animal): def __init__(self, name, hp, aggr, sex): Animal.__init__(self, name, hp, aggr) # self.sex = sex # 派生属性 jin = Dog('金老板',200,500,'teddy') alex = Person('alex',300,50,'女') print(jin.name) print(alex.name) ''' 金老板 alex '''
父类中没有的属性在子类中出现叫做派生属性
父类中没有方法在子类中出现叫做派生方法
主要是子类的对象调用,子类中有的名字一定用子类的,子类中没有才找父类,如果父类也没有就报错
如果父类子类都有的,用子类的
如果既想实现新的功能,也想实现父类原本的功能,还需要在子类中再调用父类或super().__init__().
super()不需要传self了,()里面已经默认传了,super()关键字只在新式类中才有,python3中所有的类都是新式类。super()是用来解决多重继承问题的,直接用类名调用父类方法在单继承的时候没有问题,但是如果使用多继承,会涉及到查找顺序(MRO),重复调用(钻石继承)等种种问题。总之前人留下的经验就是:保持一致性。要不全部用类名调用父类,要不全部用super,不要一半一半。
super()也可以在类外使用
如果还想用父类的,单独调用父类的
父类名.方法名 需要自己传self
正常代码中 单继承是为了减少代码的重复性
继承表达的是一种子类是父类的关系
class A: def func(self): print('A') class B: def func(self): print('B') class C: def func(self): print('C') class D(A,B,C):pass # def func(self):print('D') d = D() d.func() #A
class A: def func(self): print('A') class B(A): def func(self): print('B') class C(A): def func(self): print('C') class D(B,C):pass d = D() d.func() #B
class A: def func(self): print('A') class B(A):pass # def func(self): print('B') class E: def func(self): print('E') class C(E): def func(self): print('C') class D(B,C):pass d = D() d.func() #A print(D.mro()) #把继承顺序都给出来了
新式类中的继承顺序:广度优先
经典类:如果你直接创建一个类在python2.7中就是经典类,深度优先
在多继承中,我们子类的对象调用一个方法,默认的是就近原则,就近原则找的顺序是什么?
经典类中 深度优先
新式类中 广度优先
python2.7 新式类和经典类共有,新式类要继承object
python3 只有新式类 默认继承object
经典类和新式类还有一个区别 mro方法只有新式类中有
super()只在python3中有
super()的本质不是直接找父类,而是调用者节点。
class A(object): def func(self): print('A') class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() print('D') d = D() d.func() print(D.mro()) ''' A C B D [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] '''
class A(object): def func(self): print('A') class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() print('D') b = B() b.func() print(B.mro()) ''' A B [<class '__main__.B'>, <class '__main__.A'>, <class 'object'>] '''
小节:
继承:什么是什么的关系
单继承:*****
先抽象再继承,及各类之间的相同代码抽象出来,成为父类
子类自己没有的名字,就可以使用父类的方法和属性,如果子类自己有一定先用自己的
在类中用self的时候,一定要看清楚self指向谁
多继承:***
新式类和经典类
多继承寻找名字的顺序:新式类广度优先,经典类深度优先
在新式类中,有一个类名.mro()方法,查看广度优先的继承顺序
python3中有一个super方法,根据广度优先的继承顺序查找上一个类
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-10-19 21:57
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社