基本概念
面向对象三要素之一,继承Inheritance
class A:
def a(self):
print('A')
class B:
def b(self):
print('B')
s=A()
s.a()
t=B()
t.b()
class Animal:
def __init__(self,name):
self._name=name
def shout(self):
print(self.__class__.__name__)
@property
def name(self):
return self._name
a=Animal('birds')
a.shout()
class Cat(Animal):
pass
cat=Cat('bigcat')
cat.shout()
print(cat.name)
上例可以看出,通过继承、猫类不同写代码,直接继承了父类的属性和方法。
继承:
- class Cat(Animal)这种形式就是从父类继承,括号中写上继承的类的列表。
- 继承可以让子类从父类获取特征(属性和方法)
父类 - Animal就是Cat的父类,也称为基类、超类
子类
Cat就是Animal的子类,也称为派生类
定义
格式如下
class 子类名(基类1[,基类2,……]):
语句块
如果类定义时,没有基类列表,等同于继承自object。在Python3中object类是所有对象的根基类
class A:
pass
class A(object):
pass
注意,上例在Python2中,两种写法是不同的
Python个支持多继承,继承也可以升级
查看继承的特殊属性和方法有
特殊属性和方法 | 含义 |
base | 类的基类 |
bases | 类的基类元组 |
mro | 显示方法查找顺序、基类的元组 |
mro() | 显示方法查找顺序,返回列表 |
subclasses() | 类的子类列表 |
继承中的访问控制
从父类继承,自己没有的,就可以到父类中找
私有的都是不可以访问的,但是本质上依然是改了名称放在这个属性所在类或实例__dict__中。知道这个新名称就可以直接找到这个隐藏的变量。
总结
继承时,公有的,子类和实例都可以随机访问;私有成员被隐藏,子类和实例不可直接访问,但私有变量所在的类内的方法中可以访问这个私有变量。
Python通过自己一套实现,实现和其它语言一样的面向对象的继承机制,
实例属性查找顺序
实例的__dict__----->类__dict__---->如果有继承----->父类的__dict__
如果搜索这些地方后没有找到就会抛异常,先找到就立即返回了。
方法的重组、覆盖override
class Animal:
def shout(self):
print('Animal')
class Cat(Animal):
#覆盖了父类的方法
def shout(self):
print('miao')
a=Animal()
a.shout()
c=Cat()
c.shout()
print(a.__dict__)
print(c.__dict__)
print(Animal.__dict__)
print(Cat.__dict__)
class Animal:
def shout(self):
print('Animal')
class Cat(Animal):
#覆盖了父类的方法
def shout(self):
print('miao')
def shout(self):
print(super())
print(super(Cat,self))
print(super(self.__class__,self))
super().shout()
super(Cat,self).shout()
self.__class__.__base__.shout(self)
super()可以访问到父类的类属性
对于静态方法和类方法
class Animal:
@classmethod
def class_method(cls):
print('miaomiao')
@staticmethod
def static_method():
print('wangwang')
class Cat(Animal):
@classmethod
def class_method(cls):
print('wangwang')
@staticmethod
def static_method():
print('miaomaio')
c=Cat()
c.class_method()
c.static_method()
print(Cat.__dict__)
print(Animal.__dict__)
这些方法都可以覆盖,原理都一样,属性字典的搜索顺序
继承时使用初始化
class A:
def __init__(self,a):
self.a=a
class B:
def __init__(self,b,c):
self.b=b
self.c=c
def printv(self):
print(self.b)
print(self.a)
f=B(200,300)
print(f.__dict__)
print(f.__class__.__bases__)
f.printv()
上例代码可知:
如果类B定义时声明继承自类A,则在类B中__bases__中是可以看到类A
但是这和是否调用类A的构造方法是两回事
但是B中调用了父类A的构造方法,就可以拥有父类的属性了