- 内置可重写函数
- __str__函数
- __repr__函数
- 练习
- 运算符重载
- 定义
- 多继承
- 面向对象设计思想补充
- 里氏替换(继承后的重写)
- 迪米特法则(类与类交互的原则)
- 总结
内置可重写函数
Python中,以双下划线开头、双下划线结尾的是系统定义的成员。我们可以在自定义的类中进行重写,从而
类中进行重写,从而改变其行为。
__str__函数:将对象转换为字符串(对人友好的)。
class StudentModel:
"""
学生模型
"""
def __init__(self,name="",age=0,score=0,id=0):
self.name = name
self.age = age
self.score = score
self.id = id
# 对象-->字符串(随意格式)
def __str__(self):
return "我叫%s,编号是%d ,年龄是%d ,成绩是:%d"%(self.name,self.id,self.age,self.score)
s01 = StudentModel("无忌",27,100,101)
str01 = str(s01)
print(str01)#我叫无忌,编号是101 ,年龄是27 ,成绩是:100
print(s01)#我叫无忌,编号是101 ,年龄是27 ,成绩是:100
__repr__函数
__repr__函数:将对象转换为字符串(解释器可识别的)。
"""
内置可重写函数
"""
class StudentModel:
"""
学生模型
"""
def __init__(self,name="",age=0,score=0,id=0):
self.name = name
self.age = age
self.score = score
self.id = id
# 对象-->字符串(随意格式)
def __str__(self):
return "我叫%s,编号是%d ,年龄是%d ,成绩是:%d"%(self.name,self.id,self.age,self.score)
# 对象-->字符串(解释器可识别,有格式)
def __repr__(self):
return "StudentModel('%s',%d,%d,%d)" % (self.name,self.age, self.score,self.id)
s01 = StudentModel("无忌",27,100,101)
str01 = str(s01)
print(str01)#我叫无忌,编号是101 ,年龄是27 ,成绩是:100
print(s01)#我叫无忌,编号是101 ,年龄是27 ,成绩是:100
str02 = repr(s01)
print(str02)
#根据字符串执行python代码
re = eval("1+2*5")
print(re)#11
#克隆对象
#repr返回python格式的字符串
#eval根据字符串执行代码
s02 = eval(repr(s01))
print(s02.name)#无忌
s02.name = "老张"
print(s01.name)#无忌
print(s02.name)#老张
练习
创建Enemy类对象,将对象打印在控制台中(格式自定义)。
克隆Enemy类对象,体会克隆对象变量的改变不影响原对象。
class Enemy:
def __init__(self,name,attack,hp,defense):
self.name = name
self.attack =attack
self.hp = hp
self.defense = defense
def __str__(self):
return "敌人的名字:%s,敌人的攻击力:%d,敌人的生命值:%d,敌人的防御值:%d"%(self.name,self.attack,self.hp,self.defense)
def __repr__(self):
return "Enemy('%s',%d,%d,%d)" % (self.name, self.attack, self.hp, self.defense)
e01 = Enemy("张三",100,200,100)
print(str(e01))
r01 = Enemy("李四",100,200,100)
e02 = eval(repr(r01))
print(e02.name)
运算符重载
定义
让自定义的类生成的对象(实例)能够使用运算符进行 *** 作。
"""
运算符重载
"""
class Vector1:
def __init__(self,x):
self.x = x
def __str__(self):
return "一维向量的分量是:"+str(self.x)
def __add__(self,other):
return Vector1(self.x + other)
def __radd__(self,other):
return Vector1(self.x + other)
def __iadd__(self,other):
self.x += other
return self
v01 = Vector1(10)
print(v01 + 2)#v01.__add__(2)#一维向量的分量是:12
print (2+ v01)#v01.__radd__(2)#一维向量的分量是:12
print(id(v01))#1842544712336
#重写__iadd__,实现在原对象基础上的变化。
#如果重写__iadd__,默认使用__add__,一般会产生新对象。
v01 += 2
print(v01,id(v01))#一维向量的分量是:12 1842544712336
list01 =[1]
print(id (list01))#2062509301504
#生成新对象
re = list01 +[2]
print(re, id(re))#[1, 2] 2062510616320
#在原有对象基础上,累加.
list01 += [2]
print(list01 , id (list01))#[1, 2] 2062509301504
多继承
- 父类(基类、超类)、子类(派生类)。
- 父类相对于子类更抽象,范围更宽泛;子类相对于父类更具体,范围更狭小。
- 单继承:类只有一个(例如Java,C#)。
- 多继承:父类有多个(例如C++,Python)。
- Object类:任何类都直接或间接继承自object类。
- 多继承语法:
类自身–>父类继承列表(由左至右)–>再上层父类
D–>B–>C–>A
"""
多继承 -- 语法
MRO:同名方法的解析顺序
"""
class A:
def m01(self):
print("A - m01")
class B(A):
def m01(self):
print("B - m01")
class C(A):
def m01(self):
print("C - m01")
class D(B,C):
def m02(self):
self.m01()
d01 = D()
d01.m02()
#B - m01
#mro():同名方法的解析顺序
print(D.mro())
#[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
面向对象设计思想补充 里氏替换(继承后的重写)
Liskov Substitution Principle
父类出现的地方可以被子类替换,在替换后依然保持原功能。
子类要拥有父类的所有功能。
子类在重写父类方法时,尽量选择扩展重写,防止改变了功能。
Law of Demeter
不要和陌生人说话。
类与类交互时,在满足功能要求的基础上,传递的数据量越少越好。因为这样可能降低耦合度。
面向对象:考虑问题从对象的角度出发,让程序变得灵活。
抽象:从多个事物中,舍弃个别的/非本质的特征(不重要),抽出共性(重要的)的本质过程。
三大特征∶
- 封装:将每个变化点单独分解到不同的类中。
例如:老张开车去东北
做法:定义人类,定义车类。
- 继承:重用现有类的功能和概念,并在此基础上进行扩展。(统一概念,代码复用)
例如:图形管理器,统计圆形/矩形....面积。
做法:用图形类代表/约束,圆形/矩形..具有计算面积的方法。
- 多态:调用父"抽象的"方法,执行子类"具体的"方法。
重写:覆盖父类那个比较抽象的方法。
例如:图形管理器调用图形的计算面积方法,具体图形必须重写图形的计算面积方法。
继承是共性(计算面积),多态是个性(长 * 宽 / pi * i ** 2)。
设计原则:
- 开闭原则:允许增加新功能﹐不允许修改客户端代码。
- 单一职责:一个有且只有一个改变的原因。
- 依赖倒置:调用抽象(父),不要调用具体(子)
抽象不要依赖具体。 - 组合复用:如果仅仅是代码的复用,优先使用组合。
- 里氏替换
- 迪米特法则
类与类关系
泛化(继承):泛化(从具体到抽象)、继承(从抽象到具体)
组合:关联(做成成员变量)
组合:依赖(做成方法参数)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)