Python--05--面向对象(继承,多态)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


面向对象

面向对象--02--封装、继承、多态

1.继承

python 复制代码
# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

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

# 定义一个Student类(子类、派生类), 继承自Person类(父类、超类、基类)
class Student(Person):
    def __init__(self, name, age, gender, stu_id, grade):
        # 在子类中,有两种方式去调用父类的初始化方法,来实现对继承属性:name, age, gender 初始化操作
        # 方式1(更推荐)
        super().__init__(name, age, gender)

        # 方式2
        # Person.__init__(self, name, age, gender)

        # 子类独有的属性,需要自己手动完成初始化
        self.stu_id = stu_id
        self.grade = grade

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

# 创建Student类的实例对象
s1 = Student('李华', 16, '男', '2025001', '初二')
# print(s1.__dict__)
# print(type(s1))

# 查找speak方法的过程:1.实例自身(s1) => 2.Student类 => 3.Person类
# s1.speak('你好')

# print(s1.__dict__)

# 查找study方法的过程:1.实例自身(s1) => 2.Student类 => 3.Person类
# s1.study()


python 复制代码
# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

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


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

    # 方法重写:当子类中定义了一个与父类中相同的方法,那么子类中的方法就会"覆盖"父类的方法
    def speak(self, msg):
        super().speak(msg)
        print(f'我是学生,我的学号是{self.stu_id},我正在读{self.grade},我想说:{msg}')

s1 = Student('李华', 12, '男', '2025001', '初二')
s1.speak('好好学习')
python 复制代码
# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

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

p1 = Person('张三', 18, '男')
s1 = Student('李华', 12, '男', '2025001', '初二')

# 方法1:isinstance(instance, Class),作用:判断某个对象是否为指定类或其子类的实例
print(isinstance(s1, Student))
print(isinstance(p1, Person))
print(isinstance(s1, Person))
print(isinstance(p1, Student))

# 方法2:issubclass(Class1, Class2),作用:判断某个类是否是另一个类的子类
print(issubclass(Student, Person))
print(issubclass(Person, Student))
python 复制代码
# 所谓多重继承,就是一个类,可以同时继承多个父类
# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
    def speak(self):
        print(f'我叫{self.name}, 年龄是{self.age}, 性别是{self.gender}')

# 定义一个Worker类
class Worker:
    def __init__(self, company):
        self.company = company
    def do_work(self):
        print(f'我在{self.company}做兼职')

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

# 创建Student实例对象
s1 = Student('张三', 18, '男', '2025001', '初二', '麦当劳')
print(s1.__dict__)
s1.speak()
s1.do_work()
s1.study()

# 类的__mro__属性:用于记录属性和方法的查找顺序
# 通过实例去查找属性或方法时,会现在实例自身上寻找,如果没有,就按照__mro__中所记录的顺序去查找
print(Student.__mro__)

2.权限控制


测试『类外部』访问:

python 复制代码
class Person:
    def __init__(self, name, age, idcard):
        self.name = name        # 公有属性:当前类内部、子类内部、类外部,可都可访问
        self._age = age         # 受保护属性:当前类内部、子类内部,可以访问
        self.__idcard = idcard  # 私有属性:仅能在当前类内部访问

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

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

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

# 类的外部,仅能访问公有属性
# 注意:如果在类的外部,强制访问【受保护的属性】,也能访问,但最好别这么做
print(p1._age)

# 强制访问【私有属性】会报错
# print(p1.__idcard)

# 扩展:Python保护【私有属性】的方式,是重命名,例如:__idcard属性,会被重命名为:_Person__idcard
print(p1.__dict__)
print(p1._Person__idcard)
python 复制代码
class Person:
    def __init__(self, name, age, idcard):
        self.name = name        # 公有属性:当前类内部、子类内部、类外部,可都可访问
        self._age = age         # 受保护属性:当前类内部、子类内部,可以访问
        self.__idcard = idcard  # 私有属性:仅能在当前类内部访问

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

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

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

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

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

# 测试修改age
p1._age = 19
print(p1.age)

# 测试修改idcard
p1.idcard = 'asd'

3.魔法方法

python 复制代码
# 类中以双下划线开头和结尾的方法,叫魔法方法(魔术方法)。
# 魔法方法不需要手动调用,Python会在特定场景自动调用。
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    # __str__ 方法,执行时机:当调用 print(对象)或str(对象) 时
    def __str__(self):
        return f'姓名:{self.name}, 年龄:{self.age}, 性别:{self.gender}'

    # __len__ 方法,执行时机:当调用len(对象)时
    def __len__(self):
        return len(self.__dict__)

    # __lt__方法,执行时机:当执行 对象1 < 对象2 时
    def __lt__(self, other):
        return self.age < other.age

    # __gt__方法,执行时机:当执行 对象1 > 对象2 时
    def __gt__(self, other):
        return self.age > other.age

    # __eq__方法,执行时机:当执行 对象1 == 对象2 时
    def __eq__(self, other):
        return self.__dict__ == other.__dict__

    # __getattr__方法,执行时机:当访问了对象不存在的属性时
    def __getattr__(self, item):
        print(f'您访问的{item}属性,不存在!')

# 创建Person实例
p1 = Person('张三', 18, '男')
p2 = Person('李四', 22, '女')

# 测试代码
print(p1)
print(str(p1))
print(len(p1))
print(p1 < p2)
print(p1 > p2)
print(p1 == p2)
print(p1.address)

4.object 类

python 复制代码
# Python 中,所有的类都继承了 object 类,即:object 类是所有类的顶层父类。
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

# 验证一下:所有的类都继承了 object 类
print(issubclass(Person, object))
print(issubclass(int, object))
print(issubclass(str, object))
print(issubclass(list, object))
print(issubclass(tuple, object))
print(issubclass(bool, object))

# 因为 object 是所有类的父类,所以 Python 中的所有对象,都间接是 object 类的实例。
p1 = Person('张三', 18, '男')
print(isinstance(p1, object))
print(isinstance(100, object))
print(isinstance('hello', object))
print(isinstance(True, object))
print(isinstance(None, object))
print(isinstance([10, 20, 30], object))
print(isinstance({'吃饭','睡觉'}, object))

# 所有对象都继承了 object 类所提供的:各种属性和方法,从而保证每个对象都具备统一的基本能力。
for key in object.__dict__:
    print(key)

p1 = Person('张三', 18, '男')
print(p1.__dict__)  # 打印对象自己身上的东西
print(dir(p1))      # 打印对象能访问到的东西

print(p1.__str__())
print(p1)

object 类所提供的:各种属性和方法

python 复制代码
D:\DevTools\Python\python.exe C:\Users
__new__
__repr__
__hash__
__str__
__getattribute__
__setattr__
__delattr__
__lt__
__le__
__eq__
__ne__
__gt__
__ge__
__init__
__reduce_ex__
__reduce__
__getstate__
__subclasshook__
__init_subclass__
__format__
__sizeof__
__dir__
__class__
__doc__

Process finished with exit code 0

5.多态

python 复制代码
# 多态是指:同一个方法名,在不同的对象上调用时,能呈现出不同的行为。
# Python中支持:标准多态、鸭子多态

# 标准多态:
class Animal:
    def speak(self):
        print('动物正在发出声音')

class Dog(Animal):
    def speak(self):
        print('汪汪汪!')

class Cat(Animal):
    def speak(self):
        print('喵喵喵!')

# 注意Pig类没有继承Animal类
class Pig:
    def speak(self):
        print('哼哼哼!')

# make_sound函数要求:传入的对象,必须是 Animal 类型(或其子类型),才能保证可以调用到sepak方法
def make_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 中能运行,但这不属于标准多态
python 复制代码
# 核心理念:如果一个东西看起来像鸭子,叫起来也像鸭子,那它就是鸭子。
# 鸭子类型是一种编程风格,它不检查对象的类型,只关注对象能否"做某件事"(是否有对应的方法)。

class Dog:
    def speak(self):
        print('汪汪汪!')

class Cat:
    def speak(self):
        print('喵喵喵!')

class Pig:
    def speak(self):
        print('哼哼哼!')

class Fish:
    def speak(self):
        print('咕噜噜!')

# 不再对animal的类型做限制,animal可以是任何类型,只要能调用speak方法就可以
def make_sound(animal):
    animal.speak()

# 创建实例对象
d1 = Dog()
c1 = Cat()
p1 = Pig()
f1 = Fish()

make_sound(d1)
make_sound(c1)
make_sound(p1)
make_sound(f1)
python 复制代码
from abc import ABC, abstractmethod

#【抽象类】是一种不能直接实例化的类,它通常作为"规范",让子类去继承,并实现其中定义的【抽象方法】。

# MustRun类一旦继承了ABC类,那MustRun类就是【抽象类】了
class MustRun(ABC):
    # run方法一旦被@abstractmethod装饰后,就变成了【抽象方法】
    @abstractmethod
    def run(self):
        pass

class Person(MustRun):
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def run(self):
        print(f'我叫{self.name},我在努力的奔跑!')

p1 = Person('张三', 18, '男')
p1.run()
相关推荐
csbysj20203 小时前
Vue3 样式绑定
开发语言
:1213 小时前
java继承
java·开发语言
m0_617493943 小时前
PyTorch CUDA设备不可用错误解决方案
人工智能·pytorch·python
小郑加油3 小时前
python学习Day15:综合训练——数据清洗与缺失值补充
开发语言·python·学习
完成大叔3 小时前
Agent入门:用本地模型从零搭建
开发语言·python·langchain
rGzywSmDg3 小时前
如何在Dev-C++中设置TDM-GCC为默认编译器
开发语言·c++
xyq20243 小时前
Ruby 日期 & 时间处理指南
开发语言
qxwlcsdn3 小时前
CSS如何实现元素镜像翻转_使用transformscalex负值
jvm·数据库·python