前言

写代码时,你是否曾想过把现实世界的事物搬进程序里?比如一只狗会“汪汪”,一只猫会“喵喵”,而它们都属于“动物”。这正是面向对象编程(OOP)的魅力所在。


Python面向对象基础

面向对象的基本概念

Python是一门面向对象的语言(也是一门面向过程的语言)。要掌握面向对象的基本语法,则首先需要掌握两个重要的概念:类、对象。
在这里插入图片描述
类: 对现实事物的抽象描述
对象: 现实事物的具体体现

Python类:

# 定义类
class 类名:
    # 定义方法
    方法列表...
# 1.定义类
class Car:
    # 2.定义类方法
    def run(self):
        print("能跑起来了...")

对象的基本语法格式
Python对象实例化:

对象名 =()

调用方法:

对象名.方法名()	
# 定义类
class Car:
    def run(self):
        print("能跑起来了...")

# 创建对象: 对象名 = 类名()
car = Car()
# 调用行为: 对象名.方法名()
car.run()

self关键字
Self是python内置的关键字,用于指向对象实例本身。

class Car:
    def run(self):
        print("车跑起来了")
    def work(self):
        self.run()
car = Car()
car.work()

在这里插入图片描述

self的常见作用:在类的内部调属性和方法

添加和获取对象属性

属性表示的是固有特征,在Python中使用变量表示,例如人的姓名、年龄、身高、体重等,都是对象的属性。
设置属性

对象名.属性 = 属性值
car.color = "黑色"	# 定义属性,并给属性color赋值
car.number = 10		# 给属性number赋值

获取属性值

对象名.属性
print("颜色:%s"%car.color)
print("轮胎数:%d"%car.number)
class Car:
    def run(self):
        print("车跑起来了")
car = Car()
car.color = '黑色'
car.number = 10
print(f"车的颜色为:{car.color}")
print(f"车的数量为:{car.number}")

在这里插入图片描述
类内部获取属性值

self.属性
class Car:
    def show(self):
        # 对象名.属性  = self.属性
        print(f"车的颜色为:{self.color}")
        print(f"车的数量为:{self.number}")
car = Car()
car.color = '黑色'
car.number = 10
car.show()

在这里插入图片描述

魔法方法

在Python中,有一些可以给Python类增加魔力的特殊方法,它们总是被双下划线所包围,我们称之为魔法方法。
在特殊情况下会被自动调用,不需要开发者手动去调用。

__魔法方法名__()

init()方法

自动调用
在Python中,当新创建一个对象时,则会自动触发__init__()魔法方法。
无参数情况:不需要外面传递参数,初始化属性值
有参数情况:当需要外面传递参数,初始化属性值

class Car:
    # 初始化:无参数,类内部直接赋值
    def __init__(self):
        self.color = 'blue'
        self.number = 10
    def show(self):
        # 对象名.属性  = self.属性
        print(f"车的颜色为:{self.color}")
        print(f"车的数量为:{self.number}")
car = Car()
car.show()

在这里插入图片描述

class Car:
    # 初始化:无参数,类内部直接赋值
    def __init__(self,color,num):
        self.color = color
        self.number = num
car = Car("蓝色",10);
print(f"车的颜色:{car.color},车的数量:{car.number}")

在这里插入图片描述

str_()方法

自动调用
当使用print输出对象时,默认打印对象的内存地址;如实现了__str__()方法,print就自动调用该魔法方法。

def __str__(self):
    # ...
    return 字符串结果
class Car:
    # 初始化:无参数,类内部直接赋值
    def __init__(self,color,num):
        self.color = color
        self.number = num
    def __str__(self):
        return "车的颜色:"+self.color+",车的数量:"+str(self.number)
car = Car("玫瑰色",10);
print(car)

在这里插入图片描述

del_()方法

当删除对象时(调用del删除对象或文件执行结束后),Python解释器会默认调用__del__()方法。

def __del__(self):
    # ...
# 定义类
class Car:
    # 初始化方法:定义品牌类
    def __init__(self,brand):
        self.brand = brand
    # 定义删除的方法
    def __del__(self):
        print("del 自动调用了__del__()方法")
# 创建对象
car = Car("BYD")
# 获取品牌属性
print(car.brand)
# 删除对象
del car
# 获取品牌属性,报错
print(car.brand)

在这里插入图片描述

Python面向对象高级

定义类的几种语法

方式1:类名

class 类名:
     代码
 # 定义教师类
class Teacher:
     ...

方式2:类名()

class 类名():
     代码
     ...
# 定义教师类
class Teacher():

方式3:类名(object)

class 类名(object):
     代码
     ...
# 定义教师类
class Teacher(object):
    ....

python中的继承

面向对象代码中的“继承”:指子类继承父类的属性和方法
类是用来描述现实世界中同一组事务的共有特性的抽象模型,但是类也有上下级和范围之分
在这里插入图片描述

注意: 继承指的是类的继承,而不是对象的继承 

在Python中,继承形式:

class 父类名(object): 
    ...(省略)
class 子类名(父类名):
    ...(省略)    

在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。

继承:一个类从另一个已有的类获得其成员的相关特性,就叫作继承! (站在子类角度)
派生:从一个已有的类产生一个新的类,称为派生! (站在父类角度)
很显然,继承和派生其实就是从不同的方向来描述的相同的概念而已,本质上是一样的!

父类:也叫作基类,就是指已有被继承的类!
子类:也叫作派生类或扩展类

单继承和多继承

单继承就是一个子类只能继承自一个父类,不能继承多个类。这个子类会有具有父类的属性和方法。
基本语法:

 # 父类Father
class Father(object):
    pass

# 子类Son
class Son(Father):
    pass

多继承就是一个类同时继承了多个父类,并且同时具有所有父类的属性和方法。例如:孩子会继承父亲和母亲的方法和属性
基本语法

# 父类1Father
class Father(object):
    pass

# 父类2Mother
class Mother(object):
    pass

# 子类Son
class Son(Father,Mother):
    pass

# 1. 师父类,属性和方法
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
# 为了验证多继承,添加School父类
class School(object):
    def __init__(self):
        self.kongfu = '[创新煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')

# 2. 定义徒弟类,继承师父类 和 学校类
class Prentice(School, Master):
    pass
#3. 用徒弟类创建对象,调用实例属性和方法
hgq = Prentice()
print(hgq.kongfu)
hgq.make_cake()

在这里插入图片描述

当一个类有多个父类时,默认使用第一个父类的同名属性和方法,可以使用类名.__mro__属性或类名.mro()方法查看调用的先后顺序。
注:MRO(Method Resolution Order):方法解析顺序

# 通过属性查看引用顺序
print(Prentice.__mro__)
# 通过方法查看引用顺序
print(Prentice.mro())

在这里插入图片描述

子类重写父类同名方法和属性

重写也叫作覆盖,就是当子类属性或方法与父类的属性或方法名字相同时,从父类继承下来的成员可以重新定义!
子类重写父类的属性和方法, 优先会调用子类的属性和方法

# 1. 师父类,属性和方法
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')
# 为了验证多继承,添加School父类
class School(object):
    def __init__(self):
        self.kongfu = '[创新煎饼果子配方]'
    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')

# 2. 定义徒弟类,继承师父类 和 学校类
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        print(f'运用{self.kongfu}制作煎饼果子')

hgq = Prentice()
print(hgq.kongfu)
hgq.make_cake()

在这里插入图片描述
如果子类和父类拥有同名属性和方法,子类创建对象调用属性和方法的时候,调用到的是子类里面的同名属性和方法

子类中仍想要保留父类的行为,则需要在子类中调用父类方法.可以直接使用父类名来进行调用,使用的方法:

父类名.父类方法名(self)
 class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')
    def make_school_cake(self):
        School.__init__(self) # 父类初始化
        School.make_cake(self)
    def make_master_cake(self):
        Master.__init__(self) # 父类初始化
        Master.make_cake(self)
hgq = Prentice()
hgq.make_cake()
hgq.make_master_cake()
hgq.make_school_cake()
hgq.make_cake()

在这里插入图片描述
子类调用父类方法
使用super()调用父类方法,使用的方法:

super().父类方法名(self)
# 2. 定义徒弟类,继承师父类 和 学校类
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'

    def make_cake(self):
        self.__init__()
        print(f'运用{self.kongfu}制作煎饼果子')
    def make_old_cake(self):
        super().__init__()
        super().make_cake()
hgq = Prentice()
hgq.make_cake()
hgq.make_old_cake()

在这里插入图片描述

python中的封装

在软件编程中,将属性和方法书写到类的里面的操作即为封装,封装可以为属性和方法添加私有权限。

私有属性和私有方法

在Python中,可以为属性和⽅法设置私有权限,即设置某个属性或⽅法不继承给⼦类。
设置私有属性和方法的方式:在属性或方法名前面加上 __,格式:

# 私有属性
__属性名

# 私有方法
def __方法名():
    ...

私有属性和方法使用规则:

  • 只能在类的内部使用,不能在类的外部使用;
  • 如果想在类的外部使用通过公共接口

私有属性不能直接访问,在Python中,一般定义方法名’ get_xx ‘用来获取私有属性,定义’ set_xx '用来修改私有属性值。

# 2. 定义徒弟类,继承师父类 和 学校类
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[独创煎饼果子配方]'
        self.__money = 20000
    ......
    # 得到私有属性__money
    def get_money(self):
        return self.__money
    # 修改私有属性__money
    def set_money(self,money):
        self.__money = money
hgq = Prentice()
print(hgq.get_money())
hgq.set_money(10000)
print(hgq.get_money())        

在这里插入图片描述

访问私有方法,可以使用重新设置一个公有方法来访问。

	 # 私有方法
     def __make_cake(self):
             print(f'运用{self.kongfu}制作煎饼果子’)

     def make(self):
         self.__make_cake()

python中的多态

多态,指的是:多种状态。比如:同样一个函数在不同的场景下有不同的状态

class Animal:
    def speak(self):
        pass
class Dog(Animal):
    def speak(self):
        print("汪汪汪")
class Cat(Animal):
    def speak(self):
        print("喵喵喵")

def make_noise(animal : Animal):
    animal.speak()

dog = Dog()
cat = Cat()
make_noise(dog)
make_noise(cat)

在这里插入图片描述

: Animal 是类型注解(Type Hint),它表示:参数 animal 期望的类型是 Animal 类(或者它的子类)

同样的行为(函数),传入不同的对象,得到不同的状态

实现多态的三个条件
1、有继承 (定义父类、定义子类,子类继承父类)
2、函数重写 (子类重写父类的函数)
3、父类引用指向子类对象 (子类对象传给父类对象调用者)

多态的好处
在不改变框架代码的情况下,通过多态语法轻松的实现模块和模块之间的解耦合;实现了软件系统的可拓展

继承相当于:孩子可以复用老爹的东西。
多态相当于:老爹框架,不做任何修改的情况下,可以可拓展的使用后来人(孩子)写的东西。

抽象类(接口)

父类Animal的speak方法,是空实现

class Animal:
    def speak(self):
        pass

在 Python 中,pass 是一个空操作语句,执行时什么也不做。它主要用于语法上需要一条语句、但程序逻辑上不需要任何操作的场合。

这种设计的含义是:

  • 父类用来确定有哪些方法(父类制定接口标准)
  • 具体的方法实现有子类来实现(子类实现接口标准)

这种写法,就叫做抽象类(也可以称之为接口)

抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法

在这里插入图片描述
抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现

class AC:
    #制冷
    def cool_wind(self):
        pass

    # 制热
    def hot_wind(self):
        pass
    #左右摆风
    def swing_l_r(self):
        pass

class Midea_AC(AC):
    def cool_wind(self):
        print("美的空调制冷")

    def hot_wind(self):
        print("美的空调制热")
    def swing_l_r(self):
        print("美的空调左右摆风")
class GREE_AC(AC):
    def cool_wind(self):
        print("格力空调制冷")

    def hot_wind(self):
        print("格力空调制热")
    def swing_l_r(self):
        print("格力空调左右摆风")

def make_cool(ac : AC):
    ac.cool_wind()

midea = Midea_AC()
gree = GREE_AC()
make_cool(midea)
make_cool(gree)

在这里插入图片描述

面向对象的其他属性

属性

类或对象中的属性都属于属性

对象名.属性名
self.属性名

类属性

类属性,指的就是类所拥有的属性,它被共享于整个类中(即都可以直接调用)。

类名.类属性名    # 推荐使用
对象名.类属性名
class Person:
    count = 10

print(Person.count)
p = Person()
print(p.count)

在这里插入图片描述

类方法

所谓类方法,指的是类所拥有的方法,并需要使用装饰器@classmethod来标识其为类方法,同时一定要注意的是对于类方法的第一个参数必须是类对象,通常以cls作为第一个参数名。

@classmethod
def 类方法名(cls):
    ...
类名.类方法名    # 推荐使用
对象名.类方法名
class Cat:
    @classmethod
    def eat(cls):
        print("猫都喜欢吃鱼")
Cat.eat()
c = Cat()
c.eat()

在这里插入图片描述

静态方法

静态方法需要通过装饰器@staticmethod来标识其为静态方法,且静态方法不需要多定义参数。

@staticmethod
def 静态方法名():
    ...
类名.静态方法名    # 推荐使用
对象名.静态方法名

总结

面向对象不仅仅是语法技巧,更是一种组织复杂程序的思维方式。当你下次再写 Python 代码时,不妨尝试用类来抽象现实逻辑,让代码更贴近自然的认知。实践出真知——快打开你的编辑器,创建一个属于你的 Animal 王国吧!

更多推荐