当前位置:首页>python>Python快速入门学习笔记十四:面向对象(下)继承、权限控制、多态、抽象类

Python快速入门学习笔记十四:面向对象(下)继承、权限控制、多态、抽象类

  • 2026-10-11 08:26:31
Python快速入门学习笔记十四:面向对象(下)继承、权限控制、多态、抽象类
❝

Python入门第十四课,主要是学习了面向对象编程的进阶知识,通过封装、继承和多态组织代码,将数据与行为结合,构建出模块化、可复用的程序结构。

  • 继承
    • 基本语法
    • 方法重写
    • isinstance() 和 issubclass()
    • 多重继承
  • 权限控制
    • 三种访问权限
    • getter 和 setter
  • 魔术方法
  • object 类
  • 多态
    • 什么是多态
    • 标准多态
    • 鸭子多态
  • 抽象类
  • 内存分析

继承

基本语法

概念:继承就是一个类可以继承另一个类的属性和方法。『父类』又称 『基类 或 超类』, 『子类』又称 『派生类』。

作用:通过继承可以实现代码的复用和扩展,避免重复编写相同的代码,让代码结构更简洁、更高效。

语法:def 子类名(父类名),例如:def Student(Person)就表示定义了一个Student类继承自Person类。

在子类中,有两种方式去调用父类的初始化方法,来实现对继承属性的初始化操作:

❏ 方式1(推荐):super().__init__(param1, param2)。

❏ 方式2:父类名.__init__(self, param1, param2)。

子类独有的属性,需要自己手动完成初始化。

示例代码:

# 定义一个Person类(父类)
classPerson:
def__init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

defspeak(self, msg):
        print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说:{msg}')

# 定义一个Student类(子类),继承自Person类
classStudent(Person):
def__init__(self, name, age, gender, stu_id, grade):
        super().__init__(name, age, gender)

        self.stu_id = stu_id
        self.grade = grade

defstudy(self):
        print(f'我叫{self.name},我在努力学习Python,争取做到{self.grade}年纪的第一名')

# 查看子类的属性和方法
print(Student.__dict__)

# 创建子类的实例对象
s1 = Student('李俊', 16, '男', '2026001', '初二')
print(s1.__dict__) # {'name': '李俊', 'age': 16, 'gender': '男', 'stu_id': '2026001', 'grade': '初二'}
print(type(s1)) # <class '__main__.Student'>

# 子类实例对象调用父类的方法
s1.speak('你好')

# 子类实例对象调用自己的方法
s1.study()

方法重写

如果子类中定义了与父类同名的方法,则子类方法会“覆盖”父类中同名的方法,又称:重写。

# 定义一个Person类(父类)
classPerson:
def__init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

defspeak(self, msg):
        print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说:{msg}')

# 定义一个Student类(子类),继承自Person类
classStudent(Person):
def__init__(self, name, age, gender, stu_id, grade):
        super().__init__(name, age, gender)

        self.stu_id = stu_id
        self.grade = grade

defstudy(self):
        print(f'我叫{self.name},我在努力学习Python,争取做到{self.grade}年纪的第一名')

# 方法重写
defspeak(self, msg):
        super().speak(msg)
        print(f'我是学生,我的学号是{self.stu_id},我正在读{self.grade}, 我想说:{msg}')

# 创建子类的实例对象
s1 = Student('李俊', 16, '男', '2026001', '初二')

# 子类实例对象调用自己的重写了父类方法
s1.speak('你好')

isinstance() 和 issubclass()

两个常用函数:

❏ isinstance(obj, Class)判断对象是否为指定类或其子类的实例。

❏  issubclass(Sub, Super)判断一个类是否是另一个类的子类。

示例代码:

# 定义一个Person类(父类)
classPerson:
def__init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

defspeak(self, msg):
        print(f'我叫{self.name},年龄{self.age},性别是{self.gender},我想说:{msg}')

# 定义一个Student类(子类),继承自Person类
classStudent(Person):
def__init__(self, name, age, gender, stu_id, grade):
        super().__init__(name, age, gender)

        self.stu_id = stu_id
        self.grade = grade

defstudy(self):
        print(f'我叫{self.name},我在努力学习Python,争取做到{self.grade}年纪的第一名')

# 方法重写
defspeak(self, msg):
# super().speak(msg)
        print(f'我是学生,我的学号是{self.stu_id},我正在读{self.grade}, 我想说:{msg}')

p1 = Person('张三', 18, '男')
s1 = Student('李俊', 16, '男', '2026001', '初二')

print(isinstance(s1, Student)) # True
print(isinstance(p1, Person)) # True
print(isinstance(s1, Person)) # True
print(isinstance(p1, Student))  # False

print(issubclass(Student, Person)) # True
print(issubclass(Person, Student))  # False
print(issubclass(Person, Person)) # True
print(issubclass(Student, Student)) # True

多重继承

概念:多重继承指一个类同时继承多个父类,从而拥有多个父类的属性和方法。

语法:

class 子类名(父类A, 父类B, ...):
# 子类可以继承多个父类的属性和方法
    ...

下面的示例代码中,Student类同时继承Person类和Worker类。

# 定义一个Person类
classPerson:
def__init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
defspeak(self):
        print(f'我叫{self.name},年龄{self.age},性别{self.gender}')

# 定义一个Worker类
classWorder:
def__init__(self, company):
        self.company = company
defdo_work(self):
        print(f'我在{self.company}做兼职')

# 定义一个Student类,继承自:Person类,Worker 类
classStudent(Person, Worder):
def__init__(self, name, age, gender, stu_id, grade, company):
        Person.__init__(self, name, age, gender)
        Worder.__init__(self, company)
        self.stu_id = stu_id
        self.grade = grade
defstudy(self):
        print(f'我在很努力的学习,争取做{self.grade}年纪的第一名')

# 创建Student实例对象
s1 = Student('张三', 18, '男', '2026001', '大一', '肯德基')
print(s1.__dict__)
s1.speak()
s1.do_work()
s1.study()

# 查看属性和方法的查找顺序
print(Student.__mro__) # (<class '__main__.Student'>, <class '__main__.Person'>, <class '__main__.Worder'>, <class 'object'>)
❝

扩展:

类的__mro__ 属性用于记录属性和方法的查找顺序。

通过实例去查找属性和方法时,会先在实例自身上查找,如果没有,就按照__mro__中记录的顺序去查找。

权限控制

三种访问权限

在Python中,我们可以给属性赋予三种权限,分别是:

  • 公有属性:当前类内部、子类内部、类外部,都可以访问。
  • 受保护属性:当前类内部、子类内部,都可以访问。
  • 私有属性:仅能在当前类内部访问。

示例代码:

classPerson:
def__init__(self, name, age, idcard):
        self.name = name
        self._age = age
        self.__idcard = idcard
defspeak(self):
# 类的内部,可以访问任何权限的属性(公有属性、受保护属性、私有属性)。
        print(f'我叫{self.name},年龄{self._age},身份证:{self.__idcard}')

classStudent(Person):
defhello(self):
# 子类的内部可以访问:公有属性、受保护属性
        print(f'我是学生,我叫{self.name},年龄{self._age}')

p1 = Person('张三', 18, '110101199001011234')
# 类的外部,仅能访问公有属性
print(p1.name)
print(p1._age) # 在类的外部强制访问受保护的属性,也可以访问,但是不建议这样做
# print(p1.__idcard) # 运行时直接报错:AttributeError: 'Person' object has no attribute '__idcard'

# 扩展:Python 保护私有属性的方式是重命名,例如:__idcard属性,会被重命名为:_Person__idcard
print(p1.__dict__)
print(p1._Person__idcard) # 但是不建议这样访问

getter 和 setter

在面向对象编程中,我们会把一些内部数据保护起来,但同时还想提供一个“安全的通道”让外部访问。

这个时候我们就会用到:

  • getter:读取属性的方法。
  • setter:修改属性的方法。

在 Python 中,通过 @property和@xxx.setter语法,把普通方法变成属性一样使用的方法。

示例代码:

classPerson:
def__init__(self, name, age, idcard):
        self.name = name
        self._age = age
        self.__idcard = idcard

# 注册 age 属性的 getter 方法,当访问 Person 实例的 age 属性时,会自动调用此方法
    @property
defage(self):
return self._age

# 注册 age 属性的 setter 方法,当给 Person 实例的 age 属性赋值时,会自动调用此方法
    @age.setter
defage(self, value):
if (value <= 120):
            self._age = value
else:
            print('年龄非法,已将年龄变为最大值120')
            self._age = 120

# 注册 idcard 属性的 getter 方法,当访问 Person 实例的 idcard 属性时,会自动调用此方法
    @property
defidcard(self):
return self.__idcard[:6] + '********' + self.__idcard[-4:]

# 注册 idcard 属性的 setter 方法,当给 Person 实例的 idcard 属性赋值时,内部会禁止修改身份证号并给出提示
    @idcard.setter
defidcard(self, value):
        print('抱歉,身份证号不允许随意修改,如有特殊需求,请联系管理员')

p1 = Person('张三', 18, '110101199001011234')
print(p1.age)
print(p1.idcard)

p1.age = 21
print(p1.age)

p1.idcard = 'asdd'
print(p1.idcard)

print(p1.__dict__)
print(Person.__dict__)

魔术方法

概念:以__xxx__命名的特殊方法(双下划线开头和结尾)。

特点:不需要手动调用,在特定场景由 Python 自动调用。

几个常用的魔术方法:

示例代码:

classPerson:
def__init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

def__str__(self):
returnf'姓名:{self.name}, 年龄:{self.age}, 性别:{self.gender}'

def__len__(self):
return len(self.__dict__)

def__lt__(self, other):
return self.age < other.age

def__gt__(self, other):
return self.age > other.age

def__eq__(self, other):
return self.__dict__ == other.__dict__

def__getattr__(self, name):
        print(f'您访问的{name}属性,不存在!')

p1 = Person('张三', 18, '男')
p2 = Person('李四', 21, '女')

print(p1)
print(str(p1))
print(len(p1))
print(p1 < p2)
print(p1 > p2)
print(p1 == p2)
print(p1.address)

object 类

object 是所有类的最终祖先,所有的类,无论写与不写,都继承自object。

object 提供了所有对象都会有的一组最基本的方法,例如:

上述这些方法,如果我们不去重写,Python 会自动继承并使用默认版本。

classPerson:
def__init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


# 验证所有的类都继承了 object 类
print(issubclass(Person, object))  # True
print(issubclass(int, object))  # True
print(issubclass(str, object))  # True
print(issubclass(bool, object))  # True
print(issubclass(list, object))  # True
print(issubclass(tuple, object))  # True
print(issubclass(set, object))  # True
print(issubclass(dict, object))  # True

print()

# 验证python中所有对象都是 object 类的实例
p1 = Person('张三', 18, '男')
print(isinstance(p1, object))  # True
print(isinstance(100, object))  # True
print(isinstance('hello', object))  # True
print(isinstance(False, object))  # True
print(isinstance([1, 2, 3], object))  # True
print(isinstance((1, 2, 3), object))  # True
print(isinstance({1, 2, 3}, object))  # True
print(isinstance({'James': 41, 'Kobe': 48}, object))  # True

# 查看 object 所有的属性和方法
for key in object.__dict__:
    print(key, object.__dict__[key])

print(p1.__dict__) # 打印对象自己身上的东西
print(dir(p1)) # 打印对象能访问到的东西

# 下面三种写法等价
print(p1.__str__())
print(p1)
print(str(p1))

多态

什么是多态

多态(Polymorphism)是面向对象编程的三大特性之一,指同一个操作或方法作用于不同类型的对象时,可以表现出不同的行为。简单来说,就是“一个接口,多种实现”。在 Python 中,多态主要通过以下两种形式:标准多态和鸭子多态,下面分别详细介绍。

  • 继承与方法重写:子类重写父类的方法,当使用父类类型的引用调用该方法时,实际执行的是子类的方法。这种形式又叫“传统多态”或“标准多态”。
  • 鸭子类型(Duck Typing):指一种编程风格,它并不依靠查找对象类型来确定其是否具有正确的接口,而是直接调用或使用其方法或属性(“看起来像鸭子,叫起来也像鸭子,那么肯定就是鸭子。”)

标准多态

标准多态,又叫“传统多态”,基于继承与方法重写:子类重写父类的方法,当使用父类类型的引用调用该方法时,实际执行的是子类的方法。

classAnimal:
defspeak(self):
        print('动物正在发出声音')

classDog(Animal):
defspeak(self):
        print('汪汪汪!')

classCat(Animal):
defspeak(self):
        print('喵喵喵!')

# 注意:Pig类没有继承Animal类
classPig:
defspeak(self):
        print('哼哼哼!')

# make_sound 函数要求:传入的对象必须是 Animal 类型(或其子类)
defmake_sound(animal:Animal):
    animal.speak()

a1 = Animal()
d1 = Dog()
c1 = Cat()

# 下面就是多态的体现
make_sound(a1) # 动物正在发出声音
make_sound(d1) # 汪汪汪!
make_sound(c1) # 喵喵喵!

# 按标准多态规则:Pig 没有继承 Animal,类型不匹配(会出现类型警告)
p1 = Pig()
make_sound(p1)  # 在其它语言中会报错,虽然 Python 中能运行,但这不属于标准多态

鸭子多态

鸭子多态(Duck Typing):指一种编程风格,它并不依靠查找对象类型来确定其是否具有正确的接口,而是直接调用或使用其方法或属性(“看起来像鸭子,叫起来也像鸭子,那么肯定就是鸭子。”)

官方文档地址:https://docs.python.org/zh-cn/3.13/glossary.html#term-duck-typing

classDog:
defspeak(self):
        print('汪汪汪!')

classCat:
defspeak(self):
        print('喵喵喵!')

classPig:
defspeak(self):
        print('哼哼哼!')

# make_sound 函数不在限制入参类型
defmake_sound(animal):
    animal.speak()

d1 = Dog()
c1 = Cat()
p1 = Pig()

# 下面就是多态的体现
make_sound(d1) # 汪汪汪!
make_sound(c1) # 喵喵喵!
make_sound(p1)  # 哼哼哼!

抽象类

概念:抽象类(Abstract Class)是指不能被直接实例化、主要用于定义接口的类,它通常包含一个或多个抽象方法(只有声明而没有具体实现的方法)。子类必须实现这些抽象方法才能被实例化。

定义:Python 通过内置的 abc 模块(Abstract Base Classes)来支持抽象类和抽象方法的定义。具体步骤如下:

1. 导入 ABC 和 abstractmethod

从 abc 模块导入 ABC 类(作为抽象类的基类)和 abstractmethod 装饰器。

2. 定义抽象类

创建一个继承自 ABC 的类,并用 @abstractmethod 装饰需要子类强制实现的方法。

3. 实例化限制

如果子类没有实现所有抽象方法,则子类本身也是抽象类,无法被实例化。

4. 普通方法

抽象类不仅可以包含抽象方法,也可以包含普通方法(即非抽象方法,带有具体实现)。这些具体方法会被子类继承,并且可以直接使用,无需子类重写。

实例代码:

from abc import ABC, abstractmethod

classMustRun(ABC):
    @abstractmethod
defrun(self):
pass

deftest(self):
        print("test method called")

classPerson(MustRun):
def__init__(self, name, age):
        self.name = name
        self.age = age

defrun(self):
        print(f"run method called {self.name} with age {self.age}")

p1 = Person("P1", 20)
p1.run()
p1.test()

# m1 = MustRun() # 直接实例化抽象类运行时会报错

内存分析

内存分为两个部分:栈内存、堆内存;变量在栈内存中,对象在堆内中。

Python 中变量里保存的不是数据,而是指向堆内存中对象的引用(内存地址)。

不可变对象:重新赋值会创建对象。

int 类的实例对象,时不可变对象,所以修改变量 a 时,会创建新对象,不会影响其他引用 b。

Python 中常见不可变对象有:int、float、bool、str、tuple、frozenset、None。

Python 中常见的可变对象有:list、dict、set、自定义类的实例对象。

可变对象:修改内容不改变地址。

自定义类对象的内存表示。

最新文章

随机文章