用代码“收养”一只宠物:Python 面向对象编程轻松学
前言
写代码时,你是否曾想过把现实世界的事物搬进程序里?比如一只狗会“汪汪”,一只猫会“喵喵”,而它们都属于“动物”。这正是面向对象编程(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 王国吧!
更多推荐


所有评论(0)