python(8):面向对象编程
有三种程序类型:
(1)面向过程:按照一定的逻辑顺序,一步步垒代码
(2)面向函数:对用常用的计算,建立函数避免重复
(3)面向对象: 函数的集合,对函数进行分类和封装
(一) 抽象
抽象: 哈巴狗, 宾利犬... 都是狗, 狗就是抽象
对象: 哈巴狗, 宾利犬, 藏獒
类的具体化叫对象, 对象的抽象叫做类
类是一个模板,
class(类):包含了很多函数的一个模块: 如何定义类?
class class_name(object): 'define classname class' class_suite
(object) 为父类!,,, 之后会介绍, 如果你的类没有继承任何父类, 那么默认就是object作为父类,
object是万类之源.
定义一个什么也不做的空类
class mydate(object): 'this is a very simple example class' pass # 表示什么也不做 # 这里的类仅作为名称空间
类的方法
class dog(obect): def greet(self): # python 类的定义中需要每个方法的声明中第一个参数是self print('hello')
第一个参数是self, 说明调用这个方法的对象自身在调用时不需要实参跟它对应.
# 定义类dog, 有一个方法是greet class dog(object): def greet(self): # python 类的定义中需要每个方法的声明中第一个参数是self print('hello') #实例创建 dog1=dog() # dog1就是实例名 dog1.greet() # 调用方法, hello
实例属性 instance attributes
class dog(object): def setname(self,name): self.name=name # 相当于dog.name='paul' def greet(self): print('Hi, my name is %s'%self.name) if __name__=='__main__': # 可以理解为一个程序的入口, 类似C中的main函数 dog1=dog() dog1.setname('paul') dog1.greet()
dog.name 就是实例属性
重要的__init__方法: 对象的初始化方法 __int__()
当类被调用后, python会创建实例对象,
创建完对象之后, python自动调用的第一个方法是__int__().
实例对象作为方法的第一个参数(self)被传递进去, 调用类创建实例对象时的参数都传给__int__()
class dog(object): def __init__(self, name): self.name=name def greet(self): print('Hi, my name is %s.'%self.name) if __name__=='__main__': # 可以理解为一个程序的入口, 类似C中的main函数 dog1=dog('mike') dog1.greet()
狗这个类是实例化之后都会自动创建名字, 每一个实例都要完成的事, 所以可以把它放到__init__方法中去.
类属性 : cnt实现统计这个类被创建的实例对象个数 , cnt 与具体的对象无关, 只跟类有关, 成为类属性, 也叫静态属性.
class dog(object): cnt=0 def __init__(self, name): self.name=name dog.cnt+=1 # 修改类属性必要要用类名 def greet(self): print('Hi, I am %s, my number id %d'%(self.name,dog.cnt)) if __name__=='__main__': # 可以理解为一个程序的入口, 类似C中的main函数 dog1=dog('sara') dog1.greet() dog2=dog('jason') dog2.greet() #Hi, I am sara, my number id 1 #Hi, I am jason, my number id 2
实例: roster 花名册
(1)__init__()方法对数据进行初始化,以班主任的姓名初始化;
(2)add():加入一个学生姓名;
(3)remove():按照姓名移除学生;
(4)print_all():输出班主任姓名和所有学生名单。
class roster(object): "students and teacher class" teacher = "" students = [ ] def __init__(self, tn = 'XY'): self.teacher = tn def add(self, sn): self.students.append(sn) def remove(self, sn): self.students.remove(sn) def print_all(self): print("Teacher:",self.teacher) print("Students:", self.students) r1=roster('scarlett') r1.add('mike') r1.add('jim') r1.add('alice') r1.add('kelly') r1.remove('jim') r1.print_all() #Teacher: scarlett #Students: ['mike', 'alice', 'kelly']
(二) 继承
在原有抽象的基础上进行修改, 生成新的抽象, 称作 继承
继承可以修改一个已经定义好的类, 将其修改生成一个新的类, 而不需要将原来的类再次实现一遍!
车--轿车, 救护车, 公共汽车...
子类的定义:
class subclassname(parentclass1): # 多个父类 class subclassname([parentclass1,parentclass2]): class_suite
单个父类叫做 单继承, 多个父类叫做 多继承
并不是所有的语言都支持多继承, java就不支持多继承
class dog(object): cnt=0 def __init__(self, name): self.name=name dog.cnt+=1 # 修改类属性必要要用类名 def greet(self): print('Hi, I am %s, my number id %d'%(self.name,dog.cnt)) # 定义一个子类, barkingdog, 父类是dog # 这里, 子类重写了父类的greet() 方法 class barkingdog(dog): def greet(self): print('woof!I am %s, my number is %d'%(self.name,dog.cnt)) if __name__=='__main__': dog=barkingdog('zoe') dog.greet() #woof!I am zoe, my number is 1
注意: 如果父类的__init__ 初始化方法被子类修改, 那么父类的初始化方法就不会被自动调用,
必须显式的写出来才会被执行.
实例:
class people: def __init__(self,n,a,w): self.name=n self.age=a self.weight=w def speak(self): print('%s is speaking: I am %d years old'%(self.name,self.age)) p=people('mike',10,20) p.speak() #不用加print print p.name print p.age ans: mike is speaking: I am 10 years old mike 10
具体:
class funset: 定义类的名称 def fun1(self): self是特殊的参数,必须要有!: #类中函数的第一个参数必须是self,类中定义的函数称为 方法, fun1就是一个方法 #do something x=funset()#根据类funset 创建对象
为什么要用类 ,明明函数可以解决的事情?
函数与函数之间是独立的,没有共用的数据!!!
面向对象的三大特征:封装\继承\多态
1.封装
#封装:先把东西封装在某个地方,以后在拿出来调用 class funset: def __init__(self,name,age): self.name=name self.age=age x=funset('xx',19) #将'xx'与19分别封装到x self的name与 age 属性中 y=funset('yy',20) #self是一个形式参数,执行x=funset('xx',19) 时,self等于x;执行y=funset('yy',20),self=y #内容被封装到了x, y 中,每个对象x,y都有name age 属性, #调用封装: 通过对象直接调用被封装的内容 print x.name print y.age #调用封装: 通过self间接调用被封装的内容 class funset: def __init__(self, name, age): self.name = name self.age = age def detail(self): print self.name print self.age x = funset('xx', 18) print x.name # 直接调用x对象的name属性 print x.age y=funset('alex', 73) y.detail() #间接调用, 默认将y传递给self参数,即x.detail(x)
解释__init__:init 创建完对象之后,pyhton会自动调用的方法,通过两个例子可以秒懂:
例1:
class dog(object): 'define dog class' def setname(self,name): self.name=name #传递形参的效果:dog.name='wangcai' def greet(self): print('hi, my name is %s'%self.name) if __name__=='__main__':#程序的入口,类似c语言中的main函数 dog1=dog() dog1.setname('wangcai') #将参数传递给形参, #传递形参的效果:dog.name='wangcai' dog1.greet() ans:hi, my name is wangcai
例2:
class dog(object): 'define dog class' def __init__(self,name): #实例化之后会自动取名字 #定义init, self.name=name def greet(self): print('hi, my name is %s'%self.name) if __name__=='__main__': dog1=dog('haha')#要是没有init那么 只能用dog1=dog(),dog1=dog('haha')中的haha传递不进去的 dog1.greet()
练习1;
请输出:
小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,下山采蘑菇
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,下山采蘑菇
方法一:面向函数
编写三个函数即可:
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 mogu(name, age, gender): print "%s,%s岁,%s,下山采蘑菇" %(name, age, gender) kanchai('小明', 10, '男') qudongbei('小明', 10, '男') mogu('小明', 10, '男') kanchai('老李', 90, '男') qudongbei('老李', 90, '男') mogu('老李', 90, '男')
方法二:面向对象
class funset: 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 mogu(self): print '%s,%s岁,%s,下山采蘑菇'%(self.name,self.age,self.gender) xm=funset('小明',10,'男') xm.kanchai() xm.qudongbei() xm.mogu()
练习二:
创建三个游戏人物:
水,女,18,初始战斗力1000
木,男,20,初始战斗力1800
山,女,19,初始战斗力2500
游戏场景,分别是:
草丛战斗,消耗200战斗力
自我修炼,增长100战斗力
多人游戏,消耗500战斗力
class person: def __init__(self,name,gender,age,fight): self.name=name self.age=age self.gender=gender self.fight=fight def grassland(self): self.fight-=200 def practice(self): self.fight+=200 def incest(self): self.fight-=500 def detail(self): temp='姓名:%s;性别:%s;年龄:%s;战斗力:%s'%(self.name,self.age,self.gender,self.fight) print temp x=person('haha','女',18,2400) x.detail() x.incest() x.detail() x.grassland() x.detail() ans: 姓名:haha;性别:18;年龄:女;战斗力:2400 姓名:haha;性别:18;年龄:女;战斗力:1900 姓名:haha;性别:18;年龄:女;战斗力:1700
应用实例:
从给出的数据文件中,找到成绩最好的学生:
class student: def __init__(self,name,hours,points): self.name=name self.hours=float(hours) self.points=float(points) def getname(self): return self.name def gethours(self): return self.hours def getpoints(): return self.points def gpa(self): return self.points/self.hours # #s=student('xxx',100,10) #print s.name #print s.getname()#两者一样 def makestudent(info): name,hours,points=info.split('\t') return student(name,hours,points) def main(): f=open(r'C:\Users\xuyin\Desktop\test\info_student.txt') best=makestudent(f.readline()) for line in f: if makestudent(line).gpa()>best.gpa(): best=makestudent(line) f.close() # print('the best student is %s'%best.getname()) # print('the hours are %.2f'%best.gethours()) # print('the gpa is %.2f'%best.gpa()) print('the best student is %s'%best.name) #不需要用getname print('the hours are %.2f'%best.hours) print('the gpa is %.2f'%best.gpa()) #if __name__=='__main__':#这一行不需要也可以的 main()
源数据:
ans:
the best student is ccc
the hours are 120.00
the gpa is 2.51