面向对象编程
-
两种编程思想
-
面向过程:解决问题的步骤,先干什么后干什么,按照步骤一步一步就解决问题.基于该编程思想就好比是在编写一条流水线,是一种机械式的思维方式.
-
优势:复杂问题流程化,进而简单化
-
劣势:可拓展性差,维护性差. (实现流程是固定的,一旦中间某一个步骤发生变化,将导致整体都需要修改)
-
使用场景:对拓展性要求低的软件,比如系统内核,脚本等. 但是对于拓展性强的的程序就不再适合该思想编程,即产生了面向对象编程.
-
-
面向对象(OOP : object oriented programming ):对象指的是特征和技能的结合体(基于其特征能找到实际物体).基于该思想编写程序就好比在创造一个世界,你就是这个世界的上帝,是一种上帝的思维方式.
-
优势:
-
不用考虑繁琐的实现步骤 , 从一个流水线思维变成了上帝思维
-
可拓展性高(当需要一个新功能时,写一个具备新功能的对象,命令它去完成任务,各个对象出现问题,不会对其他对象产生影响,可维护性高)
-
-
劣势 :
-
编程的复杂度高于面向过程.
-
无法准确预知结果
-
-
应用场景: 需要较高的拓展性时,(直接与用户发生交互的程序例如:微信. qq等).......对于不需要拓展的程序而言,使用面向对象就会增加其复杂度.
-
-
-
为什么要使用面向对象
-
在当前市场情况下,百分之九十以上的得程序都需要直接与用户交互,而用户的需求千变万化,所以对编程的拓展性要求很高,故我们必须要使用面向对象编程.
-
-
类与对象
-
对象: 对象是特征与技能的结合体(基于其特征能找到实际对应对象)
-
类:类是一个抽象的概念,是一系列具有相同某一技能或特征的的结合体.
-
现有对象还是先有类:
-
在现实生活中,一定是先有对象,后来随着人类文明的发展总结的类,对象是具体存在的,而类只是一种抽象的概念
-
在程序中,务必先定义类,后调用类来产生对象.
在程序中特征用变量标识,技能用函数标识
因而类中最常见的无非是:变量和函数的定义
-
-
class Student: # 定义类(类名首字母大写) school = 'Tsinghua' # 相同特征,变量 def learning(): # 相同技能,函数 print('learning') stu1 = Student() # 调用类产生对象 print(obj) # 运行结果 # <__main__.Student object at 0x0000000002648358> # 解释以上结果:模块名为main,其中Student类下有一个指定内存地址为xxx的对象 print(stu.school) # 输出对象的属性(特征) stu.learning() # 输出对象的属性(技能)
注意:1.类中可以有任意python代码,这些代码在定义类的时候便会执行
2.因而会产生新的名称空间,用来存放类的变量名和函数名,可以通过"类名.__ dict__"查看
3.对于经典类来说 ,我们可以通过过字典操作类名称空间的名字,但是python为我们提供了专门的语法.
4.点是访问属性的语法,类中定义的名字,都是类的属性
# 程序中类的用法 # 访问 1,类名.变量名 # 相当于经典操作"类名.__ dict__['变量名'] 2,类名.函数名() # 相当于经典类操作"类名.__ dict__['函数名'] # 增加 类名.变量名 = 变量值 # Student.classes = '计算机一班' # 修改 类名.变量名 = 变量值 # 即如同字典的操作,更改已存在的变量(key=新value) # 删除 del 类名.函数名 # 对象的初始化__init__:该方法是在对象产生后才会执行,只用来为对象进行初始化操作,可以有任意代码,但是一定不能有返回值 class Student: ...... # 函数的初始化(self一定要有,表示要初始化的对象) def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex ...... s1 = Student('jason', 23, 'male') # 相当于先调用类产生空对象s1,然后调用类.__init__(s1,'jason',23,'male') # 对象的操作,类似于类的操作 # 对象名.变量名.......
属性查找与绑定方法
-
属性查找
类有两种属性:数据属性和函数属性
-
类的数据(变量)属性是所有对象共享的
-
类的函数属性是绑定给对象用的(obj,method称为绑定方法,内存地址都不一样)
-
s1 = Student() s2 = Student() print(id(Student.school)) # 通过类名.变量名访问类中数据 print(id(s1.school)) # 通过对象名访问变量 print(id(s2.school)) 输出结果 ''' 4377347328 4377347328 4377347328 4377347328 ''' 得出结论:类的数据是共享的,id都一致 print(id(Student.learning)) # 通过类名.函数名访问类中数据 print(id(s1.learn)) # 通过对象名访问函数 print(id(s2.learn)) 输出结果: ''' <function OldboyStudent.learn at 0x1021329d8> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x1021466d8>> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146710>> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146748>> '''
-
类中属性查找的顺序:obj.name会先从自己的名称空间里找name,找不到则去类中找(类中找不到就去父类中找...最后没找到就会报错).
-
绑定方法
-
绑定方法:就是将对象或者类与函数进行绑定的方法,这里的方法指的也就是函数
对象本质上就是一种存放数据的容器 函数是用于处理数据的代码 绑定方法就是将数据与处理数据的函数绑定在一起
-
为什么要进行绑定:当没有进行绑定时
-
每次传递参数,必须手动传递,很有可能传参顺序而发生错误
-
每次处理数据 都需要手动传参数
-
当要处理的数据特别的多 就不能再定义为变量了 你可以使用列表出来存储要处理的数据但是 每次处理 都需要先获取数据 在传递给处理数据的函数 所以,绑定过后 可以简化代码,提高效率
class Student: school = "BeiJing" def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age def learning(self): print("正在学习..") def sayHI(self): print("hello my name is %s my age:%s my sex:%s" % (self.name,self.age,self.sex)) # 默认情况下 在类中定义的函数都是绑定方法,共同点是,都会将对象作为第一个参数self stu1 = Student("一个学生","man",18) stu1.sayHI() # 当用用对象来调用类中的方法时,默认把对象传入方法中 Student.sayHI(stu1) # 而用类名来调用时,则需要手动传入对象
-
强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法init也是一样的道理)
-
绑定给类的方法
-
绑定的方法包括两种,常用的是绑定给对象的,另一种是绑定给类的
class Student: school = "Tsinghua" def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex # 绑定给类的方法 使用一个装饰器叫classmethod,必须有一个参数,表示当前类,参数名也可以自己定义,建议不要修改 @classmethod def print_school(cls): # 输出类里面叫school的属性 print(cls.school) # def print_school2(self): # 输出类里面叫school的属性 # print(self.school) # 这是绑定给对象的方法 def sayHello(self): print(self.name, " 说: 你好") # Student.print_school_name() Student.print_school()
-
一个方法到底应该绑定给对象还是帮对给类? 当要处理的数据包含在类中时,就应该绑定给类 当要处理的数据包含在对象中时,就应该绑定给对象
-
绑定给对象和绑定给类的差别
-
对象绑定方法 可以使用对象来调用 也可以使用类名来调用 在对象调用时会自动传入对象自己
-
类调用时不会自动传参
类的绑定方法,对象和类都能调用,并且都会自动传入这个类
-
-
-
非绑定方法(了解)
class Teacher: def __init__(self,name,sex): self.name = name self.sex = sex # @staticmethod 用于定义个非绑定方法 @staticmethod def test_func(num): print("test_func run!") print(num) Teacher.test_func(1) t1 = Teacher("矮根","男") t1.test_func(100) print(t1.test_func) # 什么是非绑定方法 再类中 即不绑定给类 也不绑定给对象 # 特点:没有自动传参数的效果 ,类和对象向都能调用,就是一个普通函数 # 当你的这个功能不需要访问类的数据 也不需要访问对象的数据,就可以作为一个非绑定方法 # 使用场景较少