Python Class 类的继承与多继承
1、继承概念
-
面向对象的三要素之一:继承
inheritance
-
在面向对象的世界中,从父类继承,就可以直接拥有父类的属性和方法,这样可以减少代码、多复用。子类可以定义自己的属性和方法
-
继承:
class
子类(父类) 这种形式就是从父类继承,括号中写上继承的类的列表。继承可以让子类从父类获取特征(属性和方法) -
父类:也称为 基类 超类
-
子类:也称为 派生类
-
定义:
class 子类名(基类1[, 基类2, ...]): 语句块
-
如果定义时,没有基类列表,等同于继承object
-
在Python3中, object类是所有对象的根基类
-
Python支持多继承,继承也可以多级
-
查看继承的特殊属性和方法有:
2、继承中的访问控制
- 从父类继承,自己没有的,就可以到父类中找
- 私有的都是不可以访问的,但是本质上依然是改了名称放在这个属性所在类或实例的
__dict__
中,知道这个新名称就可以直接找到这个隐藏的变量,这是个黑魔法技巧,慎用 - 继承时,共有的,子类和实例都可以随意访问;私有成员被隐藏,子类和实例不可直接访问,但私有变量所在的类内的方法中可以访问这个私有变量
- 私有属性最好只在当前类中使用,修改名称时,在哪个类里修改为哪个类的名称
- 实例属性查找顺序:
实例的__dict__ ===> 类__dict__ === 如果有继承 ===> 父类__dict
- 继承关系中,同一种方法,在不同的类中有不同的表现方法,这就叫
Python的多态
- 自己的私有属性,就该自己的方法读取和修改,不要借助其他类的方法,即使是父类或者派生类的方法
- 作为好的习惯,如果父类定义了
__init__
方法,就该在子类的__init__
中调用它
3、示例
3.1 示例 1
class Animal:
def __init__(self, name):
self._name = name
def shout(self):
print('{} shouts.'.format(self.__class__.__name__))
@property
def name(self):
return self._name
a = Animal('Monster')
a.shout() # Animal shouts.
a.name # 'Monster'
class Dog(Animal):
pass
dog = Dog('Maltese')
dog.shout() # Dog shouts.
dog.name # 'Maltese'
class Cat(Animal):
pass
cat = Cat('Garfield')
cat.shout() # Cat shouts.
cat.name # 'Garfield'
Cat.__base__ # __main__.Animal
Cat.__bases__ # (__main__.Animal,)
Cat.__mro__ # (__main__.Cat, __main__.Animal, object)
Cat.mro() # [__main__.Cat, __main__.Animal, object]
Animal.__subclasses__() # [__main__.Dog, __main__.Cat]
3.2 示例 2
看懂如下示例,继承就可以完全get
了。
class Animal:
__COUNT = 100 # _Animal__COUNT
HEIGHT = 0
def __init__(self, age, weight, height):
self.__COUNT += 1 # slef._Animal__COUNT
self.age = age
self.__weight = weight # self._Animal__COUNT
self.HEIGHT = height
def eat(self):
print("{} eat".format(self.__class__.__name__))
def __getweight(self):
print(self.__weight) # self._Animal__COUNT
@classmethod
def showcount1(cls):
print(cls)
print(cls.__dict__)
print(cls.__COUNT) # cls._Animal__COUNT
@classmethod
def __showcount2(cls):
print(cls.__COUNT) # cls._Animal__COUNT
def showcount3(self):
print(self.__COUNT) # self._Animal__COUNT
class Cat(Animal):
NAME = 'CAT'
__COUNT = 200
c = Cat(3, 5, 15)
print(c.__dict__) # {'_Animal__COUNT': 101, 'age': 3, '_Animal__weight': 5, 'HEIGHT': 15}
print(c.HEIGHT) # 15
# print(c.__COUNT) # 'Cat' object has no attribute '__COUNT'
# c.__getweight() # 'Cat' object has no attribute '__getweight'
c._Animal__getweight() # 5 【注意,隐藏属性改名的只和当前类有关系,设置私有属性的当前类,在谁里面改谁的名】
c.showcount1() # 自己没有的,会和父类去要
# <class '__main__.Cat'>
# {'__module__': '__main__', 'NAME': 'CAT', '_Cat__COUNT': 200, '__doc__': None}
# 100
# c.__showcount2() # 'Cat' object has no attribute '__showcount2'
c._Animal__showcount2() # 100
c.showcount3() # 101
print(Cat.__dict__) # {'__module__': '__main__', 'NAME': 'CAT', '_Cat__COUNT': 200, '__doc__': None}
print(c._Cat__COUNT)