python学习笔记DAY15(面向对象编程)
这是我个人的学习笔记,都赖于(egon老师)的分享,以下是老师博客的原地址:
https://www.cnblogs.com/xiaoyuanqujing/articles/11640888.html
面向对象编程
一、对象的概念
-
“面向对象”的核心是“对象”,而对象的精髓在于“整合”。
-
事实上所有的程序都是有“数据”与“功能”组成,因此编写程序的本质就是定义出一系列的数据,然后定义出一系列的功能来对数据进行操作。
- 在之前的学习内容中,程序中的数据与功能是分离开的:
# 数据:name age sex
name = "nida"
age = 20
sex = "female"
# 功能: tell_info
def tell_info(name,age,sex):
print(f"{name,age,sex}")
tell_info(name,age,sex)
如上:如果想查看全部个人信息,需要同时有两样东西,一个是功能函数tell_info,一个是全部的个人信息变量。才能得到结果
- 而对象就想是一个容器,可以存放数据与功能,所以:把数据与功能整合到一起的产物,就是对象。
二、类和对象
类,顾名思义就是类别/种类,在python中类是实现面向对象编程不可或缺的工具。当我们有多个对象,而多个对象又有许多同样的属性时,就可以把这些相同的属性提取出来,放到类中共所有对象共同使用。
-
虽然我们人类的逻辑思维中,是先拥有多个对象---->提取对象的相同属性与功能---->创建类保存这些数据与功能
-
但是在程序中,必须要先定义类(定义好相同的内容)---->然后再调用类产生对象---->(调用类拿到的返回值就是对象)
产生对象的类与对象之间存在关联:
- 对象可以访问到类中共有的数据个功能,所以类中的数据依然是数据对象的。
- 类只不过是一种节省空间、减少代码冗余的机制。
三、面向对象编程
3.1类的定义与实例化
以下以选课系统为例,简单介绍面向对象的思想是如何编写程序的。
面向对象编程基本思路:
1. 把程序中要用到的、相关联的数据整合到对象里,然后再去使用
2. 但程序中用到数据及功能很多,改如何分类关联?
3. 先提取选课系统涉及的全部角色:学生,老师,课程等。
4. 而 学生,老师,课程 都有自己的数据和功能
以下,以学生为例:
# 学生的数据有 (学校/名字/年龄/性别)
# 学生的功能有 (选课)
# 学生1
数据:
学校 = 北大
姓名 = 陈秀
性别 = 男
年龄 = 20
# 学生2
数据:
学校 = 北大
姓名 = 钱多多
性别 = 男
年龄 = 21
# 学生3
数据:
学校 = 北大
姓名 = 徐颖
性别 = 女
年龄 = 19
根据以上数据,提取一个学生类,这个类中可以有的共同属性是:数据学校,功能选课。
接下来开始定义类,然后调用类产生对象:
class Student:
school = "北大"
def chose(self):
print(f"{self.name}正在选择一门课程")
在类体中最常见的是:
- 变量的定义和函数的定义。(但其实可以包含任意python代码)
- 类体的代码在定义阶段就会执行,会产生新的名词空间来存放类中定义的名称。
- 可以打印Student.dict_,查看当前类存放的所有内容
print(Student.__dict__)
# {...'北大', 'chose': <function Student.chose at 0x000001543482C5E0>,...}
- 调用类的过程称为:实例化(拿到返回值就是程序中的对象,或者叫实例)
# 每实例化一次得到一个学生对象
stu1 = Student()
stu2 = Student()
stu3 = Student()
如上,三个学生对象的数据都是一样的(类中共同的数据),没有独有的数据。
- 在实例化中为每个学生添加独有的数据:需要新增一个_init__方法:
class Student:
school = "北大"
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def choose(self):
print(f"{self.name}正在选择一门课程")
如上,init方法:
- 该方法会在对象产生之后自动执行
- 专门为对象进行初始化操作
- 可以有任意代码,但返回值只能是None
- 然后创建三个有自己独有数据的学生对象
stu1 = Student("陈秀","男",18)
stu2 = Student("钱多多","男",20)
stu3 = Student("徐颖","女",19)
- 分析对象创建过程(以stu1为例)
调用类之后会产生一个空对象stu1,然后将调用类时传入的参数一起传给Student.init_
# 在创建对象时,会将左侧的空对象当做参数传给第一个值(self)
def __init__(self,name,sex,age):
self.name = name # stu1.name = "陈秀"
self.sex = sex # stu2.sex = "男"
self.age = age # stu3.age = 20
以上,我们一共创建了三个对象,一个类。
**总结 **实例化的过程:
- 产生一个空对象。
- 自动调用init方法,将空对象和参数一起传入。
- 然后返回初始化完毕的对象。
3.2属性访问
- 类属性与对象属性
对象的名称空间值存放自己独有的属性,而对象们相同的属性是存放在类里面的。访问类的属性值有一个叫_dict__的方法,比如Student.__dict["school"],但python提供了专门访问/修改/删除/新增 属性的方法:
# 查看属性
Student.school # 北大 相当于:Student.__dict__[school]
Student.choose() # <function Student.choose at 0x00000205DA33C9D0>
# 新增属性
Student.city = "北京" # 相当于:Student.__dict__[city] = "北京"
print(Student.__dict__) # {...'city': '北京'}
# 修改属性
Student.school = "北京大学" # 相当于Student.__dict__[school] = "北京大学"
print(Student.school) # 北京大学
# 删除属性
del Student.city # 相当于 del Student.__dict__["city"]
print(Student.__dict__) # city 已经被删除
操作对象的属性也是一样的:
stu1.name # 查看
stu1.height = 186 # 新增
stu1.sex = 23 # 修改
del stu1.height # 删除
- 属性查找顺序与绑定方法
对象在访问属性时,会优先从对象本身dict中找,如果没有就去类的dict中查找。
- 类中定义的变量是所有对象共用的,都指向的是同样的内存地址
- 类中定义的函数也是所有对象共用的,但是绑定给不同对象之后,就是不同的绑定方法,内存地址各不相同。
# 类 和 对象 分别调用类体的变量
print(id(Student.school)) # 2418617550480
print(id(stu1.school)) # 2418617550480
# 所以:当类修改自己的变量值时,所有使用类原生变量的对象,也会跟着改变
# 而 这些对象如果改自己所引用的变量,受影响的只有当前对象
# 类调用自身的方法 与 对象调用类的方法 的区别
print(stu1.choose) # <bound method Student.choose of <__main__.Student object at 0x00000255AFD8BBE0>>
# 如上,对象调用类的方法,并没有新增一个方法的内存空间,而是一个绑定了类的方法的链接
print(Student.choose) # <function Student.choose at 0x00000255AFD7CA60>
# 绑定方法
# 类 和 对象 分别调用类体的函数
print(id(Student.choose)) # 2418617600608
print(id(stu1.choose)) # 2418617673280
print(id(stu3.choose)) # 2418617673216
print(id(stu2.choose)) # 2418617673280
备注:绑定到对象的方法的特殊之处在于,绑定给谁就是有谁来调用,调用时把“调用者”本身,当做第一个参数传入。
- 其实关于对象的概念,我们一直在使用,比如:list
# 实例化 3 个列表对象
l1 = list([1,2,3]) # 其实就是 实例化list的对象l1 ,把l1作为空对象当成第一个参数,括号内为后续参数,传入对象
l2 = list(["nida","lili","yoayao"])
l3 = list(["nida","lili","yoayao"])
# 每个实例化对象的 方法 内存地址 各不相同
print(l1.append) # <built-in method append of list object at 0x0000027324CBEA00>
print(l2.append) # <built-in method append of list object at 0x0000027324CBEA40>
print(l3.append) # <built-in method append of list object at 0x0000027324CBEA80>
- 总结:
对象是一个高度整合的产物,有了对象,我们只需要“对象.***” 就可以得到跟对象相关的所有数据与功能,十分方便,解耦合程度极高。

浙公网安备 33010602011771号