理解面向对象编程(OOP Object Oriented Programming)

理解面向对象编程(OOP: Object Oriented Programming) 面向过程与面向对象 什么是面向过程编程? 答:按照先干什么、再干什么、最

理解面向对象编程(OOP: Object Oriented Programming)

面向过程与面向对象

什么是面向过程编程?

答:按照先干什么、再干什么、最后干什么的思路。事情都自己干,流水线,程序员是打工仔视角

​ 优点:使复杂的问题简单化、流程化

​ 缺点:可扩展性差

什么是面向对象编程?

答:在面向对象编程中,程序员就好像是在创造一个世界,在这个世界中,程序员创造了一个个对象,用来帮自己解决问题。事情都交给对象干,程序员是老板视角。

​ 优点:可扩展性强

​ 缺点:复杂度略到与面向过程

对象和类的概念

对象:

  • 特征(变量)与技能(函数)的结合体。
  • 对象是具体的存在的事物

类:

  • 一系列对象的相同特征(变量)与技能(函数。)的结合体
  • 类是抽象的概念

在现实世界中:是先有具体的对象,然后将这些具有相同特征和技能的对象归结为一个类。比如:是先有人这个对象,然后把所有人归结为人类这个抽象的概念。

在程序中:是先定义一个类,然后由这个类,实例化为一个个对象。

在一个类中,最常定义的是变量和函数。重点:类体代码会在定义阶段就执行,然后产生一个类名称空间,将类体代码中产生的名称,丢进类名称空间中。

类里的函数里面的代码体只有调用的时候才执行,但是,类里面的__init__函数会在定义的时候就执行。

#查看类名称空间里面的名称:__dict__
class Student:
		school = '社会大学'
    def __init__(self, name):
      	self.name = name
        
    def study(self):
      	print('我是学生,我会学习')
 
print(Student.__dict__) 
'''
结果:{'__module__': '__main__', 'school': '中北大学', '__init__': <function Student.__init__ at 0x108e685f0>, 'study': <function Student.study at 0x108e684d0>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

school、study、__init__: 类定义时产生的名称
__module__:当前文件的模块,因为是执行文件,所以是__main__
__doc__:类的文档注释
'''

print(Student.school)  #结果:社会大学  #相当于:print(Student.__dict__['school'])
print(Student.study)  
#结果: <function Student.study at 0x1013244d0>  #相当于:print(Student.__dict__['study'])
Student.school = '北京大学'  # 相当于Student.__dict__['school'] = '北京大学'

(****)类本质就是一个名称空间,里面存放变量和函数的名字,是一个存放变量和函数的容器

类的用途之一:从名称空间中找名字

类的用途之二:生对象

类中定义的变量是所有对象共享的,如果类改变了该变量,所有对象.这个变量的时候都会改变。对象是不能改变类的变量的,对象.一个类变量,并没有改变类的这个变量,本质上是在自己对象的命名空间中添加了一个属性。

class Student:
  	age = 18
  	def __init__(self):
      	pass
      
stu1 = Student()
stu2 = Student()
print(stu1.age) # 18
print(stu2.age) # 18
Student.age = 10
print(stu1.age) # 10
print(stu2.age) # 10

stu1.age = 20
print(stu1.age)  # 20
print(stu2.age)  # 10
print(stu1.__dict__)  # {'age': 20} 

对象

调用类可以产生对象。

调用类之后的返回值称为一个对象/实例。

调用类的过程称为类的实例化。

对象的本质也是一个命名空间。如果类的init没有参数,对象的命名空间为空。

例1:
class Student:
		def __init__(self):
      	print(1)
        
stu = Student()
print(stu.__dict__)  #结果:{}

例2:
class Student:
  	def __init__(self, name):
      	self.name = name
        
 stu = Student('你爹')
print(stu.__dict__)  #结果:{'name':'你爹'}

重点:调用类发生了什么?

1、生成一个空对象返回

2、触发类中init函数的执行,将这个空对象传给init的第一个参数。调用类括号内的参数再一次传给init第一个参数后面的参数。

init补充:1、init函数在类调用的时候就执行了。2、init函数不能有返回值。

属性查找顺序

对象.属性,.后面的叫做属性

对象.属性的时候,现在对象的命名空间里面找有没有这个属性,如果没有,就从类的名称空间里面找属性。

class Student:
    school = '中北大学'
    age = 18
    def __init__(self, name):
        self.name = name

    def study(self):
        print(1)

stu = Student('你爹')
print(stu.name)  
print(stu.age)
'''
说明:stu的命名空间只有name, stu.__dict__ = {'name':'你爹'}, 没有age,这时候就在类的名称空间中找。
类名称空间在类定义的时候有:school, age, __init__, study等,有age,则返回18
'''

绑定方法: 当函数的逻辑中需要访问对象时,那就绑定给对象,仅需要类中数据就绑定给类

1、类中定义的变量类可以用,对象也可以用。不管谁调用,都指向同一个地址。类变量值一旦改变,所有对象调用时都跟着变。

class Student:
    age = 18
    def __init__(self):
        pass
stu = Student()
print(id(stu.age))  # 4362244432
print(id(Student.age)) # 4362244432

Student.age = 20
stu1 = Student()
print(stu.age)  # 20
print(stu1.age) # 20

2、类中定义的函数,类也可以用,类调用的时候,这个函数就是一个普通的函数。类中定义的函数是用来给对象用的。而且是绑定给对象用的。

什么叫绑定给对象?

class Student:
    school = 'oldboy'

    def __init__(self, name, age, sex):
        self.name = name #stu1.name='小白'
        self.age = age   #stu1.age=18
        self.sex = sex   #stu1.sex='male'

    def choose_course(self,x): #self=stu1
        print('%s choosing course' %self.name)
        
stu1=Student('小白',18,'male')  # 小白 choosing course
stu2=Student('小花',38,'female') # 小花 choosing course
stu3=Student('小黑',28,'male') # 小黑 choosing course
'''
如上,用类实例化了三个对象,三个对象分别调用类里面的函数。调用时,会自动把对象传给类函数的第一个参数。
也就是说,类方法分别绑定给了不同的对象,哪个对象调用,用到的就是哪个对象的名称空间。不同对象互不干扰。
'''