面向过程与面向对象
面向过程的程序设计
过程是核心,将复杂的变成流程化,处理起来比较简单。
优点:将复杂的变成流程化,处理起来比较简单。
缺点:扩展性差,修改起来非常困难
应用场景: 一旦完成就很少改变的场景,例如 linux内核,git, 以及Apache HTTP Sever等。
面向对象的程序设计
对象是核心,对象是特征和技能的结合体,基于面向对象设计程序就好比在创造一个世界,你就是上帝,存在的一切皆为对象,不存在的也可以创造,与面向过程相比更加注重对现实世界的模拟,是一种“上帝式”的思维方式。
优点:可扩展性强
当然,一个程序的质量不仅仅是可扩展性,面向对象只是用来解决可扩展性。
缺点:
1.处理问题比较复杂,不了解面向对象而立即上手基于他设计程序,极容易出现过度设计的问题,对于一些扩展性要求较低的场景使用会增加编程难度。
2.面向对象程序一旦开始就由对象之间的交互解决问题,无法预测问题处理的流程与结果,应用场景:需要经常变化的软件,一般集中在用户层,互联网应用,企业内部软件,游戏等
类与对象
类与对象的概念
类 即类别,种类是面向随想设计的最重要的概念,对象是特征和技能的结合体,类则是一系列对象相似的特征与技能的结合体。
那么到底是现有对象在有类还是现有类才有的对象?
在现实生活中肯定是现有的各种各样实际存在的对象,然后人们根据站在不同的角度总结出了不同的类,如人类,动物类,植物类,也就是说,对象是真是存在的,而类只是一个概念,并不存在。
在程序中,先定义类,然后生成对象,与函数一样,都要先定义再调用,不同的是,调用函数返回的是函数执行的结果,调用类返回的是对象。
定义类:
在程序中,务必保证:先定义(类),后使用(产生对象)
在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是”类“,对象则是这一类事物中具体的一个。
class Student: # 定义一个学生类 school = "luffy_city" # 这里定义一个学生的属性,他们的学校都是luffy_city def __init__(self, name, sex, age): # __init__ 方法可以定义一些属性相同但值不相同的属性 self.name = name self.sex = sex self.age = age def learn(self): # 定义一个学习的技能 return "%s is learnning" % self.name def eat(self): # 定义一个吃饭的技能 return"%s is eatting" % self.name def sleep(self): # 定义一个睡觉的技能 return "%s is sleeping" % self.name print(Student.__dict__) # 可以通过 类名.__dict__拿到类中所有属性 print(Student.school) # 通过 类名.属性名 查看属性
实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征。
实例化的过程就是通过类产生对象的过程,在这个过程中,产生了一个具有具体的名字,性别,年龄和技能的对象。
语法:对象名 = 类名(参数)
student1 = Student("李二蛋", "man", 25) # 类名()相当于调用__init__方法,会自动将对象名当作第一个参数传给self ,相当于Student.__init__("student1","李二蛋", "man", 25)
查看属性和调用方法:
print(student1.name)
print(student1.learn()) # 会自动将对象名当作参数传给self,相当于Student.learn("student1")
类属性的补充:
一、我们定义的类到底保存在哪里了?查看方式dir(类名):查出的是一个名字列表类名.__dict__:查出的是一个字典,key为属性名,value为属性值
二、特殊的类属性类名.__name__ 类的名字(字符串)类名.__doc__ 类的文档字符串类名.__base__ 类的第一个父类类名.__bases__ 类的所有父类类名.__dict__ 类的字典属性类名.__module__类定义所在的模块类名.__class__ 实例对应类
类属性的操作
Student.school #查 Student.school='Oldboy' #改 Student.x=1 #增 del Student.x #删
对象属性的操作
# 调用类,或称为实例化,得到程序中的对象,执行类中的__init__方法,也会产生对象的名称空间可以用student_1.__dict__查看,查看结果为{'name': '李二蛋', 'sex': 'man', 'age': 25}
student_1.name #查,等同于student_1.__dict__['name'] student_1.name='王三炮' #改,等同于student_1.__dict__['name']='王三炮' student_1.course='python' #增,等同于student_1.__dict__['course']='python' del student_1.course #删,等同于student_1.__dict__.pop('course')
属性查找及绑定方法
属性查找
类有两种属性:数据属性和函数属性
1、类的数据属性是所有对象共享的
#类的数据属性是所有对象共享的,id都一样 print(id(student_1.school)) # 1531561867504 print(id(student_2.school)) # 1531561867504 print(id(student_3.school)) # 1531561867504
2、类的函数数据是绑定给对象用的,称为绑定到对象的方法
#类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样 print(Student.learn) # <function Student.learn at 0x00000164983D9730> print(student_1.learn) # <bound method Student.learn of <__main__.Student object at 0x00000164983D6F28>> print(student_2.learn) # <bound method Student.learn of <__main__.Student object at 0x00000164983D6F60>> print(student_3.learn) # <bound method Student.learn of <__main__.Student object at 0x00000164983D6F98>>
绑定方法
类中定义的函数(没有被任何装饰器装饰的)是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数需要传几个参数,其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法。
强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)
print(Student.learn(student_1)) # 李二蛋 is learnning print(student_1.learn()) # 李二蛋 is learnning
注意:绑定到对象的方法的这种自动传值的特征,决定了在类中定义的函数都要默认写一个参数self,self可以是任意名字,但是约定俗成地写出self。
类即类型
python中一切皆为对象,且python3中类与类型是一个概念,类型就是类
#类型dict就是类dict >>> list <class 'list'> #实例化的到3个对象l1,l2,l3 >>> l1=list() >>> l2=list() >>> l3=list() #三个对象都有绑定方法append,是相同的功能,但内存地址不同 >>> l1.append <built-in method append of list object at 0x10b482b48> >>> l2.append <built-in method append of list object at 0x10b482b88> >>> l3.append <built-in method append of list object at 0x10b482bc8> #操作绑定方法l1.append(3),就是在往l1添加3,绝对不会将3添加到l2或l3 >>> l1.append(3) >>> l1 [3] >>> l2 [] >>> l3 [] #调用类list.append(l3,111)等同于l3.append(111) >>> list.append(l3,111) #l3.append(111) >>> l3 [111]
小练习:实现对象之间的交互
class Hero: # 定义一个英雄的类 role = "hero" # 定义一个公同属性角色 def __init__(self, life_value, aggressivity, defensive): # 定义一个自定义值的属性函数 属性包括生命值,攻击力,防御 self.life_value = life_value self.aggressivity = aggressivity self.defensive = defensive def attack(self, target): target.life_value -= (self.aggressivity - target.defensive) # 定义一个攻击技能 garen = Hero(100, 60, 30) # 实例化一个盖伦对象,并传入英雄的生命值,攻击,防御 rivan = Hero(90, 70, 20) # 实例化一个锐雯对象,并传入英雄的生命值,攻击力,防御 garen.attack(rivan) # 盖伦攻击瑞文一次 rivan.attack(garen) # 瑞文攻击盖伦一次 print(garen.life_value) # 打印盖伦的生命值 60 print(rivan.life_value) # 打印瑞文的生命值 50