以步骤和过程为核心的编程范式,其核心思想是将复杂问题分解为一系列可顺序执行的函数或过程,通过逐步调用来实现整体功能
核心思想
- 步骤分解:将问题拆解为多个子任务,每个子任务由独立的函数实现,例如,处理学生早上的活动可分解为“起床→穿衣→洗漱→去学校”等步骤,每个步骤对应一个函数
- 顺序执行:程序按代码的书写顺序从上到下执行,通过条件语句(如if)和循环结构(如for)控制流程
- 数据与操作分离:数据存储在全局或局部变量中,函数通过参数接收数据并处理,结果通过返回值或修改变量传递。
典型特征
- 模块化函数:功能封装为函数,例如计算两数之和的函数
add(),通过调用实现代码复用。 - 线性流程:程序逻辑清晰,易于调试。例如读取文件数据→处理数据→输出结果的流程。
- 高效性:适用于简单任务或对性能要求高的场景,因无需对象创建开销。

面向对象(Object)
一种以对象为核心的编程范式,通过模拟现实世界中事物的交互逻辑来构建程序。其核心思想是将数据与操作数据的方法封装成独立的对象,通过对象之间的协作实现复杂功能
核心概念
- 类(Class):定义对象的模板,描述一类事物的共性特征(如属性)和行为(如方法)。例如,”汽车”类包含属性”颜色”和方法”加速”。
- 对象(Object):类的具体实例,拥有独立的状态(属性值)和行为。例如,一辆红色汽车是”汽车”类的对象
- 封装(Encapsulation):将数据和方法捆绑在对象内部,仅通过暴露的接口与外界交互,保护数据安全并简化使用。例如,银行账户的余额只能通过特定方法修改。
- 继承(Inheritance):子类可复用父类的属性和方法,并扩展新功能,实现代码复用和逻辑分层。例如,”电动车”类继承自”汽车”类,新增”充电”方法。
- 多态(Polymorphism):同一方法在不同对象中呈现不同行为,增强代码灵活性。例如,”动物”类的”发声”方法在”狗”和”猫”对象中分别输出”汪汪”和”喵喵”。
- 抽象(Abstraction):提取共性特征形成接口或抽象类,隐藏复杂实现细节,例如定义”图形”类的抽象方法”计算面积”。
核心优势
- 可维护性:对象间低耦合,修改某部分代码不影响整体系统。- 可扩展性:通过继承和多态灵活扩展功能,无需重写现有代码。- 复用性:封装后的类可跨项目重复使用,减少冗余代码。- 逻辑直观:以现实世界模型组织代码,更符合人类认知。
两者对比
面向过程—怎么做
- 把完成某一个需求的
所有步骤从头到尾逐步实现 - 根据开发需求,将某些功能独立的代码封装成一个又一个函数
- 最后完成的代码,就是顺序地调用不同的函数
注重步骤与过程,不注重职责和分工,如果需求比较复杂,虽然有函数封装,但是还是会导致代码比较臃肿。开发起来比较复杂
面向对象—谁来做
相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
- 在完成某一个需求前,首先确定职责 —— 要做的事情(方法)
- 根据职责确定不同的对象,在对象内部封装不同的方法(多个)
- 最后完成的代码,就是顺序地让不同的对象调用不同的方法
特点
- 注重对象和职责,不同的对象承担不同的职责
- 更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路
- 需要在面向过程基础上,再学习一些面向对象的语法

类的规范和实例化讲解


==注意==:1.class定义类
2.实例化对象的时候,会自动调用 __init__ 来初始化,我们可以在 __init__ 中定义对象初始化的属性
3.self 在实例化对象时自动=实例p1,所以可以用self.属性或方法
4.__dir__查看对象内所有属性以及方法
类与对象
在面向对象中,类与对象是两个核心的概念
类
- 类是对一群具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用
- 特征 被称为 属性
- 行为 被称为 方法
- 类就相当于制造飞机时的图纸,是一个模板,是负责创建对象的
对象
- 对象是由类创建出来的一个具体存在,可以直接使用。
- 由哪一个类创建出来的对象,就拥有在哪一个类中定义的:属性 & 方法。
- 对象就相当于用图纸制造的飞机。
类的设计
在使用面相对象开发前,应该首先分析需求,确定一下,程序中需要包含哪些类

在程序开发中,要设计一个类,通常需要满足一下三个要素:
- 类名 这类事物的名字,满足大驼峰命名法
- 属性 这类事物具有什么样的特征
- 方法 这类事物具有什么样的行为
大驼峰命名法
CapWords
类名的确定
通常类名的选择,我们应该根据整个业务流程来提取,或者从大的角度来选择
属性和方法的确定
- 对对象的特征描述,通常可以定义成属性
- 对象具有的行为,通常可以定义成方法
类的定义
类的基本定于语法如下:
class Human:
'''
这里可以写上对于这个类的说明
'''
变量 = xxxx # 这里是类的静态属性,也可以理解为该类共有的特性
dic = {}
l1 = []
def __init__(self,xxx,xxx): # 初始化方法
pass
def func(self): # 方法,动态属性
pass
类的三大特性:封装,继承和多态
封装:将属性,方法封装到类内
将数据和方法捆绑在对象内部,仅通过暴露的接口与外界交互,保护数据安全并简化使用

==注意==:最好不要给类动态增加属性,不然破坏封装性原则,可以通过继承更改
私有和公有:访问控制

==注意==:约定self.__属性=属性为私有属性,def __方法(self,xxx,xxx)为私有方法,本质都可访问,java不同,私有不可外部访问
访问:实例名._Student__属性,python语法规范就是这样
类属性和实例属性
| 类型 | 属于 | 定义位置 | 内存 | 访问方式 |
|---|---|---|---|---|
| 类属性 | 类本身 | 类体内,方法外 | 只存一份,所有实例共享 | 类名.属性或实例.属性 |
| 实例属性 | 某个具体实例 | 通常在__init__内用self.xxx定义 |
每个实例各存一份 | 实例.属性 |
class Dog:
species = "Canis familiaris" # 类属性:所有狗共享的物种名
def __init__(self, name):
self.name = name # 实例属性:每只狗有自己的名字
dog1 = Dog("Buddy")
dog2 = Dog("Lucy")
print(Dog.species) # Canis familiaris 通过类访问
print(dog1.species) # Canis familiaris 实例也能读(向上查找)
print(dog2.species) # Canis familiaris
Dog.species = "犬科" # 修改类属性
print(dog1.species) # 犬科(受影响,因为共享)
dog1.name = "Max" # 修改实例属性
print(dog2.name) # Lucy (互不影响)

@staticmethod静态方法装饰器
不需要传入self,本质就是个普通函数,只是放在类的命名空间里,调用直接用类.方法
本质:为了定义类方法,类.方法读取
计数器计算多少个实例对象
class Dog:
count = 0 # 类属性:计数器
def __init__(self, name):
Dog.count += 1 # 每次实例化,类属性加1
self.name = name # 实例属性class Dog:
count = 0 # 类属性:计数器
def __init__(self, name):
Dog.count += 1 # 每次实例化,类属性加1
self.name = name # 实例属性
a = Dog("Buddy")
print(Dog.count) # 1
b = Dog("Lucy")
print(Dog.count) # 2
==注意==:类属性类似于模块的全局变量,修改后全局共享,但是被命名空间限制在类里,所以由实例共享,创建一个改为1,创建第二个自动在修改后的1,后面加1变为2
继承:复用父类的属性,方法,和增加新属性,方法
子类可复用父类的属性和方法,并扩展新功能,实现代码复用和逻辑分层
单继承(yes),多继承(pass)
单继承:只继承自一个父类
调用父类.jpeg)
==注意==:子类方法重写:默认覆盖父类方法,要在新方法中调用super( )父类属性或方法,再增加新功能,super只会找上一级父类,上一级也可能继承自别的,也有super(),所以不要搞的继承很多,很复杂
多态:实例方法的角度
同一方法在不同对象中呈现不同行为,增强代码灵活性

==注意==:不管实例化对象是什么,都继承了基类的基础属性和方法,直接定义一个函数,函数体内调用具体方法
本质:调用函数把实例对象作为参数传进去,即实例对象().具体方法
鸭子类型
- 如果像鸭子一样叫,就当成鸭子
- ==Python不强制继承关系,只要对象有对应方法就可以==

鸭子类型的本质:它是一种”不通过继承,而通过方法兼容性”来实现多态,关注对象能做什么,而不是它是什么,偶然的行为兼容
java vs python
- Python:本身就符合语法规则,天生的真’鸭子类型’
- Java:必须制要求显式的继承或接口关系,为了通过编译器类型检查,如果不建立显式接口关系,直接用多态的方法调用会报错,静态类型系统为了安全性和可维护性的设计选择,所以==设计鸭子类型来进行
java和别的静态类型语言的多态开发==
反射:以字符串形式直接到类方法调用
在运行时,根据字符串动态的操作对象

==注意==:核心思路是由字符串直接到类方法执行,原本是创建实例调用,现在直接操作,hasattr和getattr是判读实例对象里有这个方法或属性,getattr是得到这个方法或属性
Python测试框架原理


- globals( )打印结果
{ '_name_': '_main_', '_doc_': None, '_package_': None, '_loader_': <frozen_importlib_external.SourceFileLoader object at 0x0000023358750680>,
'_MathTwoNumber_': '_run_all_tests_': <function run_all_tests at 0x0000023358750680>}None, '__loader__': <frozen_importlib_external.SourceFileLoader object at 0x0000023358781C10>, '_spec__': None, '_annotated_namespace': None, '_file__': 'C:UsersLiDesktopprojectdeepseekaitext.py', '_cached__': None, 'MathTwoNumber': <Class '__main__.MathTwoNumber >,'run_all_tests': <function run_all_tests at 0x0000023358750680> }
globals()以字典形式把 内置名称,当前模块的模块信息,自定义的全局变量、函数、类,导入的模块
dir(instance)运行结果是:实例对象的所有方法名
(venv) PS C:UsersliDesktopprojectdeepseekai> python .text.py
add方法通过测试
mul方法通过测试
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'add', 'b', 'mul', 'test_add', 'test_mul']
globals()[test_class_names]运行结果:在globals( ) 字典里取相应的类

MRO算法
多继承中,子类调用一个属性或顺序时,Python按照什么顺序在继承链中搜索
口诀:子类在前,父类在后 ; 多父类时,左父先于右父;最后运行共同父类,只运行一次
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
object
|
A
/
B C
/
D
MRO(D) → [ D , B , C , A , object ]
顺序方向:从左到右查找
本质:你写的代码经过MRO算法会优化搜索顺序