Python学习笔记--面向对象--基础
1.面向对象和面向过程的区别是?
-
面向过程:
-
把问题,拆解性小的流程。
-
优点是:把复杂问题,流程化后简单了。
- 缺点是:扩展性差。
-
-
面向对象:
-
优点是:扩展性强。
- 缺点是:将编程的复杂性变大。
-
2.面向对象编程,是什么?
-
核心是对象二字,那什么是对象?
-
对象是一个概念
- 是一个国外翻译过来的概念。
-
对象是一个容器
- 函数是一个容器,盛放功能的。
- 对象也是一种容器,盛放数据+功能的。
-
基于面向对象的编程思想,就是创造一个个容器,来梳理代码的。
- 同样,面向过程也是创造一个个函数,来梳理代码的。
3.面向对象可以比喻房子里的什么东西,来帮助理解?
-
面向过程(功能)
-
散落的木板 ==》 书架
- 冰箱零件 ==》 冰箱
-
-
面向对象(数据+功能)
- 书(数据)
- 书在地上,在厕所,在厨房 ==》书在书架上。【数据+功能】
- 大蒜(数据)
- 大蒜在地上,在卧室... ==》大蒜在冰箱里。【数据+功能】
- 韭菜(数据)
- 韭菜在地上,在客厅... ==》 韭菜在冰箱里。【数据+功能】
- 书(数据)
-
面向对象是一种归类。
- 原则是:把相关的放在一起。
- 比如,厨房这个容器。(对象)
- 盛放了数据【葱,姜,蒜,鸡蛋,韭菜,调味料】
- 盛放了功能【冰箱,电饭锅,微波炉】
- 比如,厨房这个容器。(对象)
- 原则是:把相关的放在一起。
-
冰箱这个容器到底是函数还是对象?
-
冰箱没有放任何数据的话
- 是一个函数。
- 它就是由一堆零件组成的。
-
冰箱盛放了数据的话
- 是一个对象。
- 它由零件组成的功能+盛放的数据【葱,姜,蒜,韭菜,黄瓜...】
-
-
如何区分,容器是函数还是对象?
-
关键在于是否承载了数据。
-
4.谈谈我理解的面向对象。
- 优点:扩展性好。
- 缺点,需要进一步整理,复杂度高了。
- 比如,我收拾房间。我要把书放在书架上。
- 我首先要买个书架子,快递发给我一套木板,一堆螺丝钉,一把螺丝刀。
- 我把这些东西组装起来,形成一个书架【功能】,功能性就是实现了。也就是函数实现了。
- 现在又要把,书放到书架上,我这个书架有5层,我书有人文的,自然的,历史的,IT的。
- 还有书看过的,没看过的,那些我判断是使用频率高的书籍,哪些是频率低的,把频率高的放在中间3层,4层,频率低的放在1层2层5层。
- 我根据这些原则,把这个书【数据】放在一起。这个过程,就完成了对象的概念。同样,我相比起函数,付出了更多的时间和精力,复杂性相比之前的函数,确实提高。同样的好处是,我更方便使用这个书架,每个书的位置,都有了一定的原则(索引位置)。找起来更方便了。
5.最能体现面向对象的扩展性强的是?
-
封装。
-
《封装》最能体现,但像 《继承》,反而与扩展性强是相违背的。
-
6.面向对象的演绎
-
原来的
-
# ============数据跟功能分开============== name = "liqi" age = 18 gender = "male" def tell_info(): print(f"名字是{name},年龄是{age},性别是{gender}") tell_info() # =====================================
-
-
收拾一下
- 把数据放到一起
-
# 把数据放到一个容器(字典里) def tell_info(student): print(f"学生的名字是{student['name']},年龄是{student['age']},性别是{student['gender']}") student = { "name": "liqi", "age": 18, "gender": "male", "tell_info": tell_info, } student["tell_info"](student) # 把数据由传3个,变为只传递1个 # 上面这也是一种面向对象的思想 # =====================================
-
再收拾一下
- 把功能也放进去
-
# # 尝试把函数的功能也放进去。(下面是的伪代码,不能运行) student = { "name": "liqi", "age": 18, "gender": "male", "tell_info": tell_info, def tell_info(student): print(f"学生的名字是{student['name']},年龄是{student['age']},性别是{student['gender']}") } student["tell_info"](student) # # # 后面python用一种更优雅的方式,把这些串到一起。 # =====================================
8.类和对象的关系是什么?
- 学生A,小明;学生B,小红;学生C,小华......这些是对象,具体的人。
- 他们的有共同的特点,都是学生,所以把他们归类成 [ 学生类 ]
-
总结:
-
对象是具体的人或物,类是抽象人或物的集合。
-
9.把对象转换为类
10.探究类里面的东西
11.定义类,调用类发生的事情。
-
定义类发生的事:
- 1.立刻运行类体代码
- 2.将运行过程中产生的名字都丢到类的名称空间中
-
调用类发生的事:
- 1.创造一个对象的字典,用来存放对象独有的数据
- 2.将对象与类建立好关联
12.类的初始化函数推演-1
- 简化11行-17行
-
13.类的初始化函数推演-2
-
1.把函数init放进类里面,建立关联
-
2.让init自动调用,使用双下划线__
-
14.类的初始化函数推演-3
15.类的属性查找
-
对象的属性:先从对象自己的字典找,没有再去类的字典里找
-
类的属性:从自己的字典找
-
类的数据属性:共享给所有对象的
-
class Student: school = "北京大学" def __init__(self, x, y, z): # 加了双下划线,就会自动调用 self.name = x self.age = y self.gender = z def tell_info(student): # 公共函数 print(f"学生的名字是{student['name']},年龄是{student['age']},性别是{student['gender']}") obj1 = Student("tom",19,"female") # 对象,属性的查找属性:先从对象的字典里找,再从类的字典里找 print(obj1.name) # obj1.__dict__['name'] print(obj1.school) print(obj1.tell_info) # 类的属性:从类自己的字典里找 print(Student.school) # 北京大学 print(Student.__init__) # <function Student.__init__ at 0x0000028E5CCC29D0> print(Student.tell_info) # <function Student.tell_info at 0x0000028E5CCDC1F0> # 类的数据属性是直接共享给所有对象用的 Student.school = "新的大学" print(Student.school,id(Student.school)) # 新的大学 2810465115760 print(obj1.school,id(obj1.school)) # 新的大学 2810465115760
16.类的绑定方法
-
类中的函数,是为对象服务的。
- 为了方便使用,python自动帮把调用者obj1本身当做第一个参数传入。
-
类的可以直接调用自己的方法。(等同于普通函数)
-
obj1.fun()会报错?背后的原因就是类把对象obj1当做第一个参数传入。
-
class Student: school = "北京大学" def __init__(self, x, y, z): self.name = x self.age = y self.gender = z def tell_info(self): # 变量名更改为self,下面也同步更改 print(f"学生的名字是{self.name},年龄是{self.age},性别是{self.gender}") def fun(): # 类中的函数(方法)是给对象使用的。 print("xxxx") obj1 = Student("tom",19,"female") obj2 = Student("liqi",16,"male") # 类中的函数:相当于普通函数,该怎么传参数就参数 # 但其实类中的函数是给对象用 # 对象来调用就是一个绑定方法,绑定方法的特点是会将调用当做第一个参数自动传入 print(Student.tell_info) Student.tell_info(obj1) Student.tell_info(obj2) # 对象的方法: 绑定方法,自动把调用者当做第一个参数传入。 print(obj1.tell_info) # 这是绑定方法 # 结果为 <bound method Student.tell_info of <__main__.Student object at 0x0000018C63BA8E20>> obj1.tell_info() # 把调用者obj1传入==> obj1.tell_info(obj1) # 可以这样使用,但类中的函数,是给对象使用的 Student.fun() obj1.fun() # TypeError: fun() takes 0 positional arguments but 1 was given
17.类中的术语:
-
类中的字典,叫属性。
-
类中的函数def ,叫方法。
18.封装是什么?
-
最简单来讲,封装是一种思想。把东西放到一起,方便使用。
- 举例来说,就是把东西放到麻袋里,外面看就是一个麻袋,里面装有很多东西。
- 在举例来书,书包也是一种封装,把书本,笔,电脑等封装到一个书包里。
19.类的隐藏属性
-
利用__country来隐藏属性
-
class People: # country = "China" __country = "China" def __init__(self,name,age): self.name = name self.age = age # print(People.country) # 隐藏后 # print(People.country) # 访问不到 # print(People.__country) # 也访问不到 print(People.__dict__) # 分析底层原理 print(People._People__country) # 可以访问到
20.类的隐藏方法
- 利用__func(self)来隐藏
-
class People: # country = "China" __country = "China" def __init__(self,name,age): self.name = name self.age = age def __func(self): print("xxx") # print(People.country) print(People.__dict__) # 分析底层原理 obj1 = People("LIQI",15) # 建立个self对象给到下面 People._People__func(obj1) # 可以访问隐藏方法 xxx
21.类的隐藏init的属性
- 利用self.__name = name来隐藏
-
class People: __country = "China" def __init__(self, name, age): self.__name = name self.__age = age def __func(self): print("xxx") # print(People.__dict__) # 分析底层原理 obj1 = People("tom", 20) # 建立个self对象给到下面 print(obj1.__dict__) # 查看对象的字典 # {'_People__name': 'tom', '_People__age': 20} print(obj1._People__age) # 非要访问的话
22.类的__开头的属性特点:
-
1.并没有真正的隐藏,只是变形
-
2.该变形只在类的定义阶段,扫描语法的时候执行,此后__开头的属性,不会变形。
-
3.该隐藏对外不对内
- 代码-特点2
-
obj1 = People("tom", 20) print(obj1.__dict__) # 变形 obj1.__gender = "female" print(obj1.__dict__) # 后赋值,不变形
- 代码-特点3-对外不对内:
-
class People: __country = "China" def __init__(self, name, age): self.__name = name self.__age = age def __func(self): print("xxx") def tell_name(self): print(self.__name) obj1 = People("tutu",18) obj1.tell_name()
23.类的隐藏属性,为什么要隐藏?
- 类中的东西,要么是数据,要么是功能。
- 为什么要隐藏属性(数据)?
- 准确来说__开头的数据,不是隐藏起来,是保护起来。
- 控制数据的访问形式。
- 用函数的形式,保护数据的类型,增加逻辑判断等。
- 比如:self.__name的修改
24.类的隐藏函数,为什么要隐藏?
- 有些琐碎的功能,不希望别人调用。
- 仅供内部使用的。
- 专业一点:隔离复杂度。
- 生活中,比如,开机只有一个键。
- 开机背后,封装了很多复杂的功能。
25.类是什么?
- 类是对象的归纳,是盛放对象与对象之间的公共部分,解决冗余问题的。
26.类和类之间要是有冗余怎么办?
- 这就引出了类的【继承】的概念。
- 继承就是为解决类与类支间的冗余。
27.继承有缺点吗?
- 有,继承是一种强耦合,彼此关联性强。
- 跟面向对象的扩展性的思想相悖。
- 所以要辩证的来看待。
28.类与对象的区别?
- 对象是盛放相关的数据和功能的容器。
- 类是盛放对象相似的数据和功能的容器。
29.比如一个学生类有很多数据,如何确定哪些数据是要用的?
- 根据场景来分析。
- 比如,学生数据中可以有,学号,性别,班级,爱好,兴趣,吃喝拉撒等等。
- 但在一个具体的场景,选课系统。那么学号,班级,就有关系。其他就信息就不重要,可以舍弃。
- 实际公司中,具体的需求分析,是产品经理组织开会,一起讨论出来的。
30.实例化是什么?
- 调用类的过程。
- (类是虚的,是抽象的,是概念的;实例是具体的事务,是小华,是小明,是实实在在的人,是实际的。)
31.如何在类里面统计有多少对象调用这个类的功能?
- 利用类调用时,自动触发__init__的功能来写。
-
class Student: n = 0 def __init__(self, x, y, z): Student.n += 1 # 利用类定义自动调用函数,来统计有几个对象调用了 self.name = x self.age = y self.gender = z def choose(self): pass obj1 = Student("liqi", 18, "male") # Student.n +=1 obj2 = Student("liqi", 28, "male") # Student.n +=1 obj3 = Student("liqi", 38, "male") # Student.n +=1 print(obj1.n) # 3 print(obj2.n) # 3 print(obj3.n) # 3
- 参考资料: