Python小白学习教程从入门到入坑------第二十四课 继承(语法进阶)
一、继承
继承就是让类和类之间转变为父子关系,子类默认继承父类的属性和方法
在Python中,继承是一个非常强大的特性,它允许我们创建一个新的类(称为子类),这个新类可以继承另一个类(称为父类或基类)的属性和方法
这样,子类就可以复用父类的代码,同时还可以添加新的属性和方法或者重写父类的方法来实现特定的功能
想象一下,你有一个“动物”类,这个类描述了所有动物共有的属性和方法,比如“吃”和“呼吸”
然后,你想创建一个特定的动物类,比如“狗”,狗也是动物,所以它应该继承“动物”类的所有属性和方法,但同时,狗还有一些特有的属性和方法,比如“叫”和“摇尾巴”
通过继承,你可以这样做:
首先,定义一个“动物”类,包含所有动物共有的属性和方法
然后,定义一个“狗”类,让它继承自“动物”类。这样,“狗”类就自动拥有了“动物”类的所有属性和方法
最后,你可以在“狗”类中添加狗特有的属性和方法
1.1 语法
class 类名(父类名):
代码块...
注意:继承分为单继承和多继承
1.2 单继承
单继承是指一个子类只继承一个父类的情况
这是最简单、最直接的继承方式
在单继承中,子类可以访问父类的所有公开(public)和受保护(protected)成员(属性和方法),但不能直接访问私有(private)成员(通常以双下划线__开头的成员名)
不过,通过一些特殊的方法(如名称修饰),子类仍然可以间接地访问这些私有成员
eg:
class Person: # 父类
def eat(self):
print("我会吃饭")
def sing(self):
print("我是唱歌小能手")
class Girl(Person): # Person类的子类
pass # 占位符,代码里面类下面不写任何东西,会自动跳过,不会报错
class Boy(Person): # Person类的子类
pass
girl = Girl()
girl.eat()
girl.sing()
# 输出内容:
# 我会吃饭
# 我是唱歌小能手
boy = Boy()
boy.eat()
boy.sing()
# 输出内容:
# 我会吃饭
# 我是唱歌小能手
# 总结:子类可以继承父类的属性和方法,就算子类自己没有,也可以使用父类的。
1.3 继承的传递(多重继承)
A/B/C C(子类) 继承于B(父类), B类 (子类) 继承A类 (父类), C类具有 A/B 类的属性和方法
子类拥有父类的父类的属性和方法
eg:
class Father: # 父类
def eat(self):
print("吃饭")
def sleep(self):
print("睡觉")
class Son(Father): # Father类的子类
pass
class Grandson(Son): # Son的子类
pass
grandson = Grandson()
grandson.eat()
grandson.sleep()
# 输出结果:
# 吃饭
# 睡觉
1.4 方法的重写
含义:如果从父类继承的方法不能满足子类的需求,可以在子类中重写父类的方法,这个过程称为方法的覆盖,也称为方法的重写;
1.4.1 覆盖父类方法
eg:
class Person: # 父类
def money(self):
print("一百万需要被继承")
class Man(Person): # 子类
def money(self):
print("自己赚一千万")
man = Man()
man.money()
# 输出结果:自己赚一千万
1.4.2 对父类方法进行扩展
继承父类的方法,子类也可以增加自己的功能
实现对父类方法进行扩展的三种方式:
1. 父类名.方法名(self)
2. super().方法名() -----推荐使用
3. super(子类名,self). 方法名
接下来通过代码详细解释一下这三种方式:
1. 父类名.方法名(self)
eg:
class Parent:
def some_method(self):
print("Parent method")
class Child(Parent):
def some_method(self):
# 调用父类方法
Parent.some_method(self)
# 添加子类特有的逻辑
print("Child method")
# 测试
child = Child()
child.some_method()
输出结果:
Parent method
Child method
优点:简单直接,易于理解
缺点:如果父类名被更改或继承结构变得复杂,这种方式可能会变得难以维护
2. super().方法名() -----推荐使用
super在python里面是一个特殊的类,super()是使用super类创建出来的对象,可以调用父类中的方法
eg:
class Parent:
def some_method(self):
print("Parent method")
class Child(Parent):
def some_method(self):
# 调用父类方法
super().some_method()
# 添加子类特有的逻辑
print("Child method")
# 测试
child = Child()
child.some_method()
输出结果:
Parent method
Child method
优点:
1、自动处理多重继承中的方法解析顺序(MRO)
2、更容易维护,特别是当涉及多重继承时
缺点:稍微比直接调用父类方法复杂一点,但通常这种复杂性是值得的。
3. super(子类名,self). 方法名
这是 super() 的另一种形式,明确指定了子类和实例
虽然这在某些情况下可能有用,但通常不推荐使用,因为 super() 已经足够,并且更简洁
class Parent:
def some_method(self):
print("Parent method")
class Child(Parent):
def some_method(self):
# 调用父类方法
super(Child, self).some_method()
# 添加子类特有的逻辑
print("Child method")
# 测试
child = Child()
child.some_method()
输出内容:
Parent method
Child method
优点:在某些需要明确指定子类和实例的复杂情况下可能有用
缺点:
1、冗长且容易出错
2、不如 super() 直观和简洁
二、新式类写法
python3中如果一个类没有继承任何类,则默认继承object类,因此python3都是新式类
2.1 第一种经典类
格式:
class A: # 经典类:不由任意内置类型派生出的类
pass
那么什么是派生类什么是非派生类呢?
常常是那种继承父类又改变了父类的属性或者方法的类就称为派生类(简单来说就是有不同于父类的就是派生类)
eg1:非派生类
class Animal:
def walk(self):
print("我会走路")
class Dog(Animal): # 非派生类,完全继承父类的方法
pass
eg2:派生类
class Animal:
def walk(self):
print("我会走路")
class Dog(Animal): # 派生类,在继承父类方法的基础上新增了自己的方法
def bite(self):
print("会咬人")
2.2 第二种经典类
格式:class A ()
在Python中,class A() 定义了一个名为 A 的空类。这里,A 是类名,而括号 () 表示这个类是从哪个基类(或父类)继承而来的。由于在这个例子中括号内为空,A 默认从Python的内置基类 object 继承。
2.3 新式类 (推荐使用)
格式:class A(object)
新式类:继承了object类或者该类的子类都是新式类
object:对象,Python为所有对象提供的基类(顶级父类),提供了一些内置的属性和方法,可以用dir()查看
eg:
print(dir(object))
输出内容:
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
三、多继承
在Python中,多继承是指一个类可以从多个基类(父类)继承属性和方法,并且具有所有父类的属性和方法
这是面向对象编程(OOP)的一个强大特性,允许类组合多个父类的功能,从而创建更灵活和可重用的代码结构
3.1 子类可以拥有多个父类,并且具有所有父类的属性和方法
eg:
class Father(object): # 父类一
def money(self):
print("拥有一百万遗产需要被继承")
class Mother(object): # 父类二
def appearance(self):
print("绝世容颜需要被继承")
class Son(Father,Mother):
pass
son = Son()
son.money()
son.appearance()
# 输出结果:
# 拥有一百万遗产需要被继承
# 绝世容颜需要被继承
3.2 不同的父类存在同名的方法
注意:开发时应尽量避免此类情况,有多个父类的属性和方法如果多个父类具有同名方法的时候,调用就近原则
eg:Father类在前,Mother类在后
class Father(object): # 父类一
def money(self):
print("拥有一百万遗产需要被继承")
class Mother(object): # 父类二
def money(self):
print("拥有一百二十万遗产需要被继承")
def appearance(self):
print("绝世容颜需要被继承")
class Son(Father,Mother):
pass
son = Son()
son.money()
son.appearance()
# 输出结果:
# 拥有一百万遗产需要被继承
# 绝世容颜需要被继承
eg:Mother类在前,Father类在后
class Father(object): # 父类一
def money(self):
print("拥有一百万遗产需要被继承")
class Mother(object): # 父类二
def money(self):
print("拥有一百二十万遗产需要被继承")
def appearance(self):
print("绝世容颜需要被继承")
class Son(Mother,Father):
pass
son = Son()
son.money()
son.appearance()
# 输出结果:
# 拥有一百二十万遗产需要被继承
# 绝世容颜需要被继承
3.3 方法的搜索顺序(了解)
python中内置的属性__mro__可以查看方法搜索顺序
搜索方法时,会先按照__mro__的输出结果,从左往右的顺序查找
如果在当前类中找到了方法,就直接执行,不再搜索
如果找到最后一个类,还没有找到这个方法,程序就会报错
eg:
class Father(object): # 父类一
def money(self):
print("拥有一百万遗产需要被继承")
class Mother(object): # 父类二
def money(self):
print("拥有一百二十万遗产需要被继承")
def appearance(self):
print("绝世容颜需要被继承")
class Son(Mother,Father):
def money(self):
print("拥有十万")
son = Son()
son.money()
son.appearance()
print(Son.__mro__)
# 输出结果:
# 拥有十万
# 绝世容颜需要被继承
# (<class '__main__.Son'>, <class '__main__.Mother'>, <class '__main__.Father'>, <class 'object'>)
今天的分享就到这里了,有错误的地方欢迎大家指出,希望能够帮助到大家~