six day--面向对象
Posted yuyou123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了six day--面向对象相关的知识,希望对你有一定的参考价值。
一、复习模块
1.计算时间差例子
2.随机数 代码 sample 随机取多个返回值
3.re 要求掌握常用的:与注册相关的,邮箱、手机号、省份证号
1 # collections模块 2 # 有序字典 orderddict 3 # 默认字典 defaultdict 4 # 可命名元祖 namedtuple 5 6 # 时间模块 7 # 三种时间格式 时间戳时间 结构化时间 格式化时间 8 # 计算时间差 9 # 两个时间都转换成时间戳 10 # 时间戳之间相减 以秒为单位的小数差 11 # 将小数差转换成结构化时间 元组 1970 1.3 12 # 用当前结构化的时间差 减去 1970 1 1 0:0:0 13 14 # random模块 15 # 发红包 发200的红包,发5个 —— 代码 16 # (0,200) 取4个点 17 # 验证码 18 # 从数字中选一个 0-9 19 # 从a-z选一个 20 # 到底是字母还是数字也是随机的 21 22 # os模块 —— 操作系统打交道 23 # 文件相关 24 # 文件夹相关的 25 # 和执行系统命令相关 26 # 和路径相关的 27 28 # sys模块 —— 和解释器相关的 29 # sys.path 30 # sys.argv 执行py脚本的时候传入的参数 31 32 # 正则模块 33 # 正则表达式 34 # 能够判断 邮箱 手机号 35 # re模块 36 37 38 # 三个模块+序列化 未讲
二、面向对象
1.引入--人狗大战
1.传具体的四个值,bug:未改变dog字典的值,写法麻烦
优化-传person、dog函数 --存在bug:出现人要狗、狗打人事件
优化2--把bite、attack放入dog、person的内部;函数内部去掉一个参数,形成闭包
注意:为何要引入Person函数--创建模板,要求必须具有这个属性,为何要放入内部---确定谁能调用
1 # 函数 基础数据类型 循环 文件处理 模块 2 # 游戏公司 3 # 人狗大战 4 # 两个角色 5 # 人 6 # 昵称 7 # 性别 8 # 生命值 9 # 战斗力 10 # 背包 11 # 狗 12 # 昵称 13 # 品种 14 # 生命值 15 # 战斗力 16 def Person(name,sex,hp,dps): # 人模子 17 dic = {‘name‘:name,‘sex‘:sex,‘hp‘:hp,‘dps‘:dps,‘bag‘:[]} 18 def attack(dog): 19 dog[‘hp‘] -= dic[‘dps‘] 20 print(‘%s打了%s,%s掉了%s点血,剩余%s点血‘ % (dic[‘name‘], dog[‘name‘], dog[‘name‘], dic[‘dps‘], dog[‘hp‘])) 21 dic[‘attack‘] = attack #注意位置 22 return dic 23 def Dog(name,kind,hp,dps): # 狗模子 24 dic = {‘name‘:name,‘kind‘:kind,‘hp‘:hp,‘dps‘:dps} 25 def bite(person): 26 person[‘hp‘] -= dic[‘dps‘] 27 print(‘%s咬了%s,%s掉了%s点血,剩余%s点血‘ % (dic[‘name‘], person[‘name‘], person[‘name‘], dic[‘dps‘], person[‘hp‘])) 28 dic[‘bite‘] = bite 29 return dic 30 alex = Person(‘alex‘,‘不详‘,250,5) 31 ha2 = Dog(‘哈士奇‘,‘藏獒‘,15000,200) 32 # 人打狗 33 print(alex) 34 print(ha2) 35 print(alex[‘attack‘]) #<function Person.<locals>.attack at 0x00000000021C99D8> 调用函数返回内存地址。。。 36 alex[‘attack‘](ha2) #执行函数 37 print(ha2) 38 39 40 # 面向对象的编程思想 41 # 人狗大战 42 # 创建一个人 43 # 创建一个狗 44 # 人打狗 —— 函数 45 # 狗咬人 —— 函数 46 47 # 造模子 —— 面向对象 48 # 规范了一类角色的属性项目、属性的名字、技能、技能的名字 49 # 权限 有一些函数 只能是这个角色才能拥有 才能调用
2.初识类的语法
类:具有相同属性和相同动作的一类事物 组成一个类 是抽象的
对象: 具体的某一个具有实际属性 和具体动作的一个实体 是具体的
类被创造出来 就是模子 是用来描述对象的
写法: class 类名: 静态属性=None def 动态属性(self): #在类中的方法的一个默认的参数,但也只是一个形式参数,约定必须叫self pass 注:只要是写在类名中的名字 不管是变量还是函数名 都不能在类的外部直接调用 只能通过类名来使用它
类名的第一个功能---查看静态属性
类名.静态属性 可以增删改查
1 # print(类名.静态属性) # 查看 2 # 类名.静态属性 = 456 # 修改 3 # print(类名.静态属性) 4 # 类名.静态属性2 = ‘abc‘# 增加 5 # print(类名.静态属性2) 6 # # del 类名.静态属性2 #删除 7 # # print(类名.静态属性2)
类名.__dict__ 传值!!! 类中必要的默认值之外 还记录了程序员在类中定义的所有名字
类名可以查看某个方法,但是一般情况下,我们不直接使用类名来调用方法
类名.动态属性 ---只能查看,不能修改
类名的第二个功能---实例化(创造对象) 对象=类名()
一般 函数第一个字母小写,类名的第一个字母大写
class Person:pass
1 # alex = Person() 2 # 对象 = 类名() 3 # print(alex) # object 4 # print(Person) 5 # alex name hp dps bag sex 6 # print(alex.__dict__) 7 # # alex.__dict__[‘name‘] = ‘alex‘ 8 # # alex.__dict__[‘sex‘] = ‘不详‘ 9 # # alex.__dict__[‘hp‘] = 250 10 # # alex.__dict__[‘dps‘] = 5 11 # # alex.__dict__[‘bag‘] = [] 12 # # print(alex.__dict__) 13 # alex.name = ‘alex‘ # 给alex对象添加属性 14 # alex.hp = 250 15 # alex.dps = 5 16 # alex.sex = ‘不详‘ 17 # alex.bag = [] 18 # print(alex.__dict__)
1 # class Person: 2 # def __init__(self,name,hp,dps,sex): 3 # self.name = name 4 # self.hp = hp 5 # self.dps = dps 6 # self.sex = sex 7 # self.bag = [] 8 # 9 # alex = Person(‘alex‘,250,5,‘N/A‘) 10 # print(‘alex : ‘,alex) 11 # print(alex.__dict__) 12 # print(alex.name)
# 为什么会执行init中的内容? # self到底是什么? # 实例化的过程 # 类名()就是实例化 # 在实例化的过程中 发生了很多事情是外部看不到的 # 1.创建了一个对象 # 2.自动调用__init__方法 # 这个被创造的对象会被当做实际参数传到__init__方法中,并且传给第一个参数self # 3.执行init方法中的内容 # 4.自动的把self作为返回值 返回给实例化的地方
def init之后,一般定义默认要传值的变量,可在外部调用啦
人狗例子kv的改成.的
1 # class Person: 2 # def __init__(self,name,hp,dps,sex): 3 # self.name = name 4 # self.hp = hp 5 # self.dps = dps 6 # self.sex = sex 7 # self.bag = [] 8 # def attack(self,dog): 9 # dog.hp -= self.dps 10 # print(‘%s打了%s,%s掉了%s点血,剩余%s点血‘ % (self.name, dog.name, dog.name, self.dps, dog.hp)) 11 # 12 # class Dog: 13 # def __init__(self,name,kind,hp,dps): 14 # self.name = name 15 # self.hp = hp 16 # self.dps = dps 17 # self.kind = kind 18 # 19 # def bite(self,person): 20 # person.hp -= self.dps 21 # print(‘%s打了%s,%s掉了%s点血,剩余%s点血‘ % (self.name, person.name, person.name, self.dps, person.hp)) 22 # 23 # alex = Person(‘alex‘,250,5,‘N/A‘) 24 # ha2 = Dog(‘哈士奇‘,‘藏獒‘,15000,200) 25 # ha2.bite(alex) 26 27 # 简化的方式 28 # alex.attack(ha2) # Person.attack(alex) 29 # alex.attack(ha2) # Person.attack(alex) 30 # print(alex.attack(ha2)) # Person.attack(alex) 31 # print(ha2.hp) 32 # print(‘alex : ‘,alex) 33 # print(alex.__dict__) 34 # print(alex.name)
小结# 对象名.方法名 相当于调用一个函数,默认把对象名作为第一个参数传入函数
# 剩余的其他参数根据我的需求可以随意传
1 # 已知半径 计算圆形的面积和周长 面向对象的思想完成 2 # 类 圆 3 # 属性 半径 4 # 方法 计算面积 计算周长 计算直径 5 # pi * r ** 2 6 # 2*pi*r 7 # from math import pi 8 # class Circle: 9 # def __init__(self,r): 10 # self.r = r 11 # def area(self): 12 # return pi * self.r ** 2 13 # def perimeter(self): 14 # return self.r *pi * 2 15 # def r2(self):pass 16 # c1 = Circle(5) 17 18 # print(‘面积是:‘,c1.area()) 19 # print(‘周长是:‘,c1.perimeter())
面向对象的好处:每一个角色都有属于自己的属性和方法;高可扩展性 可读性 规范性
缺点:结局不可控--玩家可控制
类和对象都有自己的命名空间,对象能访问类的命名空间,类不能访问对象的命名空间
两个实例化例子,,小结
1 # class Person: 2 # COUNTRY = ‘中国人‘ # 静态属性 3 # def __init__(self,name): 4 # self.name = name 5 # def eat(self): 6 # print(‘%s在吃泔水‘%self.name) 7 # 8 # alex = Person(‘alex‘) 9 # egon = Person(‘egon‘) 10 # 11 # print(alex.name) 12 # print(egon.name) 13 # print(alex.COUNTRY) 14 # alex.eat() # Person.eat(alex) 15 # alex ---> Person 16 # 当一个类在创建一个实例的时候 就产生了一个这个实例和类之间的联系 17 # 可以通过实例 对象 找到实例化它的类 18 # 但是 类不能找到它的实例化
升级 修改静态属性 局部改变。。在访问变量的时候,都先使用自己命名空间中的,如果自己的空间中没有,再到类的空间中去找
在使用对象修改静态变量的过程中,相当于在自己的空间中创建了一个新的变量;
在类的静态变量的操作中,应该使用类名来直接进行操作,就不会出现乌龙问题
3种国籍的修改结果例子
1 class Person: 2 COUNTRY = [‘中国人‘] # 静态属性 3 Country = ‘中国人‘ # 静态属性 4 def __init__(self,name): 5 self.name = name 6 def eat(self): 7 print(‘%s在吃泔水‘%self.name) 8 alex = Person(‘alex‘) 9 egon = Person(‘egon‘) 10 # print(alex.Country) 11 # alex.Country = ‘印度人‘ 12 # print(alex.Country) 13 # print(egon.Country) 14 # print(Person.Country) 15 结果:# 中国人 16 # 印度人 17 # 中国人 18 # 中国人 19 20 # alex.COUNTRY[0] = ‘印度人‘ 21 # print(alex.COUNTRY) 22 # print(egon.COUNTRY) 23 # print(Person.COUNTRY) 24 # alex.COUNTRY = [‘印度人‘] 25 # print(egon.COUNTRY) 26 # print(Person.COUNTRY) 27 结果: 28 [‘印度人‘] 29 [‘印度人‘] 30 [‘印度人‘] 31 [‘印度人‘] 32 [‘印度人‘] 33 34 # 在访问变量的时候,都先使用自己命名空间中的,如果自己的空间中没有,再到类的空间中去找 35 # 在使用对象修改静态变量的过程中,相当于在自己的空间中创建了一个新的变量 36 # 在类的静态变量的操作中 应该使用类名来直接进行操作 就不会出现乌龙问题
创建一个类 能够自动计算这个类有创建了多少个实例
# class Foo: # count = 0 # def __init__(self): # Foo.count += 1 # # f1 = Foo() # print(Foo.count) # [Foo() for i in range(10)] # print(Foo.count) 结果: 1 11
3.组合
组合:一个类的对象作为另外一个类对象的属性--- 一般是点点的形式
基础数据类型 都是类
# ‘alex‘ : str的对象 # alex.name = ‘alex‘ # alex.name.startswith(‘a‘)
例子:给alex装备一个武器
1 # class Person: 2 # def __init__(self,name,sex,hp,dps): 3 # self.name = name 4 # self.hp = hp 5 # self.dps = dps 6 # self.sex = sex 7 # self.bag = [] 8 # def attack(self,dog): 9 # dog.hp -= self.dps 10 # print(‘%s打了%s,%s掉了%s点血,剩余%s点血‘ % (self.name, dog.name, dog.name, self.dps, dog.hp)) 11 # 12 # class Dog: 13 # def __init__(self,name,kind,hp,dps): 14 # self.name = name 15 # self.hp = hp 16 # self.dps = dps 17 # self.kind = kind 18 # 19 # def bite(self,person): 20 # person.hp -= self.dps 21 # print(‘%s打了%s,%s掉了%s点血,剩余%s点血‘ % (self.name, person.name, person.name, self.dps, person.hp)) 22 # 23 # class Weapon: 24 # def __init__(self,name,price,dps): 25 # self.name = name 26 # self.price = price 27 # self.dps = dps 28 # def kill(self,dog): 29 # dog.hp -= self.dps 30 # 31 # alex = Person(‘alex‘,‘N/A‘,250,5) 32 # ha2 = Dog(‘哈士奇‘,‘藏獒‘,15000,200) 33 # # print(alex.name) 34 # roubaozi = Weapon(‘肉包子‘,600000,10000) 35 # alex.money = 1000000 36 # if alex.money >= roubaozi.price: 37 # alex.weapon = roubaozi 38 # alex.weapon.kill(ha2) 39 # print(ha2.hp)
练习:已知圆形类,运用组合,求圆环的面积和周长
1 # 圆形类 --> 圆环类 2 # 已知圆形类 的基础上 运用组合 求圆环的面积和周长 3 # 一个类的对象给另一个类对象当属性 4 5 # 圆环 6 # 圆 7 # 圆环的面积 8 9 from math import pi 10 class Circle: 11 def __init__(self,r): 12 self.r = r 13 def area(self): 14 return pi * self.r ** 2 15 def perimeter(self): 16 return self.r *pi * 2 17 18 class Ring: 19 def __init__(self,outside_r,inside_r): 20 self.out_circle = Circle(outside_r) 21 self.in_circle = Circle(inside_r) 22 def area(self): 23 return self.out_circle.area() - self.in_circle.area() 24 def perimeter(self): 25 return self.out_circle.perimeter() + self.in_circle.perimeter() 26 27 r = Ring(10,5) 28 print(r.area()) 29 print(r.perimeter())
组合 是描述了一种什么有什么的关系,eg:圆环有圆、人有武器
?。。。
小结。。
交互:人打狗、狗咬人
实例找类。。。看博客例子
4.继承
面向对象的三大特性 继承 多态 封装
继承
为何会有继承? ---解决代码的冗余问题
父类 基类 超类---Parent类
子类 派生类---Son类
单继承
1 class Parent: 2 pass 3 4 class Son(Parent): #Son类继承Parent类 5 pass 6 7 8 class Parent1: 9 pass 10 class Parent2: 11 pass 12 class Son(Parent1,Parent2): #Son类继承Parent类 13 pass
多继承:多个父类
构建时:先想到对象,子类,最后父类
人狗例子!!--图!
1 # class Animal: 2 # def __init__(self, name, hp, dps): 3 # self.name = name 4 # self.hp = hp 5 # self.dps = dps 6 # def eat(self): 7 # print(‘%s吃药回血了‘%self.name) 8 # class Person(Animal): 9 # def __init__(self, name, hp, dps,sex): 10 # super().__init__(name,hp,dps) # Animal.__init__(self,name,hp,dps) 11 # self.sex = sex # 派生属性 12 # def attack(self,dog): 13 # dog.hp -= self.dps 14 # print(‘%s打了%s,%s掉了%s点血,剩余%s点血‘ % (self.name, dog.name, dog.name, self.dps, dog.hp)) 15 # 16 # class Dog(Animal): 17 # def __init__(self,name,hp,dps,kind): 18 # super().__init__(name, hp, dps) # Animal.__init__(self, name, hp, dps) 19 # self.kind = kind # 派生属性 20 # def bite(self,person): 21 # person.hp -= self.dps 22 # print(‘%s打了%s,%s掉了%s点血,剩余%s点血‘ % (self.name, person.name, person.name, self.dps, person.hp)) 23 # alex = Person(‘alex‘,250,5,‘N/A‘) 24 # ha2 = Dog(‘哈士奇‘,15000,200,‘藏獒‘) 25 # print(alex.__dict__) 26 # print(ha2.__dict__) 27 # ha2.eat() 28 # alex.eat() 29 # ha2.bite(alex) 30 # alex.attack(ha2) 31 # 对象的内存空间 - 创建这个对象的类的内存空间 - 父类的
实例化发生的时候,1.创建了一个对象2.把子类创建的对象传给...5...
继承的特征:先找对象的内存空间--创建这个类的对象的内存空间--父类的内存空间
注意:加sex时,需要对sex赋值--派生属性
强制调用--图!
简单写法super().__init__(name,hp,dps) #不写self
子类中不同位置赋值,结果不一样,取最后赋值的值
面试题:in son例子
1 # class Foo: 2 # def __init__(self): 3 # self.func() 4 # def func(self): 5 # print(‘in Foo‘) 6 # 7 # class Son(Foo): 8 # def func(self): 9 # print(‘in Son‘) 10 # Son()
抽象类与接口类--可先忽略--java实用
钻石继承 继承顺序,小乌龟继承顺序--广度优先算法 -->
print(D.mro()) #查看顺序
python两种类:
经典类 python3已经灭绝了,py2还存在,在py2中只要程序员不主动继承object,这个类就是经典类。遵循深度优先算法(一条路走到黑)
新式类 python3所有的类都是新式类,所有的新式类都继承object--在多继承中遵循广度优先算法
讨论题:都加super b+super,,找到c!!
1 # class A: 2 # def f(self): 3 # print(‘in A‘) 4 # 5 # class B(A): 6 # def f(self): 7 # print(‘in B‘) 8 # super().f() 9 # 10 # class C(A): 11 # pass 12 # def f(self): 13 # print(‘in C‘) 14 # super().f() 15 # 16 # class D(B,C): 17 # def f(self): 18 # print(‘in D‘) 19 # super().f() 20 # 21 # d = D() 22 # d.f() 23 D-B-C-A
1 # class A: 2 # def f(self): 3 # print(‘in A‘) 4 # 5 # class B(A): 6 # pass 7 # # def f(self): 8 # # print(‘in B‘) 9 # 10 # class C(A): 11 # pass 12 # # def f(self): 13 # # print(‘in C‘) 14 # 15 # 16 # class D(B,C): 17 # pass 18 # # def f(self): 19 # # print(‘in D‘) 20 # 21 # class E(C): 22 # pass 23 # # def f(self): 24 # # print(‘in B‘) 25 # 26 # class F(D,E): 27 # pass 28 # # def f(self): 29 # # print(‘in C‘) 30 # 31 # # d = D() 32 # # d.f() 33 # 34 # print(F.mro())
F-D-B-E-C-A
super和找父类是两件事
在单继承中 super就是找父类
在多级继承中 super的轨迹 是根据整个模型的起始点而展开的一个广度优先顺序 ,遵循mro规则的
小结。。
继承小结
继承的作用
减少代码的重用 提高代码可读性 规范编程模式
几个名词
抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。 继承:子类继承了父类的方法和属性 派生:子类在父类方法和属性的基础上产生了新的方法和属性
抽象类与接口类
1.多继承问题 在继承抽象类的过程中,我们应该尽量避免多继承; 而在继承接口的时候,我们反而鼓励你来多继承接口 2.方法的实现 在抽象类中,我们可以对一些抽象方法做出基础实现; 而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
钻石继承
新式类:广度优先 经典类:深度优先
5.多态 了解,不常用
在python中处处都是多态
java中是强数据类型的,传值时指定数据类型--在java中应用
在python中,数据类型:类 例子!
1 # 在python中处处都是多态 2 3 # 多态 4 # java 5 # class Person():pass 6 # 7 # alex = Person() 8 # print(type(alex)) # Person 9 # print(type(‘123‘)) 10 # print(type(123)) 11 12 # def func(Dog person): 13 # pass 14 # 15 # func(ha2) 16 17 # class Animal: 18 # pass 19 # 20 # class Dog(Animal):pass 21 # class Person(Animal):pass 22 # 23 # 24 # def func(a): 25 # pass 26 # 27 # func(alex) 28 # func(ha2)
以上是关于six day--面向对象的主要内容,如果未能解决你的问题,请参考以下文章