学了Python的面向对象相关的知识(话说我学了几遍面向对象了?),下面是学习笔记:
面向对象基础
-
编程思想
就是人们利用计算机来解决问题的思维
-
分类
-
面向过程
强调以步骤为基础完成各种操作
-
面向过程
- 参考思维:概述,思维特点,举例,总结 强调以对象为基础完成各种操作,基于面向过程
-
三大思想特点:
-
更符合人们的思考习惯
-
把复杂的事情简单化
-
把人们从执行者变成指挥者 * 举例:越符合当时的场景越好 * 总结:万物皆对象
-
面向对象三大特性
-
-
封装
- 概述
封装就是隐藏对象的属性和实现细节,仅对外公开接口
-
举例
- 电脑,手机,函数, 类 = 属性 + 行为
-
好处
-
提高代码的安全性.(私有化)
提高代码的复用性.(函数)
-
继承
- 概述
子类继承父类的成员,例如:属性,行为等. 大白话:子承父业.
-
好处
提高代码的复用性.
-
多态
- 概述
大白话:同一个事物在不同时刻表现出来的不同状态,形态.
专业版:同1个函数,接收不同的对象,有不同的效果,
类与对象 就是 抽象与具体 对象是类的具体体现和实现
案例
class Car: #创建类
def run(self):
print(f"{self}汽车在跑~~")
def work(self):
self.run() #类内调用方法
#创建该类的对象
car = Car() #实例化
car.run() #调用类的方法简写: Car#run()
- self关键字
用于指向对象实例本身
谁调用函数,self就代表哪个对象
-
对象属性
- 类外设置属性
对象名.属性名 = 值
类外设置的属性是该对象独有的属性
- 类内设置属性
- self.属性名 = 值(
__init__内) - 属性名 = 值(所有对象共有)
-
魔法方法
-
在特点条件下会自动被调用的方法
-
格式:
def __方法名__(self):pass__init__(self)(新创建对象时自动调用)class Car: def __init__(self): #无参构造 self.属性名 = 值 #def __init__(self,值1): #有参构造 #self.属性名 = 值1 #注意:Python中没有函数重载(不能有同名函数) c1 = Car() #c2 = Car(值1)__str__(self)(打印对象时调用)python def __str__(self): #默认返回对象的地址值 return ...(字符串)-
__del__(self)(删除对象时调用,不主动调用就在程序结束后调用)``` python def del(self): ...
del 对象名(手动调用) ```
-
面向对象高级
封装
封装就是把数据(属性)和操作数据的函数(方法)捆绑在一起,形成一个独立的单元(类),并隐藏内部的实现细节,只对外暴露必要的功能(方法)。
class Car:
# 类属性(所有实例对象共享的)
wheel = 4 # 轮胎数量
tax_rate =0.1 # 购置税税率
def __init__ (self, c_color, c_brand, c_name, c_owner): #公有
# 实例属性#对象属性
self.color = c_color
self.brand = c_brand
self.name = c_name
self. _owner = c_owner #私有属性
def start(self): # 启动
print(f'{self.brand} {self.name} 正在启动 ... ')
def stop(self):# 停止
print(f'{ self.brand} {self.name} 停止行驶 .. ')
def charge(self):
print(f'{self.brand} {self.name} 正在加油 ')
def __control_fuel(self): #私有方法
print(f'{self.brand} {self.name} 控制燃油分配 ... ')
私有 :私有的属性和方法只能在类的内部使用;Python中并没有真正的私有机制,约定在私有属性名和方法名前加 "__" (两个下划线)。
car = Car(奥迪,A6,黑色,汐)
print(car._Car__owner) #强行调用私有属性
car._Car__control_fuel() #强行调用私有方法
#(_类名)前缀 + 变量名
- 类属性 类属性只能通过
类名.变量名来修改 (对象名.变量名只会添加对象属性)
继承
object类是所有类的父类,Python中所有的类都直接或间接继承自object类
class FuelCar(Car):
pass
#格式: class 子类(父类):
继承 描述的是两个类之间的关系,子类继承父类,就可以获取到父类的属性和方法。(非私有)
多层继承 :Car继承自object类,而FuelCar继承自Car类
- 重写
def charge(self):
print(f'{self.brand} {self.name} 正在加油(重写) ')
#正常函数格式(函数名相同)
- 子类调用父类方法
#方式一:
#suoer().__init__(self) 当属性名重写时
super().方法名() #只能访问最近的父类
#self.重写属性名 = 重写值 同上
#e.g.: super().charge()
#方式二:
#父类名.__init__(self) 当属性名重写时
父类名.方法名(self)
#self.重写属性名 = 重写值 同上
#e.g.: Car.charge(self)
- 多继承
class 子类名(父类名1,父类名2,...):
...
#注意:当一个类继承了多个父类时,默认优先使用第一个父类中的同名属性或方法(方法重写则优先重写的方法),可以使用 类名 .__ mro __ 属性 或 类名.mro()方法查看调用顺序。
def __init__(self,brand,model,color,owner,version):
父类1.__init__(self,brand,model,color,owner)
父类2.__init__(self,version)
多态
多态是指同一个方法,具有不同的形态、行为、表现。
实现条件 1. 有继承 2. 函数重写 3. 父类引用指向子类对象
def handle_charge(car:Car):
car.charge()
handle_charge(子类1car) #调用子类1中的charge()
handle_charge(子类2car) #调用子类2中的charge()
没有继承关系的类之间只要有相同的方法名,就可以调用这个方法
def go_swimming(duck:Duck):
duck.swimming
go_swimming(Duck("唐老鸭"))
go_swimming(Dog("旺财"))
go_swimming(Pig("佩奇"))
就想上面这个案例中,Duck Dog Pig类中都有swimming()这个方法,于是就可以用一个函数go_swimmming()调用,哪怕其限制传入Duck类型的参数(因为类型的注解不具有强制性)
类方法和静态方法
类方法即类所拥有的方法.
- 属于类的方法,可以通过 类名.还可以通过 对象名. 的方式来调用.
- 定义类方法的时候,必须使用装饰器
@classmethod,且第1个参数必须表示 类对象.
class Dog (object) :
@classmethod #装饰器
def eat (cls) : #cls表示类对象(可以换成其他名字)
print("小狗都喜欢啃硬骨头 ... ”)
# 类名直接访问
Dog. eat ()
# 对象名访问
dog = Dog()
dog. eat ()
静态方法
-
属于该类下所有对象所共享的方法,可以通过 类名.还可以通过 对象名. 的方式来调用.
-
定义静态方法的时候,必须使用装饰器
@staticmethod,且参数传不传都可以.
@staticmethod
def 函数名():
函数体
区别:
-
类方法的第1个参数必须是 类对象,静态方法无参数的特殊要求
-
你可以理解为:如果函数中要用 类对象,就定义成类方法,否则定义成 静态方法,除此外,并无任何区别.
最后,我还编写了一个学生管理系统的案例: 源码:
可执行程序(exe):