six day--面向对象
分类:
IT文章
•
2023-11-20 19:11:24
一、复习模块
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 # 三个模块+序列化 未讲
View Code
二、面向对象
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
# 为什么会执行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 # 但是 类不能找到它的实例化
View Code
升级 修改静态属性 局部改变。。在访问变量的时候,都先使用自己命名空间中的,如果自己的空间中没有,再到类的空间中去找
在使用对象修改静态变量的过程中,相当于在自己的空间中创建了一个新的变量;
在类的静态变量的操作中,应该使用类名来直接进行操作,就不会出现乌龙问题
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 # 在类的静态变量的操作中 应该使用类名来直接进行操作 就不会出现乌龙问题
View Code
创建一个类 能够自动计算这个类有创建了多少个实例
# 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
View Code
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)
alex开挂买武器版-人狗大战
练习:已知圆形类,运用组合,求圆环的面积和周长
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.把我创建的对象传给__init__
3.把子类创建的对象传给父类init的self
4.执行self.5.把self返回给alex

继承的特征:先找对象的内存空间--创建这个类的对象的内存空间--父类的内存空间
注意:加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()
inson
抽象类与接口类--可先忽略--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)
多态