面向过程 VS 面向对象
面向过程
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
举例说明
我们以一个例子来说明面向过程和面向对象在程序流程上的不同之处。
假设我们要处理学生的成绩表,为了表示一个学生的成绩,面向过程的程序可以用一个dict表示:
std1 = { 'name': 'Michael', 'score': 98 } std2 = { 'name': 'Bob', 'score': 81 }
而处理学生成绩可以通过函数实现,比如打印学生的成绩:
def print_score(std): print('%s: %s' % (std['name'], std['score']))
如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,而是Student
这种数据类型应该被视为一个对象,这个对象拥有name
和score
这两个属性(Property)。如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,然后,给对象发一个print_score
消息,让对象自己把自己的数据打印出来。
class Student(object): def __init__(self, name, score): self.name = name self.score = score def print_score(self): print('%s: %s' % (self.name, self.score))
给对象发消息实际上就是调用对象对应的关联函数,我们称之为对象的方法(Method)。面向对象的程序写出来就像这样:
bart = Student('Bart Simpson', 59) lisa = Student('Lisa Simpson', 87) bart.print_score() lisa.print_score()
面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,Bart Simpson和Lisa Simpson是两个具体的Student。
所以,面向对象的设计思想是抽象出Class,根据Class创建Instance。
面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。
实例来自于这里
初识类和对象
无形中使用的类
python中一切皆为对象,类型的本质就是类,所以,不管你信不信,你已经使用了很长时间的类了
>>> dict #类型dict就是类dict <class 'dict'> >>> d=dict(name='eva') #实例化 >>> d.pop('name') #向d发一条消息,执行d的方法pop 'eva'
从上面的例子来看,字典就是一类数据结构,我一说字典你就知道是那个用{}表示,里面由k-v键值对的东西,它还具有一些增删改查的方法。但是我一说字典你能知道字典里具体存了哪些内容么?不能,所以我们说对于一个类来说,它具有相同的特征属性和方法。
而具体的{'name':'eva'}这个字典,它是一个字典,可以使用字典的所有方法,并且里面有了具体的值,它就是字典的一个对象。对象就是已经实实在在存在的某一个具体的个体。
在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象是则是这一类事物中具体的一个。
类的相关知识
初识类
def functionName(args): '函数文档字符串' 函数体
#声明一个类 ''' class 类名: '类的文档字符串' 类体 ''' #我们创建一个类 class Data: pass
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法,也叫动态属性 print("person is walking...")
类有两种作用:属性引用和实例化
属性引用(类名.属性)
class Person: #定义一个人类 role = 'person' #人的角色属性都是人 def walk(self): #人都可以走路,也就是有一个走路方法 print("person is walking...") print(Person.role) #查看人的role属性 print(Person.walk) #引用人的走路方法,注意,这里不是在调用
实例化
实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
class Person: # 定义一个人类 role = 'person' # 人的角色属性都是人 def __init__(self, name): self.name = name # 每一个角色都有自己的昵称; def walk(self): # 人都可以走路,也就是有一个走路方法 print("person is walking...") #实例化的过程就是类——>对象的过程 #语法:对象名 = 类名(参数) li = Person('libai')#实例化,类名()就等于在执行Person.__init__() #执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。 li.walk()#调用方法 print(li.name)#查看属性 直接,对象名.属性名
关于self
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做。
因为你的改动别人可能不认识
类属性的补充
一:我们定义的类的属性到底存到哪里了?有两种方式查看 dir(类名):查出的是一个名字列表 类名.__dict__:查出的是一个字典,key为属性名,value为属性值 二:特殊的类属性 类名.__name__# 类的名字(字符串) 类名.__doc__# 类的文档字符串 类名.__base__# 类的第一个父类 类名.__bases__# 类所有父类构成的元组 类名.__dict__# 类的字典属性 类名.__module__# 类定义所在的模块 类名.__class__# 实例对应的类(仅新式类中)
对象的相关知识
对象是关于类而实际存在的一个例子,即实例
对象/实例只有一种作用:属性引用
当然了,你也可以引用一个方法,因为方法也是一个属性,只不过是一个类似函数的属性,我们也管它叫动态属性。
引用动态属性并不是执行这个方法,要想调用方法和调用函数是一样的,都需要在后面加上括号
class Info: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def climb(self): return ('Info:name:{},age:{} years old,{},hobby:climb moutain'.format(self.name,self.age,self.sex)) def drive(self): return ('Info:name:{},age:{} years old,{},hobby:drive the car'.format(self.name,self.age,self.sex)) def favor(self): return ('Info:name:{},age:{} years old,{},hobby:listen to music'.format(self.name,self.age,self.sex)) no1 = Info('miky','10','male') print(no1.climb()) no2 = Info('lily','12','female') print(no2.favor()) no3 = Info('rick','28','male') print(no3.drive())
对象之间的交互
人与小狗的例子
class Dog: def __init__(self,name,aggr,hp): self.dog_name = name#小狗的名字 self.dog_aggr = aggr#小狗的攻击力 self.dog_hp = hp#小狗的生命值 def bite(self,person): person.role_hp -= dog.dog_aggr#小狗咬人,人的生命值根据小狗攻击力下降 print('{0}被{1}咬了一口,{0}剩余血量:{2}'.format(person.role_name,self.dog_name,person.role_hp)) dog = Dog('poppy',2,50)#实例化一只小狗dog class Person: def __init__(self,name,aggr,hp): self.role_name = name self.role_aggr = aggr self.role_hp = hp def attack(self,dog): dog.dog_hp -= person.role_aggr print('{0}打了小狗{1}一下,小狗{1}剩余血量:{2}'.format(self.role_name,dog.dog_name,dog.dog_hp)) person = Person('zoro',20,100)#实例化一个人物zoro print('{}当前血量:{}'.format(dog.dog_name,dog.dog_hp)) person.attack(dog) print('{}当前血量:{}'.format(person.role_name,person.role_hp)) dog.bite(person)
计算圆的周长与面积
from math import pi class Circle: # pi = 3.14 def __init__(self,r): self.radius = r def perimeter(self): return 'perimeter is :{}'.format(round(2*int(self.radius)*pi,2))#保留两位小数 def area(self): return 'area is :{}'.format(pi*int(self.radius)**2) p = Circle(2) print(p.perimeter()) a = Circle(4) print(a.area())
小练习
餐馆
# 餐馆类 class Restaurant(): def __init__(self,name,type): self.restaurant_name = name self.restaurant_type = type def describle_restaurant(self):#描述前两项信息 print("the restaurant's name is".capitalize(),self.restaurant_name) print("the restaurant's main type is".capitalize(),self.restaurant_type) def open_restaurant(self):#打印餐馆正在营业 print('the restaurant is opening now'.capitalize()) restaurant = Restaurant('over_sea'.title(),'launch') restaurant.describle_restaurant() restaurant.open_restaurant() #多家餐馆 # restaurant_bf = Restaurant('good_day'.capitalize(),'breakfast') # restaurant_bf.describle_restaurant() # restaurant_din = Restaurant('slow_down'.capitalize(),'dinner') # restaurant_din.describle_restaurant()
用户
#用户类 class User(): location = 'california' def __init__(self,*args): self.first_name = args[0] self.last_name = args[1] self.sex = args[2] def describle_user(self):#打印用户信息摘要 print(self.first_name,self.last_name,self.sex,User.location) def greet_user(self):#向用户发出个性化问候 print('hello MR.'+self.last_name,',you are from '+User.location)#+ 无缝链接,逗号有个空格 bw = User('bruce','wayne','male') bw.describle_user() bw.greet_user() #多用户 # ts = User('tony','stark','male') # ts.describle_user() # ts.greet_user() # cap = User('rogers','steve','male') # cap.describle_user() # cap.greet_user()
餐馆——就餐人数
#就餐人数 class Restaurant(): def __init__(self,name,type): self.restaurant_name = name self.restaurant_type = type self.number_served = 22#就餐人数,默认的值 def describle_restaurant(self): # print("the restaurant's name is".capitalize(),self.restaurant_name)#输出太多信息,暂时注释掉 # print("the restaurant's main type is".capitalize(),self.restaurant_type)#输出太多信息,暂时注释掉 print("this restaurant has served {} customers".format(self.number_served)) def open_restaurant(self): print('the restaurant is opening now'.capitalize()) def set_number_served(self,num):#手动设置就餐人数 self.number_served = num def increment_number_served(self,incre_num):#就餐人数递增(根据情景可以增加判断语句限定不能为负数等等) self.number_served += incre_num restaurant = Restaurant('over_sea'.title(),'launch') restaurant.describle_restaurant() restaurant.set_number_served(55) restaurant.describle_restaurant() restaurant.increment_number_served(45) restaurant.describle_restaurant()
用户——尝试登录次数
#登录次数 class User(): location = 'california' def __init__(self,*args): self.first_name = args[0] self.last_name = args[1] self.sex = args[2] self.login_attempts = 0#登录次数 def describle_user(self): print(self.first_name,self.last_name,self.sex,User.location,'登录次数:'+str(self.login_attempts)) def greet_user(self): print('hello MR.'+self.last_name,',you are from '+User.location)#+ 无缝链接,逗号有个空格 def increment_login_attemts(self):#登录次数每次执行一次,值加一 self.login_attempts += 1 def set_login_attempts(self):#登录次数重置 self.login_attempts = 0 bw = User('bruce','wayne','male') bw.describle_user() bw.greet_user() bw.increment_login_attemts() bw.increment_login_attemts() bw.increment_login_attemts() bw.describle_user() bw.set_login_attempts() bw.describle_user()
pass