1.提高了代码的复用性 2.让类与类之间产生了关系,有了这个关系,才有了多态继承,是面向对象的三大特征之一
class Person(): name = '' age = '' class Doctor(): name = '' age = '' def study(self): print('治病救人') class Sldie(): name = '' age = '' def study(self): print('保家卫国')举例: 定义一个狗类 1.直接修改动物类-修改起来比较麻烦,会违反ocp原则 2.直接创建一个新类(狗)-这样比较麻烦,会出现大量重复性代码,因为使用了大量的复制粘贴 3.直接从Animal类中继承他的属性和方法
#定义一个动物类 class Animal: def run(self): print('动物跑..。。') def sleep(self): print('动物睡觉.。。') a = Animal() a.run() #动物跑..。。 # # 定义类时,可以在类名后面加上括号,括号中指定的是当前类的父类(超类,基类,super) class Dog(Animal): def run(self): print('狗跑..。。') # # def sleep(self): # print('狗睡觉.。。') # def home(self): print('狗看家.。。') pass d = Dog() # print(d) #<__main__.Dog object at 0x000001A6BE4F4148> # d.run() #狗跑..。。 # d.sleep() #动物睡觉.。。 r = isinstance(d,Dog) print(r) #True s = isinstance(d,Animal) print(s) #True 若創建类的时候省略了父类,则默认父类是object object是所有类的父类,所有类都继承了object class Person(): pass # issubclass()--检查一个类是不是另一个类的子类 print(issubclass(Dog,Animal)) #True print(issubclass(Dog,object)) #True print(issubclass(Animal,object)) #True print(issubclass(Person,object)) #True若在子类中有和父类同名的方法,通过子类的实例去调用方法时,会调用子类的方法,而非父类的方法 这就是方法的重写(覆盖)
当我们去调用一个对象的时候 会优先调用当前对象的方法,若当前对象中没有这个方法,则会去父类中寻找,若其父类中 也没有,则会去父类的父类寻找,若无,则会逐级向上,直到object中去,若object也没有,会报错
class A(object): def test(self): print('A....') class B(A): def test(self): print('B....') class C(B): def test(self): print('C....') c=C() c.test() #C.... c.sty() #AttributeError: 'C' object has no attribute 'sty'父类中所有的方法都会被子类继承,包括特殊方法
#定义一个动物类 class Animal: def __init__(self,name): self._name = name def run(self): print('动物跑..。。') def sleep(self): print('动物睡觉.。。') @property def name(self): # print('property执行') return self._name @name.setter def name(self,name): self._name = name # 希望能够直接调用父类的__init__来初始化父类中的属性 # super可以用了获取当前的父类 # 并且通过super()返回的对象,调用父类方法时不需要写self class Dog(Animal): def __init__(self,name,age): # 希望能够直接调用父类的__init__ # self._name = name # Animal.__init__(self,name) super().__init__(name) self._age = age def run(self): print('狗跑..。。') # # def sleep(self): # print('狗睡觉.。。') # def home(self): print('狗看家.。。') @property def age(self): # print('property执行') return self._age @age.setter def age(self, age): self._age = age # e = Dog() #TypeError: __init__() missing 1 required positional argument: 'name' #子类未重写init方法之前,即注释方法def __init__(self,name,age): # e = Dog('蛇精病') # print(e.name) #蛇精病 # e.name = '二哈' # print(e.name) #二哈 #子类未重写init方法之后 e = Dog('long',3) print(e.name,e.age) #long 3语法:类名.__bases__可以用了获取当前类的所有父类 在Python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类 在开发中没有特殊情况,尽量避免使用多重继承,因为多重继承会让我们代码过于复杂 如果多个父类中有同名的方法,则会在第一个父类中寻找,然后找第二个…(父类顺序以写入的顺序为准) 前边会覆盖后面的
class A(object): def test(self): print('A....') class B(object): def test2(self): print('B....') class C(A,B): pass print(C.__bases__) #(<class '__main__.A'>, <class '__main__.B'>)-元组 print(A.__bases__) #(<class 'object'>,)-元组 print(B.__base__) #<class 'object'> c = C() c.test() #A.... c.test2() #B....面向对象的三大特征之一 熊(黑熊、棕熊、北极熊…)
一个对象可以以不同的形态去呈现
# 定义一个类 class A: def __init__(self,name): self._name = name @property def name(self): return self._name @name.setter def name(self,name): self._name = name class B: def __init__(self,name): self._name = name # def __len__(self): # # return 5 @property def name(self): return self._name @name.setter def name(self,name): self._name = name class C: pass # 定义一个函数 def speak(obj): print('你好 %s'%obj.name) # 在speak2这个函数中做了一个类型检查,也就是只有obj是A类型的对象的时候,才可以正常使用,其他类型的对象无法使用该函数,这个函数其实就违反了多态 # 违反了多态的函数,只适用于一种类型的对象,无法处理其他类型的对象,这样导致函数的适用性非常差 def speak2(obj): # 类型检查 if isinstance(obj, A): print('你好 %s' % obj.name) a = A('葫芦娃') b = B('钢铁侠') # print(len(b)) #TypeError: object of type 'B' has no len() c = C() speak(b) #你好 钢铁侠 speak2(a) ##你好 葫芦娃 speak2(b) #因为speak2中设置了对象的检查,只有A类型的可以输出,所以此时没有输出 # len() lst = [1,2,3] s = 'python' print(len(lst)) #3 print(len(s)) #6 # 刚才用len()函数来检查不同对象类型的长度其实就是面向对象的特征之一 # 之所有len()这个函数能获取长度,是因为这些对象中具有一个特殊方法__len__ # 换句话说只要对象中有__len__特殊方法,就可以通过len()方法来获取它的长度 # 面向对象的三大特征 # 封装 确保对象中的数据更安全 # 继承 保证了对象的可扩展性 # 多态 保证了程序的灵活性 # len() lst = [1,2,3] s = 'python' print(len(lst)) #3 print(len(s)) #6 刚才用len()函数来检查不同对象类型的长度其实就是面向对象的特征之一 之所以len()这个函数能获取长度,是因为这些对象中具有一个特殊方法__len__ 换句话说只要对象中有__len__特殊方法,就可以通过len()方法来获取它的长度