【python面向对象】继承与多态(二)

【python面向对象】继承与多态(二),第1张

文章目录
  • 内置可重写函数
    • __str__函数
    • __repr__函数
    • 练习
  • 运算符重载
    • 定义
  • 多继承
  • 面向对象设计思想补充
    • 里氏替换(继承后的重写)
    • 迪米特法则(类与类交互的原则)
  • 总结


内置可重写函数

Python中,以双下划线开头、双下划线结尾的是系统定义的成员。我们可以在自定义的类中进行重写,从而
类中进行重写,从而改变其行为。

__str__函数

__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
不要和陌生人说话。
类与类交互时,在满足功能要求的基础上,传递的数据量越少越好。因为这样可能降低耦合度。

总结

面向对象:考虑问题从对象的角度出发,让程序变得灵活。
抽象:从多个事物中,舍弃个别的/非本质的特征(不重要),抽出共性(重要的)的本质过程。
三大特征∶

  1. 封装:将每个变化点单独分解到不同的类中。
例如:老张开车去东北
做法:定义人类,定义车类。
  1. 继承:重用现有类的功能和概念,并在此基础上进行扩展。(统一概念,代码复用)
例如:图形管理器,统计圆形/矩形....面积。
做法:用图形类代表/约束,圆形/矩形..具有计算面积的方法。
  1. 多态:调用父"抽象的"方法,执行子类"具体的"方法。
    重写:覆盖父类那个比较抽象的方法。
例如:图形管理器调用图形的计算面积方法,具体图形必须重写图形的计算面积方法。

继承是共性(计算面积),多态是个性(长 * 宽 / pi * i ** 2)。
设计原则:

  1. 开闭原则:允许增加新功能﹐不允许修改客户端代码。
  2. 单一职责:一个有且只有一个改变的原因。
  3. 依赖倒置:调用抽象(父),不要调用具体(子)
    抽象不要依赖具体。
  4. 组合复用:如果仅仅是代码的复用,优先使用组合。
  5. 里氏替换
  6. 迪米特法则

类与类关系
泛化(继承):泛化(从具体到抽象)、继承(从抽象到具体)
组合:关联(做成成员变量)
组合:依赖(做成方法参数)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/874593.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存