python自动化_day6_面向对象_组合,继承,多态
复习:http://www.cnblogs.com/Eva-J/articles/7228075.html
模块
1 import collections,os,sys,re,random,time 2 collections.defaultdict() #默认字典 默认字典的优势就是该字典中如果没有元素就直接添加 3 collections.OrderedDict() #有序字典 字典是有序的可以直接用索引调用 4 collections.namedtuple() #可命名元祖 可以把两个元组重命名之后简单调用 5 time.time() #时间戳时间 6 time.strftime()#字符串时间 7 time.localtime()#结构化时间 8 random.choice([1,'23',[4,5]]) # #1或者23或者[4,5] #随机选择一个返回 9 random.randint(1,5)# 大于等于1且小于等于5之间的整数 10 random.randrange(1,10,2) # 大于等于1且小于10之间的奇数 11 random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合 12 #os模块中很多跟操作系统相关的东西 13 #文件相关 14 #文件夹相关的 15 #和执行系统命令相关 16 #和路径相关的 17 sys.argv() #命令行参数List,第一个元素是程序本身路径 18 sys.exit() #退出程序,正常退出时exit(0),错误退出sys.exit(1) 19 sys.version #获取Python解释程序的版本信息 20 sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 21 sys.platform #返回操作系统平台名称 22 #re模块中的正则表达式使用很重要
初识面向对象
模拟一个人狗大战的游戏:使用函数,来写人狗大战
1 #首先进一个游戏公司 2 #写人狗大战的游戏 3 #想一下 需要有一个人 一个狗 需要互相攻击(动作)会影响游戏人物或者狗的值的变化 4 #人 需要有基础属性(生命值,武力值,名字,性别,背包) 5 def Person(name,sex,hp,dps): #人模子 创建出来的所有人都有相同的属性值 6 dic = {'name':name,'sex':sex,'hp':hp,'dps':dps,'bag':[]} 7 return dic 8 alex = Person('alex','N',250,5) 9 #狗 需要有基础属性(生命值,武力值,名字,品种) 10 def Dog(name,kind,hp,dps): 11 dic = {'name': name, 'kind': kind, 'hp': hp, 'dps': dps} 12 return dic 13 ha2 = Dog('哈士奇','藏獒',15000,200) 14 #需要给人和狗安排技能 人可以打狗,狗可以咬人 15 print(alex) 16 print(ha2) 17 #人打狗 18 def attack(person_name,dog_name,person_dps,dog_hp): 19 print('%s打了%s,%s掉了%s点血,还剩%s血' %(person_name,dog_name,dog_name,person_dps,dog_hp-person_dps)) 20 attack(alex['name'],ha2['name'],alex['dps'],ha2['hp']) 21 print(ha2) 22 #目前问题 人大狗只是显示了一个数值没有改变原狗的属性,并且传参还特别麻烦所以需要想办法 23 def attack(person,dog): 24 dog['hp'] -= person['dps'] 25 print('%s打了%s,%s掉了%s点血,还剩%s血' %(person['name'],dog['name'],dog['name'],person['dps'],dog['hp'])) 26 attack(alex,ha2) 27 #狗咬人 28 def bite(dog,person): 29 person['hp']-= dog['dps'] 30 print('%s咬%s,%s掉了%s点血,还剩%s血' % (dog['name'], person['name'], person['name'], dog['dps'], person['hp'])) 31 bite(ha2,alex) 32 print(ha2,alex) 33 #从这里基本实现了人打狗,狗咬人的互动 但是有一个问题,思考如果人咬狗或者狗打人会怎么办,这是一个问题所以我们需要进行动作限制
下面思考需要对动作做限制可以如下:
1 def Person(name,sex,hp,dps): 2 dic = {'name':name,'sex':sex,'hp':hp,'dps':dps,'bag':[]} 3 def attack(dog): 4 dog['hp'] -= dic['dps'] 5 print('%s打了%s,%s掉了%s点血,还剩%s血' % (dic['name'], dog['name'], dog['name'], dic['dps'], dog['hp'])) 6 dic['attack'] = attack 7 return dic 8 def Dog(name,kind,hp,dps): 9 dic = {'name': name, 'kind': kind, 'hp': hp, 'dps': dps} 10 def bite(person): 11 person['hp'] -= dic['dps'] 12 print('%s咬%s,%s掉了%s点血,还剩%s血' % (dic['name'], person['name'], person['name'], dic['dps'], person['hp'])) 13 dic['bite'] = bite 14 return dic 15 alex = Person('alex','N',250,5) 16 ha2 = Dog('哈士奇','藏獒',15000,200) 17 18 print(alex) 19 print(ha2) 20 print(alex['attack']) 21 alex['attack'](ha2)
以上就是使用了基本的面向对象的思想。
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。面向对象的程序设计好比如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题需要四个人:唐僧,沙和尚,猪八戒,孙悟空,每个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的属性和方法),然而这并不好玩,于是如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。然后取经开始,师徒四人与妖魔鬼怪神仙互相缠斗着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取。
面向对象的程序设计的
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
在python 中面向对象的程序设计并不是全部。
面向对象编程可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
了解一些名词:类、对象、实例、实例化
类:具有相同特征的一类事物(人、狗、老虎)
对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)
实例化:类——>对象的过程(这在生活中表现的不明显,我们在后面再慢慢解释)
按照以前的逻辑,人狗大战创建一个人,创建一只狗,人打狗,狗咬人,两个函数做一些动作,可以理解为面向过程编程
造模子 -------->>>面向对象
好处:规范了一些角色的属性项目,属性的名字,技能,技能的名字
权限:有一些函数只能是这个角色才可以调用
面向对象的规则:类被创造出来 就是一个模子,谁为了描述对象的
类:具有相同属性和相同动作的一类事物组成一个类 类是抽象的
对象:具体的某一个具有实际属性和具体动作的一个实体,对象是具体的
只要是写在类名字中的名字,不管是变量还是函数名,都不能在类的外边直接使用
类的功能:查看属性、实例化----创建对象
1 class 类名: 2 静态属性 = 123 3 def 动态属性(self): #self 在类中的方法一个默认的参数 4 print(self) 5 print(类名.静态属性) 6 类名.静态属性 = 456 7 print(类名.静态属性) 8 类名.静态属性2 = 'abc' 9 print(类名.静态属性2) 10 del 类名.静态属性2 11 print(类名.静态属性2) 12 print(类名.__dict__) #类中必要的默认值之外,还记录了程序员在类中定义的所有名字
类名可以查看某个方法,但是一般情况下,我们不直接使用类名调用方法,类的函数名第一个字母一定是大写的,函数的第一个字母一定是小写的。
创建一个类:
1 class Person:pass 2 alex = Person() 3 print(alex) #object 对象 alex是Person类的一个对象 4 对象 = 类名() 5 print(Person) 6 print(alex.__dict__) 7 # alex name hp dps bag sex 8 alex.__dict__['name'] = 'alex' 9 alex.__dict__['sex'] = 'N' 10 alex.__dict__['hp'] = 250 11 alex.__dict__['dps'] = 5 12 alex.__dict__['bag'] = [] 13 print(alex.__dict__) 14 alex.name = 'alex' 15 alex.hp = 250 16 alex.dps = 5 17 alex.bag = [] 18 alex.sex = 'N' 19 print(alex.__dict__)
分析:为什么会执行init中的内容 self到底是什么
实例化的过程:
1、类名()就是实例化
2、在实例化的过程中发生了很多事情外部是看不到的
3、创造一个对象,自动调用__init__方法
4、这个被创造的对象会被当做实际参数传到__init__方法中,并且传给第一个self参数
5、执行__init__方法中的内容
6、自动把self方法作为返回值,返回给实例化的地方
1 #人狗大战 使用面向对象 2 class Person: 3 def __init__(self,name,hp,sex,dps): 4 self.name = name 5 self.hp = hp 6 self.sex = sex 7 self.dps = dps 8 self.bag = [] 9 def attack(self,dog): 10 dog.hp -= self.dps 11 print('%s打了%s,%s掉了%s点血,还剩%s血' % (self.name, dog.name, dog.name, self.dps, dog.hp)) 12 class Dog: 13 def __init__(self,name,hp,kind,dps): 14 self.name = name 15 self.hp = hp 16 self.kind = kind 17 self.dps = dps 18 def bite(self,person): 19 person.hp -= self.dps 20 print('%s咬%s,%s掉了%s点血,还剩%s血' % (self.name, person.name, person.name, self.dps, person.hp)) 21 alex = Person('aelx',250,'N',5) 22 ha2 = Dog('哈士奇',15000,'藏獒',200) 23 print(alex.__dict__) #init的储存的内容查看使用__dict__ 24 Person.attack(alex) #类中的函数调用 25 alex.attack(ha2) 26 ha2.bite(alex) 27 print(alex.__dict__) 28 print(ha2.__dict__)
对象名 方法名 相当于调用一个函数,这个函数默认把对象名作为第一个参数传入函数中
剩余的其他参数根据我们的需求可以随意传
1 #小练习 计算圆形的面积和周长 已知半径 2 from math import pi 3 class Circle: 4 def __init__(self,r): 5 self.r = r 6 def perimeter(self): 7 print(2*pi*self.r) 8 def area(self): 9 print(pi*self.r*self.r) 10 circle = Circle(5) 11 circle.perimeter() 12 circle.area() 13 14 #每一个角色都有属于自己的属性和方法 15 #高可扩展性 可读性 规范性 16 #结局不可控
#############命名空间####################
类有自己的命名空间,对象也有自己的命名空间,分析对象是否可以访问类的命名空间,类是否可以访问对象的命名空间
1 class Person: 2 COUNTRY = '中国人' #静态属性 3 def __init__(self,name): 4 self.name = name 5 def eat(self): 6 print('%s在吃泔水' %self.name) 7 alex = Person('alex') 8 egon = Person('egon')
#当一个类在创建一个实例的时候,就产生了一个这个实例和类之间的联系
#可以通过实例 对象 找到实例化它的类
#类不能找到他的实例化
#在访问变量的时候,都先使用自己命名空间中的,如果自己的空间没有,再到类的空间中去找
#在使用对象修改静态变量的过程中,相当于在自己的空间中创建了一个新的变量
#在类的静态变量的操作中,应该使用类名来直接进行操作,就不会出现乌龙操作
1 #创建一个类,计算这个类创建了多少个实例 2 class Foo: 3 count = 0 4 def __init__(self): 5 Foo.count += 1 6 f1 = Foo() 7 print(Foo.count)
###########################组合#########################
1 组合: 一个类的对象作为另外一个类对象的的属性 2 class Person: 3 def __init__(self,name,hp,sex,dps): 4 self.name = name 5 self.hp = hp 6 self.sex = sex 7 self.dps = dps 8 self.bag = [] 9 def attack(self,dog): 10 dog.hp -= self.dps 11 print('%s打了%s,%s掉了%s点血,还剩%s血' % (self.name, dog.name, dog.name, self.dps, dog.hp)) 12 class Dog: 13 def __init__(self,name,hp,kind,dps): 14 self.name = name 15 self.hp = hp 16 self.kind = kind 17 self.dps = dps 18 def bite(self,person): 19 person.hp -= self.dps 20 print('%s咬%s,%s掉了%s点血,还剩%s血' % (self.name, person.name, person.name, self.dps, person.hp)) 21 alex = Person('aelx',250,'N',5) 22 ha2 = Dog('哈士奇',15000,'藏獒',200) 23 print(alex.name)
1 #基础数据类型 都是类 2 #'alex' : str 的对象 3 # alex.name = 'alex' 4 #给alex装备一个武器 alex打不过狗花钱装备一个武器 5 class Weapon: 6 def __init__(self,name,price,dps): 7 self.name = name 8 self.price = price 9 self.dps = dps 10 def kill(self,dog): 11 dog.hp -= self.dps 12 dagoubang = Weapon('dagougun',600000,10000) 13 alex.money = 1000000 14 if alex.money >= dagoubang.price: 15 alex.weapon = dagoubang 16 alex.weapon.kill(ha2) 17 print(ha2.hp)
计算圆环的面积和周长,已知外圆
1 from math import pi 2 class Circle: 3 def __init__(self,r): 4 self.r = r 5 def perimeter(self): 6 return 2*pi*self.r 7 def area(self): 8 return pi*self.r*self.r 9 # circle = Circle(5) 10 class Cirque: 11 def __init__(self,outside_r,inside_r): #已知外圆内园的半径调用外圆的方法就是直接调用外圆类的函数 12 self.out_circle = Circle(outside_r) 13 self.in_circle = Circle(inside_r) 14 def perimeter(self): 15 return self.out_circle.perimeter() + self.in_circle.perimeter() 16 def area(self): 17 #返回大圆面积 - 小圆面积 18 return self.out_circle.area() - self.in_circle.area() 19 ring = Cirque(10,5) 20 print(ring.area()) 21 print(ring.perimeter())
#组合是描述了一种什么有什么的关系 圆环有圆 人有武器
#面向对象初识
# 如何创建一个类
# 类的实例化 # 实例和对象是一回事
# 对象调用方法
# 类调用静态属性
# __init__
#命名空间
#类的组合用法 人有武器 圆环有圆 两个类之间有关系 调用类的方法或者函数
#####################继承###########################
#为什么会有继承 为了解决代码的冗余问题 class Person: def __init__(self,name,hp,sex,dps): self.name = name self.hp = hp self.sex = sex self.dps = dps self.bag = [] def attack(self,dog): dog.hp -= self.dps print('%s打了%s,%s掉了%s点血,还剩%s血' % (self.name, dog.name, dog.name, self.dps, dog.hp)) class Dog: def __init__(self,name,hp,kind,dps): self.name = name self.hp = hp self.kind = kind self.dps = dps def bite(self,person): person.hp -= self.dps print('%s咬%s,%s掉了%s点血,还剩%s血' % (self.name, person.name, person.name, self.dps, person.hp)) alex = Person('aelx',250,'N',5) ha2 = Dog('哈士奇',15000,'藏獒',200) print(alex.name) #分析以上代码人和狗都有相同的属性,如果单独写,会显得很啰嗦,为了解决这个办法可以使用面向对象的继承
继承分为:单继承和多继承
1 #单继承 2 class Parent:pass 3 class Son(Parent):pass 4 #Son 类继承Parent类 5 #父类 基类 超类 ------Parent类 6 #子类 派生类 -------Son类 7 8 #多继承 9 class Parent1:pass 10 class Parent2:pass 11 class Son(Parent1,Parent2):pass
解决上面人狗大战中代码冗余问题:直接使用继承,创建一个动物类,包含人和狗一些必要的属性。
1 class Animal: 2 def __init__(self,name,hp,dps): 3 print('---------->') 4 self.name = name 5 self.hp = hp 6 self.dps = dps 7 def eat(self): #父类的eat方法子类可以调用 8 print('%s吃药回血了' %self.name) 9 class Person(Animal): 10 def __init__(self,name,hp,dps,sex): 11 super().__init__(name,hp,dps)# Animal.__init__(self,name,hp,dps) 12 self.sex = sex 13 def attack(self, dog): 14 dog.hp -= self.dps 15 print('%s打了%s,%s掉了%s点血,还剩%s血' % (self.name, dog.name, dog.name, self.dps, dog.hp)) 16 17 class Dog(Animal): 18 def __init__(self,name, hp, dps,kind): 19 super().__init__(name, hp, dps)# Animal.__init__(self, name, hp, dps) 20 self.kind = kind 21 def bite(self, person): 22 person.hp -= self.dps 23 print('%s咬%s,%s掉了%s点血,还剩%s血' % (self.name, person.name, person.name, self.dps, person.hp)) 24 alex = Person('alex',250,5,'N') 25 ha2 = Dog('哈士奇',15000,200,'藏獒') 26 print(alex.__dict__) 27 print(ha2.__dict__) 28 ha2.eat() 29 alex.eat() 30 ha2.bite(alex) 31 alex.attack(ha2)
1 #面试题 2 class Foo: 3 def __init__(self): 4 self.func() 5 def func(self): 6 print('in foo') 7 class Son(Foo): 8 def func(self): 9 print('in son') 10 Son() 11 12 #python两种类 13 #python3已经灭绝了 经典类 14 #经典类都遵循深度优先算法 15 #新式类 python3所有的类都是新式类 class A(object): 所有的新式类都继承object 16 #新式类在多继承中都遵循广度优先算法 17 #super和找父类这件事是两回事 18 #在单继承中super就是找父类 19 #在多级继承中 super的轨迹 是根据整个模型的起始点展开一个广度优先算法 遵循mro规则来的