• Three---面向对象与面向过程/属性和变量/关于self/一些魔法方法的使用/继承/super方法/多态


    python的面向对象

    面向对象与面向过程

    面向过程

    • 面向过程思想:需要实现一个功能的时候,看重的是开发的步骤和过程,每一个步骤都需要自己亲力亲为,需要自己编写代码(自己来做)

    面向对象

    • 面向对象的三大特征:封装性、继承性、多态性
    • 面向对象思想:需要实现一个功能的时候,看重的并不是过程和步骤,而是关心谁帮我做这件事(偷懒,找人帮我做)

    类与对象

    • 对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另一个新的概念——类
    • 类:抽象的,是一张“手机设计图”
    • 对象:具体的,是一个“真正的手机实例”
    • 类是抽象的,在使用的时候通常会找到这个类的一个具体的存在;一个类可以找到多个对象
    #学生案例
    class Student():   #创建一个学生类
        #定义一个info函数,并传参至self本身
        def info(self,name,age,sex):   
            print('学生的姓名是:',self.name)
            print('学生的年龄是:',self.age)
            print('学生的性别是:',self.sex)
    
    yinianji = Student()   #创建一个具体的对象:一年级
    yinianji.info()   #实例化对象调用定义的info函数
    

    案例

    当创建一个对象时,就是用一个模子来制造一个实物

    #案例
    class Dog():   #定义一个类的形式
    
        #info是一个实例方法,类对象可以调用实例方法,实例方法的第一个参数一定是self
    
        def info(self):
        
        #当对象调用实例化方法时,python会自动将对象本身的引用作为参数,传递到实例方法的第一个参数self里面
            print(self)
            print("狗祖宗")
    
    #Dog这个类实例化了一个对象 jinmao
    jinmao = Dog()
    
    #对象调用实例化方法info(),执行info()中封装的代码 .表示选择属性或方法
    jinmao.info()
    
    #打印对象,则默认打印对象在内存中的地址,结果等同于info中的print(self)
    print(jinmao)
    
    #id(taidamier)则时内存地址的十进制形式表示
    print(id(jinmao))
    -----------------------------------------------------------
    <__main__.Dog object at 0x00000190A9DC67F0>
    狗祖宗
    <__main__.Dog object at 0x00000190A9DC67F0>
    1720836712432
    

    属性和变量

    属性和变量的区别

    1. 属性:指某个对象的具体特性
    2. 变量:指可以更改的量

    属性和变量的判断依据

    • 根据宿主判断:变量无宿主,属性有宿主
    • 根据宿主的不同又分为对象属性以及类属性

    对象属性获取

    • 对象既然有实例方法,也可以有自己的属性
    • 在方法内通过self获取对象属性
    #对象属性获取
    class Dog():   #定义一个狗类
    
        def move(self):    #移动实例方法
            print("moving...")
    
        def attack(self):   #咬人实例方法
            print("咬人")
    
    #实例化一个狗对象 jinmao
    jinmao = Dog()
    
    #给对象添加属性,以及对应的属性值
    jinmao.name = "xiao"
    jinmao.hp = 200
    jinmao.atk = 40
    jinmao.armor = 100
    
    #通过.成员选择运算符,获取对象的属性值
    print("%s 的生命值为:%d" %(jinmao.name,jinmao.hp))
    print("%s 的攻击力为:%d" %(jinmao.name,jinmao.atk))
    print("%s 的护甲值为:%d" %(jinmao.name,jinmao.armor))
    
    #通过.成员选择运算符,获取对象的实例方法
    jinmao.move()
    jinmao.attack()
    -----------------------------------------------------------
    xiao 的生命值为:200
    xiao 的攻击力为:40
    xiao 的护甲值为:100
    moving...
    咬人
    

    关于self

    • self就是实例化对象本身
    #关于self
    class A:
        def f(self,data):
            print(self.name)
            print(data)
    
    o = A()
    
    print(A.f)
    print(o.f)
    -----------------------------------------------------------
    0x000002725D28ADC0>
    object at 0x000002725D2467F0>>
    
    • 其中A.f对应的时function 即为一个普通的函数
    • o.f为bound method 即在函数上绑定了一个对象 —— o
    • 结论:o.f 是返回了一个method object ,而当去调用这个object时,他会记住被创建时绑定的对象,即返回该对象,默认参数为self

    魔法方法

    魔法方法__init__()

    __init__方法可以在创建对象时就拥有一些属性,__init__通常用来做属性初始化 或 赋值 操作

    • 如果类没有写__init__方法,python会自动创建,但不会执行任何操作
    • 所以一个类里无论自己是否编写__init__方法 都一定有__init__方法
    案例一
    #init方法
    class Dog():
    #方法,用来做变量初始化 或 赋值 操作,在类实例化对象的时候,会被自动调用
        def __init__(self,name,hp) -> None:
            #__init__方法也可以带参数
            self.name = name
            self.hp = hp
            print(self.name,self.hp)
    
    #实例化一个对象,并自动调用__init__方法
    xiaohuang = Dog("小黄",200)
    ---------------------------------------------------------
    class Dog():
    
        def f(self,name,hp):
            self.name = name
            self.hp = hp
            print(self.name,self.hp)
            
    xiaohuang = Dog()
    xiaohuang.f("小黄",200)
    
    案例二
    #init方法二
    class Dog():
        
        def __init__(self,name,skill,hp) -> None:
            
            self.name = name
            self.skill = skill
            self.hp = hp
            
        def move(self):
            print("%s 正在前往事发地点..." % self.name)
    
        def attack(self):
            print("%s 咬人 %s..."%(self.name,self.skill))
    
        def info(self):
            print("%s 的生命值:%d"%(self.name,self.hp))
    
    #实例化对象时,参数会传递到对象的__init__()方法中
    jinmao = Dog("金毛","连环咬",200)
    hashiqi = Dog("哈士奇","不松口",300)
    
    #直接输出对象即为地址
    print(jinmao)
    print(hashiqi)
    
    #不同对象的属性值的单独保存
    print(id(jinmao.name))
    print(id(hashiqi.name))
    
    #同一个类的不同对象,实例方法共享
    print(id(jinmao.attack))
    print(id(hashiqi.attack))
    -----------------------------------------------------------
    <__main__.Dog object at 0x000001A3209367F0>
    <__main__.Dog object at 0x000001A32089F250>
    1800138028976
    1800138029168
    1800131850880
    1800131850880
    

    总结

    • 在类内部获取 属性 和 实例方法,通过self获取
    • 在类外部获取 属性 和 实例方法,通过对象名获取
    • 如果有一个类有多个对象,每个对象的属性时各自保存的,都有各自独立的地址
    • 实例方法时所有对象共享的,只占用一份内存空间
    • 类会通过self来判断是哪个对象,调用了实例方法

    魔法方法__str__()

    该方法用来显示信息,通过一个字符串来描述实例对象,该方法需要return一个数据,并且只有self一个参数,在类的外部时用print(对象)打印这个数据(面向用户)

    #str方法
    class Person():
    
        def __init__(self,name,age):
    
            self.name = name
    
            self.age = age
    
        def __str__(self):
    
            return "此人姓名为%s,此人的年龄为%s"%(self.name,self.age)
    
    p1 = Person("李四",18)
    
    P2 = Person("王五",19)
    
    print(p1)
    print(P2)
    -------------------------------------------------------------
    此人姓名为李四,此人的年龄为18
    此人姓名为王五,此人的年龄为19
    
    触发方式:
    1、直接通过print函数去打印
    2、通过出发str函数进行转换
    

    魔法方法__repr__()

    通过一个字符串描述实例对象的信息(面向开发人员)

    #repr方法
    class Person():
    
        def __init__(self,name,age):
    
            self.name = name
    
            self.age = age
    
        def __str__(self):
    
            return "此人姓名为%s,此人的年龄为%s"%(self.name,self.age)
    
    p1 = Person("李四",18)
    
    P2 = Person("王五",19)
    
    print(repr(p1))
    print(P2)
    -------------------------------------------------------------
    <__main__.Person object at 0x000001E7D9FD67F0>
    此人姓名为王五,此人的年龄为19
    
    #修改repr值
    class Person():
    
        def __init__(self,name,age):
    
            self.name = name
    
            self.age = age
    
        def __str__(self):
    
            return "此人姓名为%s,此人的年龄为%s"%(self.name,self.age)
    
        def __repr__(self):   #更改repr参数值
    
            return "self"
    
    p1 = Person("李四",18)
    
    P2 = Person("王五",19)
    
    print(repr(p1))
    print(repr(P2))
    print(P2)
    -------------------------------------------------------------
    self
    self
    此人姓名为王五,此人的年龄为19
    

    repr与str

    在输出值时当存在str方法便会优先输出str,repr可以面向开发者,同样repr方法也可以作为一种方法去输出str

    #repr与str
    import datetime
    
    t = datetime.datetime.now()
    
    print(t)   #此处输出的为datetime库中的类对应的str字符串
    
    print(repr(t))   #同时输出repr进行对比
    -------------------------------------------------------------
    2022-07-15 23:53:55.418332   #此为对应字符串输出值
    
    datetime.datetime(2022, 7, 15, 23, 53, 55, 418332)   #此为repr值
    
    #通过eval函数输出repr
    import datetime
    
    t = datetime.datetime.now()
    
    print(t)   #此处输出的为datetime库中的类对应的str字符串
    
    tmp = repr(t)
    
    result = eval(tmp)   #使用eval函数执行输出repr值的t
    
    print(result)
    -------------------------------------------------------------
    2022-07-16 00:00:31.144619
    2022-07-16 00:00:31.144619
    

    魔法方法__del__()

    创建对象后,python解释器默认调用__init__()方法

    当删除一个对象时,python解释器也会默认调用一个方法,这个方法叫__del__()

    #del方法
    
    class Dog():
        #创建对象后__init__方法会自动被调用
        def __init__(self, name):
            print("__init__方法被调用",name+"出生了")
            self.name = name
    
        #当对象执行完毕被删除时,__del__方法会自动被调用
        def __del__(self):
            print("__del__方法被调用%s死了"%(self.name))
    
    
    jinmao = Dog("金毛")
    ---------------------------------------------------------
    __init__方法被调用 金毛出生了
    __del__方法被调用金毛死了
    

    继承

    • 子类可以重写父类的属性和方法后,依然可以调用父类的属性和方法
    • 使用super方法调用父类
    • 多层继承关系同样可以实现
    • 装饰器
    class Dog():   #创建父类Dog
        
        def __init__(self) -> None:
            self.name = "dog dad"
        def skill_dad1(self):
            print("attack people")
    
    class Dog2():   #创建父类Dog2
    
        def __init__(self) -> None:
            self.name = "dog mom"
        def skill_mom1(self):
            print("attack dog")
        def skill_mom2(self):
            print("摇尾巴")
    
    class Son(Dog,Dog2):   
    #创建子类Son并继承父类Dog和Dog2,继承时优先继承第一个父类Dog
    
        def __init__(self) -> None:
            self.name = "dog son"
        def skill(self):
            print("lick people")
        def dad_skill(self):    
            #通过super方法进行调用父类所定义的函数与方法
            super().__init__()   
            super().skill_dad1()
        def mom_skill(self):
            super().__init__()
            super().skill_mom1()
            super().skill_mom2()
        
    
    jinmao = Son()
    jinmao.dad_skill()
    jinmao.mom_skill()
    --------------------------------------------------------------
    attack people
    attack dog
    摇尾巴
    

    多态

    • 不同的子对象调用相同的父类放啊,产生不同的结果(继承+重写)
    • 一个父类可以拥有多个子类继承
    #多态
    class Dog():
        def __init__(self) -> None:
            self.name = "dog mom"
    
        def skill(self):
            print("attack dog")
    
    #子类/派生类
    class Son1(Dog):
        def skill(self):
            print("attack man")
    
    class Son2(Dog):
        def skill(self):
            print("attack woman")
    
    class Son3(Dog):
        def skill(self):
            print("attack child")
    
    #实例化
    son1 = Son1().skill()
    son2 = Son2().skill()
    son3 = Son3().skill()
    ---------------------------------------------------------
    attack man
    attack woman
    attack child
    
  • 相关阅读:
    java检测当前CPU负载状态的方法
    阅读笔记——A Frustratingly Easy Approach for Entity and Relation Extraction
    Qframework 中超级方便的kitres
    mysql索引不生效
    zkPoT:基于机器学习模型训练的ZKP
    Hqst百兆网络变压器H81601S高频参数 IR插入损耗 RL回波损耗 CTK串扰 CMRR共模抑制 实测值
    水质查询接口
    [Jenkins] Docker 安装Jenkins及迁移流程
    Elasticsearch入门-环境安装ES和Kibana以及ES-Head可视化插件和浏览器插件es-client
    资金变动语音通知怎么实现?
  • 原文地址:https://www.cnblogs.com/311dih/p/16583840.html