一、面向对象编程:
1、面向过程编程
核心是”过程“二字,过程指的是解决问题的步骤,即先干什么再干什么
基于该思想编写程序就好比在编写一条流水线,是一种机械式的思维方式
优点:复杂的问题流程化、进而简单化
缺点:可扩展性差
2、面向对象编程
核心”对象“二字,对象指的是特征与技能/行为的结合体
基于该思想编写程序就好比在创造一个世界,你就是这个世界的上帝,是一种
上帝式的思维方式
例如:一个老板想要开公司,公司的每个事情老板不会按照面向过程一样的去解决,比如发工资和计算公司财务报表,这个时候就可以找一个有财务技能的人员来专门做这个事情,这个财务就是一个有特征和技能的对象.老板和财务就相当于是指挥者和执行者
优点:可扩展性强
缺点:编程的复杂度高于面向过程
二、类与对象
类与对象:
对象是特征和技能的结合体,那类就是一系列对象相同的特征和技能的结合体
在现实生活中,一定是先有对象,后来随着人类文明的发展总结出来的类,对象是具体存在的,而类只是一种抽象的概念
在程序中,一定要记得:先定义类,后调用类来产生对象.
现实生活中的类:(一系列相同特征和技能的结合体)
现实生活中的对象:
对象1:
特征:
school="Oldboy"
name="马冬梅"
age=18
sex="female"
技能:
学习
选课
对象2:
特征:
school="Oldboy"
name="甜蜜蜜"
age=21
sex="male"
技能:
学习
选课
对象3:
特征:
school="Oldboy"
name="原石开"
age=22
sex="male"
技能:
学习
选课
现实生活中的老男孩学生类:
相同的特征
school="Oldboy"
相同的技能
学习
选课
程序中的类:在程序中必须先定义类>>调用类>>产生对象
定义一个类:
语法:class关键字 + 类名
类名规范:大写开头,驼峰体命名法
class OldBoyStudent:
描述该类对象的特征(在类中使用变量来表示对象的特征)
school= 'OldBoy'
name = 'allen'
age = 18
sex = 'male'
描述该类对象的技能/行为 (通过函数来实现)
def learn(self):
print('is learning')
注意:在定义阶段,就会执行类中的函数体代码,然后将产生的名字存放在名称空间中
程序中类的增删改查:
使用类中的属性(查):
print(OldBoyStudent.__dict__) 查看类的名称空间中有哪些名称(为一个字典类型)
print(OldBoyStudent.__dict__['name']) 是字典就可以按照字典的取值方式进行取值
print(OldBoyStudent.name) 可以直接使用点语法来使用类中的属性
使用类中的函数(查):
print(OldBoyStudent.__dict__['learn']) 通过字典形式的方法来使用类中的函数
print(OldBoyStudent.learn) 可以直接使用点语法来调用类中的函数
增加类中的公共特征(增/改):
OldboyStudent.country='China' (增)
OldboyStudent.name='eric' (改)
删除类中公共特征(删)
del OldboyStudent.country='China' (删)
调用类(创建对象)时发生哪些事情:
1.首先会产生一个空的对象
2.然后会触发类内部的__init__函数
3.然后将空对象连同调用类时括号内的参数组成(不仅仅是self一个参数),将这四个参数一起传给__init__函数
使用类直接调用类中的函数和使用对象调用普通函数时的区别:
使用类直接调用类中的函数时,与调用普通函数没有任何区别,self仅仅是一个位置参数,这个时候即使没有传入self的值也不会进行报错
使用对象调用类中的函数时,必须传入类中的函数所需要的参数,其中对象自动传输给self参数
3、创建对象
使用下面创建的类进行对象的创建:
class OldboyStudent:
# 用变量表示特征
school="Oldboy"
# 用函数表示技能
def learn(self):
print('is learning...')
def choose(self):
print('choose course...')
stu1=OldboyStudent()
stu1=OldboyStudent()
stu1=OldboyStudent()
这样创建出来的对象都是一样的,我们需要创建的对象虽然有相同的公共特征和技能,但是每个对象之间又有不同的地方,所以这样创建出来的对象显然不是我们所需要,这个时候我们就需要创建出一个既有相同的特征和技能同时又具有可分辨的特征的对象,这个时候就需要在定义类的时候很重要的一个定义,就是在定义类的时候定义__init__函数来实现我们定义不同的类:
4、__init__的作用
class OldboyStudent:
# 用变量表示特征
school="Oldboy"
# stu1, "马冬梅", 18, 'female'
def __init__(self,name,age,sex): #self=stu1 name= "马冬梅" age=18 sex="female"
# print('==========init run=============>')
self.name=name # stu1.name = "马冬梅"
self.age=age # stu1.age = 18
self.sex=sex # stu1.sex = "female"
# 用函数表示技能
def learn(self):
print('is learning...',self)
def choose(self):
print('choose course...')
我们定义好__init__之后,之前已经介绍过,在定义类的时候会执行类下面的代码,同时在调用类创建对象的时候会触发__init__函数,这样在使用定义好__init__的类的时候,就需要对其中的参数进行传值,这样就可以定义出我们所需要的具有辨识度的对象了.
stu1=OldboyStudent()
stu1.name='马冬梅'
stu1.age=18
stu1.sex="female"
stu2=OldboyStudent()
stu2.name='甜蜜蜜'
stu2.age=21
stu2.sex="male"
上面两个是分开传值创建的对象,其实可以直接这样写,直接将需要的参数值传进去,创建出我们需要的对象:
stu1=OldboyStudent("马冬梅",18,'female') #OldboyStudent.__init__(stu1,"马冬梅",18,'female')
stu2=OldboyStudent("甜蜜蜜",21,'male') #OldboyStudent.__init__(stu2,"甜蜜蜜",21,'male')
创建好对象之后就可以对创建好的对象进行特征和技能的查看了:
对象特征的查看:
print(stu1.name,stu1.age,stu1.sex)
print(stu2.name,stu2.age,stu2.sex)
5、对象的使用
school='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
class OldboyStudent:
school='oldboy'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
#self=stu1
def learn(self):
print('%s is learning' %self.name)
def choose(self,course):
print('%s is choosing %s' %(self.name,course))
调用类---》产生类的对象,该对象也可以称为类的一个实例,调用类的过程也称为类的实例化
实例化做了三件事情:(调用类的过程也称为类的实例化,实例化的结果是一个对象或者称为一个实例)
1.先产生一个空对象
2.自动触发类内部的__init__函数的执行
3.将空对象,以及调用类括号传入的参数一同传给__init__为对顶定制独有的属性
stu1=OldboyStudent('李三胖',18,'male') #OldboyStudent.__init__(stu1,'李三胖',18,'male')
OldboyStudent.country='CHINA' 添加公共特征
print(OldboyStudent.country)
stu2=OldboyStudent('王大炮',28,'male')
print(stu2.__dict__)
类内部定义的变量(数据属性)是给所有对象共享,所有对象指向的都是同一个内存地址
print(id(stu1.school)) 2468206248208
print(id(stu2.school)) 2468206248208
print(id(OldboyStudent.school)) 2468206248208
类内部定义的函数,类可以使用,但使用类来调用的时候就是一个普通函数,普通函数有几个参就传几个参数
print(OldboyStudent.learn)
OldboyStudent.learn(123) 传入一个123给参数self
类内部定义的函数,其实是给对象使用的,而且是绑定给对象用,绑定给不同的对象就是不同的绑定方法,内存地址都不一样,但其实都是同一个功能(因为都是类中的同一个函数)
绑定方法的特殊之处:
1.绑定给谁就应该由谁来调用
2.谁来调用就会把谁当做第一个参数传入对应函数的self
print(stu1.learn) <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x000002164E9ED358>>
print(stu2.learn) <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x000002164E9ED390>>
绑定方法的特殊之处在于,谁来调用,就会将谁当作第一个参数自动传入当做self的值
stu1.learn() # OldboyStudent.learn(stu1) 将对象stu1传给learn的self
stu2.learn() # OldboyStudent.learn(stu2) 将对象stu2传给learn的self
stu1.choose('python')
stu2.choose('linux')
6、对象属性的查找顺序:先找对象自己的名称空间>>>类的名称空间
注意:不能找到在类外面定义的名称
class People:
x=1
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def run(self): #self=obj
print('%s is running' %self.name) #obj.name
obj=People('egon',18,'male') #People.__init__(obj,'egon',18,'male')
obj1=People('egon1',18,'male') #People.__init__(obj,'egon',18,'male')
obj2=People('egon2',18,'male') #People.__init__(obj,'egon',18,'male')
对象自己的名称空间包括:对象的name、age、sex
在上述例子中:print(obj.__dict__) 结果: {'name': 'egon', 'age': 18, 'sex': 'male'}
当在对象自己的名称空间中找不到相应的名称时,会到类的名称空间去找:print(obj.x) x=1
如果这里类的名称空间中没有x,但是类外面定义了x =100, 这时使用print(obj.x) 结果:'People' object has no attribute 'x'
7、一切皆对象
在python3中统一了类与类型的概念,类即类型
l1=[1,2,3] #l1=list([1,2,3])
print(type(l1)) :<class 'list'> 直接显示的就是class为list 列表的对应功能比如:l1.append(4) append可以看做是list类中的一个技能函数也可以表示为 list.append(l1,4)