人生三问
什么是面向对象的程序设计?
提面向对象编程肯定会说到面向过程编程.
面向过程:核心是过程,即先干什么再干什么,流水线\机械式的思维方式
- 优点:复杂的问题流程化,进而简单化
- 缺点:牵一发而动全身,可扩展性差
面向对象的程序设计:核心是对象,
对象在现实世界中是实实在在存在的,是具备特征与(行为)技能的集合体,如果能够准确找到这个事物,那它就是一个对象
面向对象编程:我们关注的是,使用什么样的对象可以完成我的任务
例如: 那大象装进冰箱,不在思考要先干什么后干什么,而是创造一个对象,让他去完成把大象装进冰箱的任务
- 优点:
- 1.对于程序员来说,不需要再关心具体步骤
- 2.扩展性,一个单独的个体的特征或行为发生变化时, 不会影响到其他人
- 缺点:
- 1.程序的复杂度变高,你得需要设计这个对象,注意要避免过度设计的问题,一些扩展性要求低的场景使用面向对象会特征编程难度
- 2.程序得执行结果可控性低,上帝也无法准确的预测最终结果
为什么要用面向对象的程序设计?
应用场景: 现在的软件大多数都是在不断更新的, 就会出现需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等,这些都是面向对象的程序设计大显身手的好地方
面向对象的程序设计并不是全部.对于一个软件质量来说,面向对象的程序设计知识用来解决扩展性的
怎么用面向对象来做程序设计?
类的使用
-
类
类就是分类 类型的意思
定义:一堆具备相同特征和行为的事物的抽象概念,不实际存在先有类还是先有对象:
- 生活中:
生活中类,是通过对象的特征和行为抽取而来,
先有对象才有类 - 编程中:
必须先有类,才能有对象,因为必须先告诉程序,你的对象有什么样的特征和行为(技能)
类的作用: 用于描述该类的对象具备什么样的特征和行为(技能)
- 生活中:
# 定义一个类
# class关键字 类名
# 类名规范 大写开头 驼峰命名法
class OldBoyStudent:
# 描述该类对象的特征
school = 'OldBoy'
place = 'ShangHai'
# 在定义阶段
''' 只要包含该类的py别执行 就会做两件事
1.就会创建类的名称空间
2.执行代码 将产生的名称放入名称空间'''
# 描述该类对象的行为 通过函数
def say_hi(self): #自动生成一个参数self
print('hello oldboy')
# 使用类中的属性
print(OldBoyStudent.__dict__) # 所有属性在一个字典中
print(OldBoyStudent.__dict__['place']) # 访问单个属性
print(OldBoyStudent.place) #和上面的一样访问单个属性
# 使用类中的函数
OldboyStudent.__dict__["say_hi"](10)
OldboyStudent.say_hi(10) # 和正常函数一样要传参
对象的使用
# 先定义后调用,所以我们先定义一个类
class OldboyStudent:
# 如果每个对象的这个属性都相同 才应该定义到类中
# 比如所有人的学校都是上海oldboy
school = '上海Oldboy'
# 创建对象
# 语法: 在类名后加括号 与调用函数写法相同
stu = OldboyStudent()
# 访问对象的属性
print(stu.school)
print(OldboyStudent.school)
# 修改属性的值
stu.school = '北京Oldboy'
print(stu.school)
print(OldboyStudent.school)
# 增加属性
stu.room_num = '1008'
print(stu.room_num)
print(OldboyStudent.room_num)
# 删除属性
del stu.room_num
print(stu.room_num)
print(OldboyStudent.room_num)
'''
从上面的代码结果我们会发现类里的对象的属性和类直接调的属性不一样
对象 与类的名称空间是独立的
'''
stu.school = '深圳oldboy' #为对象的属性赋予新的值
print(OldboyStudent.school) #类中的属性不会变化
stu.room_num = '1008' # 为对象增加属性
print(OldboyStudent.room_num) # 类中也不会出现新的属性
print(stu.__dict__)
print(OldboyStudent.__dict__)
# 所以 如果对象的属性是相同的 就放到类中 作为一个公共的数据
# 比如大家都在上海校区 OldboyStudent.school = '上海Oldboy'
stu2 = OldboyStudent()
print(stu2.__dict__) # stu2是空的
print(stu2.school) # 得访问到'上海Oldboy'
stu2.school = '北京Oldboy'
print(stu2.school) # 得到'北京Oldboy'
# 对象的属性查找顺序
# 对象自己的名称空间 -> 类的名称空间
stu1 = OldboyStudent()
stu1.school = 'newSchool'
print(stu1.school) #得到'newSchool'
print(stu1)
__init__函数的用法
# 定义一个类
class Dog:
# 作为一只现代文明狗 应该有 昵称name 年龄age 毛色color 性别gender
# 但是每个狗都不一样,不能写到类里
# 我们需要这样写,但是太low了 狗多了怎么办
dog1 = Dog()
dog1.name = "二黄"
dog1.age = "2"
dog1.color = "黄色"
dog1.gender = "female"
# 这个时候就用到__init__
# __init__称之为初始化函数 它会在创建对象的时候自动执行
# 创建对象是
# 1.创建一个空对象
# 2.执行一个空对象
# __init__函数的作用,就是为对象的属性赋初始值
def __init__(self,name,color,age,gender)
# __init__函数的几个参数,self对象本身(不用传),name昵称,color毛色,age年龄,gender性别
print('dog__init__执行了')
print(self)
self.name = name
self.age = age
self.color = color
self.gender = gender
# 可以先创建一个对象
dog_erhuang = Dog()
# 再调用__init__函数
dog_erhuang.__init__('二黄','黄色',2,'female')
# 也可以在创建对象时,直接传入参数(肯定用这个啊,一样清楚还少行代码呢)
dog_erhuang = Dog('二黄','黄色',2,'female')
dog_erha = Dog('二哈','白色',2,'female')
print(dog_erhuang)
print(dog_erha)
'''总结:
1.使用场景:需要为每个对象定制不用的属性值
2.__init__在创建对象后自动执行
3.第一个self参数 指的是这个对象本身 不需要手动传值
'''
上面讲解有两处好像不太一样,可能会有一些疑问,我们在使用类中的函数时,需要我们传参,现在我们使用__init__函数时却不需要传参,我们现在来说一下
绑定方式
# 同样先来定义一个类叫 人
class Person:
species = 'human' # 定义一个公共属性 人类
# 给每个对象定制不同的属性值 用初始化函数__init__
# 名字,年龄,性别,种族
def __init__(self,name,age,gender,race):
self.name = name
self.age = age
self.gender = gender
self.race = race
# 加一些行为
def sleep(self):
print('%s 睡觉' %egon.name)
def eat(self):
print('eating')
# 创建对象
egon = Person('矮根',18,'female','black')
alex = Person('艾利克斯',18,'female','The_yellow_race')
# 尝试一下在用类调用类中函数 与 对象调用的区别
egon.sleep()
alex.sleep()
print(Person.sleep)
print(egon.sleep)
# 类调用
Person.sleep(egon)
'''
总结: 类调用与对象调用的区别
对于类而言 sleep就是一个普通函数 self参数需要传值
对于对象而言 sleep是一个绑定关系 self参数会自动把对象本身传入
'''
迟到的人生三问:
- 绑定方法是什么:
是对象与类中的某个函数的绑定关系,比如我们吃饭,我吃饭你不会饱
所以吃饭这个函数对我这个对象就是绑定方法,知道是我吃的,不是你吃的 - 为什么要把函数进行绑定?
因为对象的行为,通常都需要访问这个对象的数据 或是修改这个对象的数据
如果没有对象 直接调用函数是没有意义的 在函数中访问不到对象的数据
所以需要将对象和函数进行绑定 - 特殊之处
在使用绑定方法时,不需要关系self参数 会自动将这个对象本身传入
对象调用绑定方法时 最后执行的还是类中的那个函数