1、面向对象的概念和面向过程的区别和应用场景
面向过程和面向对象是两种最重要的编程范式。(编程范式是解决问题的方式类别,程序设计思想,不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路)
1.1 面向过程
面向过程(Procedural Programming)核心是“过程”,基本设计思路就是把一个大问题逐步分解成很多个小问题或子过程直到问题小到可以用简单的步骤解决,相当于打造一条流水线。
面向过程把复杂的问题简单化,来降低系统的复杂度。
但是,正由于流水线式的程序设计,如果更改程序代码,与之相关的代码块也得随之更改,扩展性比较差。
适用于功能一旦实现就很少改变的场景,写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的。
1.2 面向对象
面向对象(OOP,Object Oriented Programing)编程是利用“类”和“对象”来创建各种模型,计算机程序的执行就是一系列消息在各个对象之间传递。核心和“对象”。
“对象”和“类”可以这么理解,站在上帝的视角去创造世界,或者说像女娲造人一样,设定好一定的标准(类),比如人有五官,四肢,会跑会走会说话等,按照这个标准拿藤条一甩,泥巴落地成一个个的人(一个个的对象)。
面向对象使程序更加容易扩展和易更改,使开发效率变的更高,但编程的复杂度高。应用于需求经常变化的场景,互联网应用,游戏等。
2、相关概念和语法
2.1 类,对象,实例化
类:拥有相同属性的对象的模板。
对象(实例):根据类这个模板创建出来的一个个具体的“对象”。
根据类创建的具体对象的过程就是实例化。
现实世界中,现有对象,根据对象总结出类。男人和女人划为一类:人。人和狗也可以划为一类:动物。人,狗和植物也可以划为一类。
程序设计中,先产生类,然后根据类实例化产生对象。
2.2 语法
2.2.1 类的创建和对象实例化
class Student: # class + 类名,首字母大写
school = '北大' # 属性,特征,所有的对象共有的属性(空一行写函数)称为数据属性
def run(self): # 方法,对象所拥有的技能(空一行写下一个函数,写完空两行)成为函数属性
pass
def learn(self):
pass
def sleep(self):
pass
student1 = Student() # 实例化,就是调用 类名+()
student2 = Student()
print(student1, student2)
<__main__.Student object at 0x00000225E92BA358>
<__main__.Student object at 0x00000225E92BA3C8>
2.2.2 补充
1、类在定义阶段便会执行,因而会产生新的名称空间存放变量名和函数名,可以通过类名+.__dict__查看(字典格式)。
class Student:
school = '北大'
print('类内部代码,如果打印说明类在定义阶段会执行')
# 类内部代码,如果打印说明类在定义阶段会执行
class Student:
school = '北大'
def run(self):
pass
print(Student.__dict__)
结果(字典形式):
{'__module__': '__main__', 'school': '北大', 'run': <function Student.run at 0x00000226E9118BF8>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
2.2.3 类的属性增删改查
之前通过.__dict__查看类的名称空间(字典形式),有数据属性和函数属性。查看属性也可以直接用 类名.属性名 ,类的属性增删改查也和字典增删改查类似。
class Student:
school = '北大'
def run(self):
pass
# 查
print(Student.run)
# <function Student.run at 0x000002871F998BF8>
print(Student.school)
# 北大
# 增
Student.class_name = '二班'
# 改
Student.school = '西南大学'
print(Student.__dict__)
# {'__module__': '__main__', 'school': '西南大学'
# 删
del Student.school
print(Student.school)
# AttributeError: type object 'Student' has no attribute 'school'
2.2.4 __init__方法为对象产生独有属性
“init”前后分别有两个下划线,在对象产生之后,才会执行,只用来对对象进行初始化操作,不能有返回值,
class Student:
school = '北大'
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
pass
s1 = Student('小明', 18)
s2 = Student('小红', 19)
print(s1.name, s2.name)
# 小明 小红
__init__方法是实例化时自动调用,实际上
s1 = Student(‘小明’, 18) 就相当于
先产生了一个空对象,然后类调用init方法赋值。
s1 =Student._init_(s1,‘小明’,18)
所以定义init方法以及其他方法时,会默认加上self ,比如上例代码中
def _init_(self, name, age)
2.2.5 对象的属性
对象属性的增删改查和类是一样的,
对象名.属性名
s1 = Student('小明', 18)
print(s1.__dict__)
# {'name': '小明', 'age': 18}
s1 = Student('小明', 18)
print(s1.name)
# 小明
s1.sex = 'male'
print(s1.__dict__)
# {'name': '小明', 'age': 18, 'sex': 'male'}
s1.name = '小李'
print(s1.__dict__)
# {'name': '小李', 'age': 18, 'sex': 'male'}
del s1.name
print(s1.__dict__)
# {'age': 18, 'sex': 'male'}
2.2.6 补充
1、类的数据属性是所有对象共有的,id都一样
class Student:
school = '北大'
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
pass
s1 = Student('小明', 18)
s2 = Student('小红', 19)
print(id(Student.school))
print(id(s1.school))
print(id(s2.school))
# 1774946602040
# 2289457679416
# 2289457679416
2、类的函数属性是绑定给对象用的(bound method),称为绑定到对象的方法。
绑定到不同的对象就是不同的绑定方法,内存地址不一样。简单理解就是类的数据属性school = 北大,是所有对象共有属性,所有对象都是北大的,但函数属性只是对象共用了这段代码,一个对象调用了函数并不代表其他对象也执行了。
print(Student.run)
print(s1.run)
print(s2.run)
# <function Student.run at 0x000001D1D30A8B70>
# <bound method Student.run of <__main__.Student object at 0x0000017D7E073E10>>
# <bound method Student.run of <__main__.Student object at 0x0000017D7E13A240>>
类似于initial方法,类中定义的函数属性主要给对象用的,看下面这段代码,对象s1调用函数run,其实相当于类调用函数然后将对象作为第一个参数传入。
s1.run() = Student.run(s1)
class Student:
school = '北大'
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
print('%s is running'% self.name)
s1 = Student('小明', 18)
s1.run()
Student.run(s1)
# 小明 is running
# 小明 is running
所以绑定到对象的方法特殊之处在于对象调用时会将自身作为一个参数传入,即自动传值,所以类中定义函数属性,第一个参数默认对象本身,约定俗成写成 self
3、对象的数据属性会先在对象中找,没有的话会去类中找,再没有就会报错,不会从全局中找!!
Student.x = 'Student的x'
s1.x = 's1的x'
print(s1.x)
# s1的x
Student.x = 'Student的x'
print(s1.x)
# Student的x
x = '全局'
class Student:
school = '北大'
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
print('%s is running'% self.name)
s1 = Student('小明', 18)
print(s1.x)
# AttributeError: 'Student' object has no attribute 'x'