初级篇
- 面向过程:根据业务逻辑从上到下写垒代码
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用,如果使用函数式编程,需要在每次执行函数时传入相同的参数,如果参数多的话,又需要粘贴复制了... ;而对于面向对象只需要在创建对象时,将所有需要的参数封装到当前对象中,之后再次使用时,通过self间接去当前对象中取值即可。
比如函数式编程
def kanchai(name, age, gender):
print "%s,%s岁,%s,上山去砍柴" %(name, age, gender)
def qudongbei(name, age, gender):
print "%s,%s岁,%s,开车去东北" %(name, age, gender)
def dabaojian(name, age, gender):
print "%s,%s岁,%s,最爱大保健" %(name, age, gender)
kanchai('小明', 10, '男')
qudongbei('小明', 10, '男')
dabaojian('小明', 10, '男')
kanchai('老李', 90, '男')
qudongbei('老李', 90, '男')
dabaojian('老李', 90, '男')
面对对象编程
class Foo:
def __init__(self, name, age ,gender):
self.name = name
self.age = age
self.gender = gender
def kanchai(self):
print "%s,%s岁,%s,上山去砍柴" %(self.name, self.age, self.gender)
def qudongbei(self):
print "%s,%s岁,%s,开车去东北" %(self.name, self.age, self.gender)
def dabaojian(self):
print "%s,%s岁,%s,最爱大保健" %(self.name, self.age, self.gender)
xiaoming = Foo('小明', 10, '男')
xiaoming.kanchai()
xiaoming.qudongbei()
xiaoming.dabaojian()
laoli = Foo('老李', 90, '男')
laoli.kanchai()
laoli.qudongbei()
laoli.dabaojian()
面向对象的思维过程:
# 对象是具体的有其特征和动作,然后从众多的对象中抽象出类来
#举例狗,以一条具体的狗来举例,用字典来描述特征和动作
#思维:首先按过程先特征后动作的来描述具体对象
# dog1={
# 'name':'元昊',
# 'gender':'母',
# 'type':'藏獒' #基本特征
# }
# 狗的基本动作
# def jiao(dog): #函数中通过输入参数来形成互动
# print('一条狗[%s],汪汪汪' % dog['name'])
# def chi_shi(dog):
# print('一条[%s] 正在吃屎' % dog['type'])
# jiao(dog1)
# chi_shi(dog1)
# #缺点:要反复建参数字典而且如果不是狗,比如人只要有参数就可以一样显示
#改进:1,用局部作用域 2 字典里将动作也加进来
# def dog():# 以狗为对象做局部作用域,和特征动作为字典来描述对象
#
# def jiao (dog): # 函数中通过输入参数来形成互动
# print('一条狗[%s],汪汪汪' % dog['name'])
#
# def chi_shi(dog):
# print('一条[%s] 正在吃屎' % dog['type'])
#
# dog1 = {
# 'name': '元昊',
# 'gender': '母',
# 'type': '藏獒',
# 'jiao': jiao,
# 'chi_shi':chi_shi,
# }
#
# return dog1
#
# d1 = dog()
# print(d1) #{'name': '元昊', 'gender': '母', 'type': '藏獒', 'jiao': <function dog.<locals>.jiao at 0x0000020743571C80>, 'chi_shi': <function dog.<locals>.chi_shi at 0x0000020743571D08>}
# d1['jiao'](d1) # 一条狗[元昊],汪汪汪
#
# 缺点:因为参数固定,只能有一条狗,所以还要加入形参变成可输入互动
# def dog(name,gender,type):# 以狗为对象做局部作用域,和特征动作为字典来描述对象
# def init(name, gender, type): # 通过一个初始化函数定义了狗这类的基本特征和动作
# dog1 = {
# 'name': name,
# 'gender': gender,
# 'type': type,
# 'jiao': jiao,
# 'chi_shi': chi_shi,
# }
# return dog1
# def jiao (dog): # 动作用函数描述,函数中通过输入参数来形成互动
# print('一条狗[%s],汪汪汪' % dog['name'])
#
# def chi_shi(dog): # 动作用函数描述,函数中通过输入参数来形成互动
# print('一条[%s] 正在吃屎' % dog['type'])
#
# return init(name,gender,type)
#
#
# d1 = dog('alex','公','吉娃娃')
# print(d1) #{'name': 'alex', 'gender': '公', 'type': '吉娃娃', 'jiao': <function dog.<locals>.jiao at 0x000001A49E821C80>, 'chi_shi': <function dog.<locals>.chi_shi at 0x000001A49E821D08>}
# print(d1['name']) #alex
# d1['jiao'](d1) #一条狗[alex],汪汪汪
#例二 :学校 特征:name,addr,type 动作:招生,开除,考试
# school1={
# 'name':'old boy',
# 'addr':'沙河',
# 'type':'私立'
# }
#
# def kao_shi(school):
# print('%s学校正在考试'%school['name'])
# def zhao_sheng(school):
# print('%s %s 学校正在招生'%(school['type'],school['name']))
#
# kao_shi(school1) #old boy学校正在考试
# zhao_sheng(school1)#私立 old boy 学校正在招生
#改进:通过对学校作为对象来设立函数加入作用域、设立形参、特征动作的联动
# def school(name,addr,type):
#
#
# def kao_shi(sch):
# print('%s学校正在考试'%sch['name'])
# def zhao_sheng(sch):
# print('%s %s 学校正在招生'%(sch['type'],sch['name']))
#
# sch = {
# 'name': name,
# 'addr': addr,
# 'type': type,
# 'kao_shi': kao_shi,
# 'zhao_sheng': zhao_sheng
# }
# return sch
#
# s1 = school('old boy','沙河','私立')
# print(s1) #{'name': 'old boy', 'addr': '沙河', 'type': '私立', 'kao_shi': <function school.<locals>.kao_shi at 0x000001D24F791C80>, 'zhao_sheng': <function school.<locals>.zhao_sheng at 0x000001D24F791D08>}
# s1['kao_shi'](s1) #old boy学校正在考试
#改进:通过def init函数,这样通过完全的几个函数将对象上升到对某类别的编程,对象:某一学校 上升到:类别:学校
# def school(name,addr,type):
# def init(name, addr, type):
# sch = {
# 'name': name,
# 'addr': addr,
# 'type': type,
# 'kao_shi': kao_shi,
# 'zhao_sheng': zhao_sheng
# }
# return sch
# def kao_shi(sch):
# print('%s学校正在考试'%sch['name'])
# def zhao_sheng(sch):
# print('%s %s 学校正在招生'%(sch['type'],sch['name']))
# return init(name,addr,type)
#
# s1 = school('old boy','沙河','私立')
# print(s1) #{'name': 'old boy', 'addr': '沙河', 'type': '私立', 'kao_shi': <function school.<locals>.kao_shi at 0x000001D24F791C80>, 'zhao_sheng': <function school.<locals>.zhao_sheng at 0x000001D24F791D08>}
# s1['kao_shi'](s1)
类和实例对象:
- class是关键字,表示类
- 创建对象,类名称后加括号即可
# class Chinese:
# '这是一个中国人的类'
# pass
#
# #实例化到底干了什么?
# p1=Chinese() #实例化
# print(p1) #<__main__.Chinese object at 0x00000264B79D0978>
'''
1.数据属性
2.函数属性
'''
# print(Chinese.__name__) # Chinese 类的名称
# print(Chinese.__doc__) #这是一个中国人的类 类的文档
# print(Chinese.__bases__) #<class 'object'>
# print(Chinese.__module__)#__main__此模块在本文件中
# print(Chinese.__class__) # <class 'type'>
# class Chinese:
# '这是一个中国人的类'
#
# dang='共产党'
# def __init__(name,age,gender):
# dic={
# 'name':name,
# 'age':age,
# 'gender':gender
# }
# return dic
# def __init__(self,name,age,gender): # 必须要有self参数,表示实例自己,而且不能有return
# print('我是初始化函数,我开始运行了')
# self.mingzi=name #p1.mingzi=name
# self.nianji=age #p1.nianji=age
# self.xingbie=gender
# print('我结束啦')
# def sui_di_tu_tan(self):
# print('%s 朝着墙上就是一口痰' %self.mingzi)
# def cha_dui(self):
# print(self)
# print('%s 插到了前面' %self.mingzi)
# def eat_food(self,food):
# print('%s 正在吃%s' %(self.mingzi,food))
#
# p1 = Chinese('元昊', 18, 'female')# 实例化,相当于调用了函数 我是初始化函数,我开始运行了 我结束啦
# print(p1) #<__main__.Chinese object at 0x0000021EF69643C8>
# print(p1.__dict__)#{'mingzi': '元昊', 'nianji': 18, 'xingbie': 'female'} 就是实例本身,某个具体的对象,但只包含数据属性,没有函数属性
# print((p1.__dict__)['nianji']) #18
# print(p1.nianji) #18
# print(p1.dang)#共产党
# Chinese.sui_di_tu_tan(p1) #元昊 朝着墙上就是一口痰
# p1.sui_di_tu_tan() #元昊 朝着墙上就是一口痰 虽然未输入参数,但实际是默认把p1传入了,如果非要传入p1,会报错多传了
# p1.eat_food('鱼')
基本属性操作:
# class Chinese:
# country='China'
# def __init__(self,name):
# self.name=name
#
# def play_ball(self,ball):
# print('%s 正在打 %s' %(self.name,ball))
# #查看
# print(Chinese.country) #China
#
# #修改
# Chinese.country='Japan'
# print(Chinese.country) #Japan
#
# p1=Chinese('alex')
# print(p1.__dict__) #{'name': 'alex'}
# print(p1.country) #Japan
#
# #增加
# Chinese.dang='共产党'
#
# print(Chinese.dang) #共产党
# print(p1.dang)#共产党
#
# #删除
# del Chinese.dang
# del Chinese.country
#
# print(Chinese.__dict__)
#print(Chinese.country) #删除后,再查询就报错了AttributeError: type object 'Chinese' has no attribute 'country'
#
# def eat_food(self,food):#目前新写的要追加的函数和类是同级,故写好后要完善下面那句
# print('%s 正在吃%s' %(self.name,food))
#
# Chinese.eat=eat_food
#
# print(Chinese.__dict__)
# p1.eat('肉')
# def test(self):
# print('test')
#Chinese.play_ball=test # 将原函数用新的函数名替代掉就名字不变,但函数体里的内容更换过来了
#p1.play_ball()# Chinese.play_ball(p1) test
#p1.test() # 这个运行无结果
#
# p1.age=18 #追加实例的属性
# print(p1.__dict__) # {'name': 'alex', 'age': 18}
# print(p1.age) # 18
# def test(self):
# print('这是实例的函数属性')
# p1.test = test
# print(p1.__dict__) #'name': 'alex', 'age': 18, 'test': <function test at 0x0000023609F6B158>}
# p1.test(p1) #这是实例的函数属性
#
# p1.age=19 # 修改
# print(p1.__dict__) #{'name': 'alex', 'age': 19, 'test': <function test at 0x0000022EAE28B158>}
# print(p1.age) #19
#
# del p1.test #删除
# print(p1.__dict__) #{'name': 'alex', 'age': 19}
进一步理解类属性和实例属性:
class Chinese:
# country='China'
# l=['a','b']
# def __init__(self,name):
# self.name=name
#
# def play_ball(self,ball):
# print('%s 正在打 %s' %(self.name,ball))
# p1=Chinese('alex')
# print(p1.l) # ['a', 'b']
# p1.l=[1,2,3] # 修改了实例的属性,但类的属性不变
# print(Chinese.l) #['a', 'b'] 类的属性不变
# print(p1.__dict__)#{'name': 'alex', 'l': [1, 2, 3]}
# p1.l.append('c')# 还是在修改实例属性
# print(p1.__dict__) #{'name': 'alex', 'l': [1, 2, 3, 'c']}
# print(Chinese.l) # ['a', 'b'] 类的属性不变
# p1.l.append('c')# 如果之前没有p1.l=[1,2,3](此命令是给实例增加了一个l的属性) ,就直接运行此命令,那么这在修改类的属性
# print(p1.__dict__) #{'name': 'alex'}实例属性不变
# print(Chinese.l) # ['a', 'b', 'c'] 类的属性变了
面向对象的三大特性是指:封装、继承和多态
1 封装 对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容
class Room:
def __init__(self,name,owner,width,length,high):
self.name=name
self.owner=owner
self.__width=width #此参数的设定外部不可见,开始准备封装
self.__length=length
self.__high=high
def tell_area(self): #此时我们想求的是面积,给对方开个接口直接见结果,但细节均不可见
return self.__width * self.__length *self.__high
def tell_width(self):
return self.__width
r1=Room('卫生间','alex',100,100,10000)
#arear=r1.__width * r1.__length # 'Room' object has no attribute '__width',因为参数对外不可见
print(r1.tell_area())
2 继承 子可以继承父的内容 对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法,除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已
- 当类是经典类时,多继承情况下,会按照深度优先方式查找
- 当类是新式类时,多继承情况下,会按照广度优先方式查找
类的组合和继承:
由类变成组合,原理:各类之间没有共同点,但有关联,所以就把类当成参数输入到另一类中,形成了组合
# class School:
# def __init__(self,name,addr):
# self.name=name
# self.addr=addr
#
# def zhao_sheng(self):
# print('%s 正在招生' %self.name)
#
# class Course:
# def __init__(self,name,price,period,school):
# self.name=name
# self.price=price
# self.period=period
# self.school=school
#
# s1=School('oldboy','北京')
# s2=School('oldboy','南京')
# s3=School('oldboy','东京')
#
# c=Course('linux',10,'1h','oldboy 北京')
# c1=Course('linux',10,'1h',s1)
#
# print(c.__dict__)#{'name': 'linux', 'price': 10, 'period': '1h', 'school': 'oldboy 北京'}
# print(c1.__dict__) #{'name': 'linux', 'price': 10, 'period': '1h', 'school': <__main__.School object at 0x000001E64D354898>}
# print(c1.school.name)# 从组合中调用类的对应的属性,也是用.来表示层级关系 #oldboy
# print(s1)#<__main__.School object at 0x00000217E5B647F0> 表示实例化的对象
# print(s1.__dict__)#{'name': 'oldboy', 'addr': '北京'},实例化的数据属性
# print(s1.zhao_sheng) #<bound method School.zhao_sheng of <__main__.School object at 0x000001F84C8947F0>>
# s1.zhao_sheng() #oldboy 正在招生 实例化后调用类的函数属性
#利用组合+input 构建一套学生自己选课的系统
# class School:
# def __init__(self,name,addr):
# self.name=name
# self.addr=addr
#
#
# def zhao_sheng(self):
# print('%s 正在招生' %self.name)
#
# class Course:
# def __init__(self,name,price,period,school):
# self.name=name
# self.price=price
# self.period=period
# self.school=school
#
#
#
# s1=School('oldboy','北京')
# s2=School('oldboy','南京')
# s3=School('oldboy','东京')
#
# # c1=Course('linux',10,'1h','oldboy 北京')
# # c1=Course('linux',10,'1h',s1)
#
# msg='''
# 1 老男孩 北京校区
# 2 老男孩 南京校区
# 3 老男孩 东京校区
# '''
# while True:
# print(msg)
# menu={
# '1':s1,
# '2':s2,
# '3':s3
# }
# choice=input('选择学校>>: ')
# school_obj=menu[choice]
# name=input('课程名>>: ')
# price=input('课程费用>>: ')
# period=input('课程周期>>: ')
# new_course=Course(name,price,period,school_obj)
# print('课程【%s】属于【%s】学校' %(new_course.name,new_course.school.name)) #课程【linux】属于【oldboy】学校
#类的继承:各类之间有不少的相同之处,可以用类的继承
# class Dad:
# '这个是爸爸类'
# money=10
# def __init__(self,name):
# print('爸爸')
# self.name=name
# def hit_son(self):
# print('%s 正在打儿子' %self.name)
#
# class Son(Dad): # 类SON需继承父类DAD,所以传入的参数是DAD
# money = 1000000000009
# def __init__(self,name,age):
# self.name=name
# self.age=age
#
# def hit_son(self):
# print('来自儿子类')
#
# print(Son.money) # 10,说明已经继承了父类的数据属性
# # print(Dad.__dict__)
# # print(Son.__dict__)
# s1=Son('alex',18) #按类的继承,参数是父亲的参数
# print(s1.name)#alex
# s1.hit_son()#alex 正在打儿子
#
# #但是如果子类有自己的属性,就会用自己的属性取代掉父亲的属性。
#接口继承,适合归一化设计
# import abc
# class All_file(metaclass=abc.ABCMeta):
# @abc.abstractmethod
# def read(self):#基类中的函数只是给子类框个规范的框架,让子类如此构建框架,并不需要实例化和具体化,子类在具体和实例化
# pass
#
# @abc.abstractmethod
# def write(self):
# pass
# class Disk(All_file):
# def read(self):
# print('disk read')
#
# def write(self):
# print('disk write')
#
# class Cdrom(All_file):
# def read(self):
# print('cdrom read')
#
# def write(self):
# print('cdrom write')
#
#
# class Mem(All_file):
# def read(self):
# print('mem read')
# def write(self):
# print('mem write')
# m1=Mem()
# m1.read()# mem read
# m1.write()#mem write #即接口规定的属性,子类就必须继承,否则无法实例化
# class A:
# # def test(self):
# # print('A')
# pass
# class B(A):
# # def test(self):
# # print('B')
#
# pass
# class C(A):
# # def test(self):
# # print('C')
# pass
#
# class D(B):
# # def test(self):
# # print('D')
# pass
#
# class E(C):
# # def test(self):
# # print('E')
# pass
#
# class F(D,E):
# # def test(self):
# # print('F')
# pass
# f1=F()
# f1.test() #通过逐一的关闭,测出其调用的顺序是经典类按深度找:F->D->B->A-->E-->C
#
# print(F.__mro__) #也可以通过__mro__来直接查看调用顺序#F-->D->B-->E--->C--->A新式类
#子类中调用父类:
# class Vehicle:
# Country='China'
# def __init__(self,name,speed,load,power):
# self.name=name
# self.speed=speed
# self.load=load
# self.power=power
# def run(self):
# print('开动啦')
# print('开动啦')
# class Subway(Vehicle):
# def __init__(self,name,speed,load,power,line):
# Vehicle.__init__(self,name,speed,load,power)
# self.line=line
#
# def show_info(self):
# print(self.name,self.speed,self.load,self.power,self.line)
#
# def run(self):
# Vehicle.run(self)
# print('%s %s 线,开动啦' %(self.name,self.line))
# line13=Subway('北京地铁','10km/s',1000000000,'电',13)
#
# line13.show_info()#北京地铁 10km/s 1000000000 电 13
# # 子类有自己的属性如何调用父类的属性,就是子类里直接在调用父类的函数上,在添加自己的
# line13.run()# 开动啦 开动啦 北京地铁 13 线,开动啦
# 缺点是父类的名称一改,所以对应子类调用的父类函数都要一一修改,所以就出现了super()来代替父类函数的方法
#使用super()方法的好处:1 不用写父类名了,所以父类名改了,不用一一修正子类 2 不用传self参数了
class Vehicle1:
Country='China'
def __init__(self,name,speed,load,power):
self.name=name
self.speed=speed
self.load=load
self.power=power
def run(self):
print('开动啦')
print('开动啦')
class Subway(Vehicle1):
def __init__(self,name,speed,load,power,line):
# Vehicle.__init__(self,name,speed,load,power)
super().__init__(name,speed,load,power) #super(__class__,self).__init__(name,speed,load,power)
#super(Subway,self).__init__(name,speed,load,power)=super().__init__(name,speed,load,power),所以super后面不用传self参数
self.line=line
def show_info(self):
print(self.name,self.speed,self.load,self.power,self.line)
def run(self):
# Vehicle.run(self)
super().run()
print('%s %s 线,开动啦' %(self.name,self.line))
line13=Subway('北京地铁','10km/s',1000000000,'电',13)
line13.show_info()#北京地铁 10km/s 1000000000 电 13
line13.run() #开动啦 开动啦 北京地铁 13 线,开动啦
print(line13.__class__) #<class '__main__.Subway'>
3 多态
class H2O:
def __init__(self,name,temperature):
self.name=name
self.temperature=temperature
def turn_ice(self):
if self.temperature < 0:
print('[%s]温度太低结冰了' %self.name)
elif self.temperature > 0 and self.temperature < 100:
print('[%s]液化成水' %self.name)
elif self.temperature > 100:
print('[%s]温度太高变成了水蒸气' %self.name)
def aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(self):
pass
class Water(H2O):
pass
class Ice(H2O):
pass
class Steam(H2O):
pass
w1=Water('水',25)
i1=Ice('冰',-20)
s1=Steam('蒸汽',3000)
w1.turn_ice()
i1.turn_ice()
s1.turn_ice()
面向对象初级知识的介绍,总结如下:
- 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
- 类 是一个模板,模板中包装了多个“函数”供使用
- 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
- 面向对象三大特性:封装、继承和多态