一、封装
封装是一种将数据和相关方法组合成一个单独的实体的机制。它将数据(属性)和操作数据的方法(方法)封装在一个对象中,并对外部代码隐藏了内部的实现细节。通过封装,对象可以提供一个公共接口,使得外部代码可以通过该接口访问和操作对象的数据,而不
需要了解其内部的具体实现。
二、继承
继承是新建类的一种方式,新建出来的类称作子类,被继承的类叫父类
它允许新类(子类)继承现有类(父类)的属性和方法,并且可以在新类中添加新的属性和方法,或者重写父类的方法来定制子类的行为。
继承促进了代码的重用和扩展(),并且提供了层次化和组织化的代码结构。解决了类与类之间的代码冗余问题
1、为什么要继承?
类解决什么问题:解决的是对象与对象之间的代码冗余问题
继承解决什么问题:解决的是类与类之间的代码冗余问题
2、子类的继承可以有多个父类
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | classParent1(object):    passclassParent2:    pass# 子类classSub1(Parent1):    pass# 多继承, 括号里面可以写多个类classSub2(Parent1, Parent2):    pass | 
3、查看一个类继承了哪些父类,.__bases__方法
| 1 2 3 | print(Sub1.__bases__) # (<class '__main__.Parent1'>,)print(Sub2.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)print(Parent1.__bases__)  # (<class 'object'>,) | 
注:python3中新定义的父类默认继承的是object类,所以父类也是一个子类
4、继承小案例
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | classPeople:  # 定义一个父类    school ='SH'# 严格依赖继承    def__init__(self, name, age, gender):        self.name =name        self.age =age        self.gender =genderclassStudent(People):    def__init__(self, name, age, gender, course):        """这个是指名道姓的调用方法,不依赖于继承"""        People.__init__(self, name, age, gender)  # name, age, gender 继承父类的属性        self.course =course    # 选课    defchoose_course(self):        passclassteacher(People):    def__init__(self, name, age, gender, level):        People.__init__(self, name, age, gender)        self.level =level  # 教室职称stu =Student('kevin', '19', 'male', 'python')teacher1 =teacher('王刚', 40, 'male', '高级教师')print(stu.name)  # kevinprint(teacher1.level)  # 高级教师 | 
5、
6、多
菱形查找分:经典类和新式类
经典类:按照深度优先查询
新式类:按照的广度优先查询
非菱形查找

| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | classG(object):    deftest(self):        print('from G')classE(G):    deftest(self):        print('from E')classF(G):    deftest(self):        print('from F')classB(E):    deftest(self):        print('from B')classC(F):    deftest(self):        print('from C')classD(G):    deftest(self):        print('from D')classA(B,C,D):    # def test(self):    #     print('from A')    passobj =A()obj.test() # 如上图,查找顺序为:obj->A->B->E->C->F->D->G->object# 可依次注释上述类中的方法test来进行验证 | 

⚠️:
1. 广度优先查找:从B开始到E回头,C到F,即查找到根部的上一级,最后一个分支查找到根部G
2. 如果D分支没有继承G,会在F查找完后查找G,形成菱形查找
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | classParentClass:    def__init__(self):        self.parent_attr ="I am the parent class"    defsome_method(self):        print("This is the parent class method")classChildClass(ParentClass):    def__init__(self):        super(ParentClass, self).__init__() # python2 的写法,python3 兼容调构造方法        self.child_attr ="I am the child class"    defsome_method(self):        super().some_method()  # python2 的写法不支持        print("This is the child class method")# 创建子类对象child =ChildClass()# 访问子类和父类的属性# print(child.child_attr)  # 输出: I am the child class# print(child.parent_attr)  # 输出: I am the parent class# 调用子类和父类的方法child.some_method()# 输出:# This is the parent class method# This is the child class method | 
如果不用super()方法来实现派生与方法重用:
指名道姓的调用某一个类的函数(不依赖于继承)
派生:比父类多的功能,派生方法。
相同的方法:重写
| 1 2 3 4 5 6 7 8 | classChildClass(ParentClass):    def__init__(self):        ParentClass.__init__(self)        self.child_attr ="I am the child class"    defsome_method(self):        ParentClass.some_method(self)        print("This is the child class method") | 
mro列表
mro(Method Resolution Order)是指在多重继承中确定方法调用顺序的算法。Python中的每个类都有一个mro列表,它决定了方法解析的顺序。MRO列表可以通过
__mro__属性来访问,它是一个元组,按照方法解析顺序列出了类及其超类。MRO列表遵循C3线性化算法,它考虑了类的继承关系和方法重写,以确保方法的解析顺序是一致且合理的。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | classA:    defsome_method(self):        print("Method from class A")classB(A):    # def some_method(self):    #     print("Method from class B")    passclassC(A):    defsome_method(self):        print("Method from class C")classD(B, C):    # def some_method(self):    #     print("Method from class D")    pass# 创建类D的实例d =D()# 调用some_method()方法d.some_method()# 打印MRO列表print(D.__mro__) | 
输出结果
| 1 2 | # Method from class C# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) | 
从结果可以看出:查找遵循了广度优先原则
三、多态
一种事物的多种形态,比如动物类会发出叫声,但是不同的动物叫声是不一样的
1、概念
允许不同的对象通过相同的接口进行交互,而无需关注对象的具体类型。多态使得我们可以编写更加灵活和通用的代码,提高代码的可重用性和可扩展性。
多态的实现依赖于继承和方法重写的机制。当多个类继承自同一个父类,并且这些子类都实现了父类的方法,那么这些子类对象可以被视为父类对象的多态形式。
多态性的关键在于子类对象可以被赋值给父类对象的变量,然后通过父类的接口来调用方法。在编译时,编译器会根据变量的声明类型选择适当的方法。而在运行时,实际上调用的是子类对象的方法。
多态实现了面向对象编程中的一个重要原则:针对接口编程,而不是针对实现编程。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | classAnimal:    defmake_sound(self):        passclassDog(Animal):    defmake_sound(self):        print("Woof!")classCat(Animal):    defmake_sound(self):        print("Meow!")defmake_animal_sound(animal):    animal.make_sound()# 创建不同的子类对象dog =Dog()cat =Cat()# 通过父类接口调用方法make_animal_sound(dog)  # 输出: Woof!make_animal_sound(cat)  # 输出: Meow! | 
⚠️:
1. 在此案例中Animal为父类,要求子类对象dog和cat有制造声音的功能。
2. dog和cat通过同一个接口传入,输出不同的结果
3. 此处的Animal 父类没有强制要求子类实现制造声音的功能,是一种思想,可以删掉Animal实现相同的效果
2、父类强制子类拥有相同的属性或方法
抽象类和抽象方法,用到abc模块,是abstract 抽象的英文缩写
class Animal(metaclass=abc.ABCMeta): 先变成抽象类,@abc.abstractmethod变成抽象方法
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #  强制子类有某种属性方法importabcclassAnimal(metaclass=abc.ABCMeta):    @abc.abstractmethod    defspeak(self):        pass    @abc.abstractmethod    defrun(self):        passclassCat(Animal):    # def speak(self):    deftest(self):        print('miaomiao')classDog(Animal):    defspeak(self):        print('wangwang!')cat =Cat()print(cat.test())# TypeError: Can't instantiate abstract class Cat with abstract methods run, speak | 
注:用上抽象类以后,子类没有遵循限制,实现相关的功能就会报错
1. 类传入 ‘metaclass=abc.ABCMeta’成为抽象类, 方法使用@abc.abstractmethod装饰器,成为抽象方法。
2. 抽象类本身不能被实例化和直接调用,它主要用于作为其他类的基类(父类)。
3. 抽象类的主要目的是为了定义一组通用的属性和方法,供子类继承和实现。
3、鸭子类型
抽象类的强制限制,这种方式是python不推荐的,python推荐的是鸭子类型
鸭子类型是一种思想,它关注对象的行为而不是对象的类型。
根据鸭子类型的理念,如果一个对象具有与鸭子相似的行为特征,那么它可以被视为鸭子。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | classDuck:    defquack(self):        print("Quack!")    deffly(self):        print("Flying!")classRobot:  # 机器人    defquack(self):        print("Beep!")    deffly(self):        print("Unable to fly!")defmake_quack_and_fly(obj):  # quack 嘎嘎叫声    obj.quack()    obj.fly()duck =Duck()robot =Robot()make_quack_and_fly(duck)  # 输出: Quack!  Flying!make_quack_and_fly(robot)  # 输出: Beep!  Unable to fly! | 
注:
定义了两个类,实例化一个鸭子和机器人,通过统一的函数接口调用方法(quack、fly),得到不同的结果
4、组合
一个对象拥有的属性或者方法,该属性或方法的被另外一个对象调用
案例1: 学生和选课
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | classPeople:    def__init__(self, name, age, gender):        self.name =name        self.age =age        self.gender =genderclassCourse:    def__init__(self, course_name, course_price, course_period):        self.course_name =course_name        self.course_price =course_price        self.course_period =course_period# 实例化课程python =Course("python", 10000, '6mon')linux  =Course("linux", 20000, '5mon')classStudent(People):    def__init__(self, name, age, gender, course=None):        ifcourse isNone:            course =[]        super(Student, self).__init__(name, age, gender)        self.courses =course    # def choose_course(self):    #     passstu =Student('kevin', '19', 'male')stu.courses.append(python)  # stu.courses ====> [python对象]stu.courses.append(linux)   # stu.courses ====> [python对象, linux对象]# print(stu.courses)print(stu.courses[0].course_name)print(stu.courses[0].course_price) | 
案例2:car汽车对象使用了另一个类Engine中的函数功能,也是一种组合
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | classEngine:    defstart(self):        print("Engine started.")    defstop(self):        print("Engine stopped.")classCar:    def__init__(self):        self.engine =Engine()  # Car类包含Engine类对象    defstart(self):        print("Car starting.")        self.engine.start()    defstop(self):        print("Car stopping.")        self.engine.stop()car =Car()car.start()car.stop()# 输出Car starting.Engine started.Car stopping.Engine stopped. | 
案例3:商品和订单的组合关系
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | classProduct:    def__init__(self, name, price):        self.name =name        self.price =price    definfo(self):        print(f"Product: {self.name}, Price: ${self.price}")classOrder:    def__init__(self, order_id):        self.order_id =order_id        self.products =[]    # 添加商品    defadd_product(self, product):   # 接收一个实例对象(包括对象的所有属性和方法)        self.products.append(product)    # 展示商品    defdisplay(self):        print(f"商品订单: {self.order_id}")        print("商品展示:")        forproduct inself.products:  # 实例对象列表,每次循环都是一个实例            product.info()   # 商品实例调用商品对象的内部info方法,打印商品名和价格信息            print("-----------")# 创建产品,实例化过程product1 =Product("Phone", 999)product2 =Product("Laptop", 1499)product3 =Product("Headphones", 199)# 创建订单,实例化过程order =Order("ORD-123")order.add_product(product1)  # 把实例传进去order.add_product(product2)order.add_product(product3)# 显示订单信息,order是一个实例对象order.display() | 
 
                    
                 

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号