[python] 面向对象的三大特性-封装及新式类
一 继承
- 继承是指一个类(子类)可以继承另一个类(父类)的属性和方法,并可以在其基础上进行扩展或修改。
-
子类可以继承父类的属性和方法,包括私有属性和隐藏属性
💡 核心思想:
- 避免重复代码,提高复用性。
- 实现类之间的层次关系。
1.1 语法和分类
- 分类: 单继承和多继承
class 类名(父类名):
代码块
1.2 应用
-
下面写了一个类并且实现了一个speak方法, 但是这个方法并没有实现具体的逻辑,
-
而是抛出一个异常,要求任何继承自 Animal 的子类都必须重写这个方法以提供具体的行为,
-
当然并不是非要抛出异常,一般来说就当成一个普通类来定义就行。
class Animal:def __init__(self, name):self.name = namedef _ask(self):print("todi")def speak(self):raise NotImplementedError("Subclass must implement abstract method")
- 像这样,继承Animal类并重写这个方法
class Dog(Animal):def speak(self):return f"{self.name}"
class Cat(Animal):def speak(self):return f"{self.name} says Meow!"
- 这样我们在调用dog类时,既可以使用父类中继承来的_ask方法,也可以使用重写的speak方法
- 正如开始所讲的,子类可以继承父类的私有属性和方法_ask是一个私有方法
if __name__ == "__main__": # 表示下面的语法只有在当前文件被直接运行时才会执行dog = Dog("汤姆")cat = Cat("丧彪")print(dog.speak())print(cat.speak())print(cat._ask())
二 多层继承
- 指的是一个类继承自另一个类,而那个类又继承自另一个类,形成一种层次结构。例如 A 继承自 B,B 继承自 C。
- 比如定义了一个动物类,然后在定义一个飞行类继承动物类,然后再定义一个狗类继承飞行类,
- 这就相当于狗类继承了父类的飞行属性,也从飞行属性的父类中继承了动物属性。
class Animal:def __init__(self, name):self._name = namedef speak(self):print(f"{self._name} makes a sound(制造噪音).")class Fly(Animal):def fly(self):print(f"{self._name} fly.(飞行)")class Dog(Fly):def speak(self):print(f"{self._name} 狗叫")
- 这时候我们创建Dog类,他是继承自->Fly(飞行类)也就永远fly的能力
- 而Fly类继承Animal动物类,他就具有speak的能力
dog1 = Dog("哈士奇")
dog1.speak()
dog1.fly()
-
如果这里Dog类,也就是孙子类没有重写这个speak方法或者使用pass什么都不做
-
那么他就会执行从层级类上面继承而来的方法
三 方法重写
- 方法重写是继承中很常见的。
-
对父类方法进行扩展: 继承父类的方法,子类也可以增加自己的功能
-
当从父类中继承的方法不能满足子的需求时,可以再子类中重写父类的方法,也叫覆盖
# 方式:
# 1 父类名.方法名()
# 2 super().方法名() --推荐使用
# 3 super(子类名,self).方法名
# 4 也可以完全覆盖重写
- 首先我们定义一个动物类,再定义一个飞行的子类继承动物类
- 再子类中重新写父类的方法,并且调用了super.speak()表示继承父类方法,然后还可以实现自己额外的功能。
- 也可以直接全部重写不调用父类的方法。
class Animal:def __init__(self, name):self._name = namedef speak(self):print(f"{self._name} makes a sound(制造噪音).")class Fly(Animal):def speak(self):super().speak()print(f"{self._name} makes a sound(制造飞行噪音).")
bird = Fly("布谷鸟")
bird.speak()
四 新式类
- 首先了解一个概念,派生类-> 有继承别的类并且修改了功能的类
- 这个概念并不重要
-
派生 = 继承 + 扩展/修改
子类有不同与父类的属性或者方法,如果子类只是继承但没有做任何东西,则不是派生类
经典类:
- 这种方式就是没有继承任何类就是属于经典类
# class A: #经典类: 不由任意内置类型派生出的类
# pass
新式类:
-
python3中如果一个类没有继承任何类,则默认继承object类
-
object类是python为所有对象提供的基类,提供了一些内置的属性和方法
-
类似与QT中的QObject
class A(object):pass
- 我们可以使用dir()内置函数查看某个类的属性和方法
print(dir(object))
五 多继承
- 指的是一个类同时继承自多个父类。例如 D 继承自 A 和 B
- 供了一种强大的机制,允许子类从多个父类继承功能,但需要小心处理方法冲突和构造函数的初始化。
class Animal:def __init__(self, name):self._name = namedef speak(self):print(f"{self._name} makes a sound(制造噪音).")class Fly(Animal):def fly(self):print(f"{self._name} fly.(飞行)")def speak(self):print(f"{self._name} makes a sound(制造飞行噪音).")class Work(Animal):def work(self):print(f"{self._name} work.(散步)")def speak(self):print(f"{self._name} makes a sound(散步聊天).")class Dog(Fly,Work):pass
dog1 = Dog("哈士奇")
dog1.speak()
-
Fly和work类中有speak这个类,但是这种有重复的属性和方法时,会优先继承靠前面类的
-
为什么有这种情况存在
-
方法的搜索顺序会按照mro输出的结果从左往右查找
-
python中内置的属性__mro__可以查看方法调用顺序
print(Dog.__mro__)
- 这时候我们会发现最左边是Dog类,也就是说如果能够在这个类中找到我们所调用的方法,那就不会再去继承的父类上去查找要调用的方法了。