• python 第四章面向对象


    1.类和对象的关系

    类和对象的关系就像数据结构和数据的关系一样,类规定了存储什么数据,对象用来实际存储数据

    1.1.对象构建小例子

    """
    1.类的定义和构造
    2.类的方法(函数) 构造 析构
    一般函数的第一个参数是实例对象名,代之需要调用函数的对象,传参时不传入
    3.类的属性(成员) 公有 私有
    """
    
    """
    python 不存在无法访问的私有属性
    如何保持封装的封闭性
    """
    
    class student:
        
        __age=0#私有成员
        
        name=""#公有成员
        Id=""
        
        def __init__(self,name,age,Id):#构造函数
            self.name=name
            self.Id=Id
            self.__age=age
            print("%s同学的信息构造完成"%self.name)
            
        def __del__(self):#析构函数
            print("%s同学的信息被删除"%self.name)
            
        def printf(self):#查看信息
            print("%s同学的年龄为:%s\n学号为:%s"%(self.name,self.__age,self.Id))
            
            
            
    if __name__ == '__main__':
        #信息构造
        stu1=student("李华","21","20212203")
        stu2=student("李明","20","20212204")
        stu3=student("李强","21","20212201")
        
        #信息查看
        stu1.printf()
        stu2.printf()
        stu3.printf()
        
        #在类外调用私有成员要加类名限制(私有成员在类外也是可以定义的)
        print("%s同学的年龄为:%s"%(stu1.name,stu1._student__age))
        
        #信息删除
        stu4=stu1
        
        del stu1#对象信息备份在stu4
        del stu2
        del stu3
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    2.常用内置方法

    2.1 __str__ 方法

    应用场景:当一个类的对象要以字符串的形式使用时要用到此方法;
    举例:复数类
    
    """
    这里的复数对象要当作字符串输出,定义__str__方法实现
    """
    
    class complex:
        def __init__(self,real,image):
            self.real=real
            self.image=image
        
        
        def __str__(self):
            if self.image >=0:
                return str(self.real)+'+'+str(self.image)+'i'
            else:
                return str(self.real)+str(self.image)+'i'
        
        '''
        def __str__(self):
            if self.image >= 0:
                return '{}+{}i'.format(self.real,self.image)
            else:
                return '{}{}i'.format(self.real,self.image)
        '''
    c=complex(-1,2.3)
    print(c)
    c1=c=complex(1,-2.3)
    print(c1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2.2 比较运算内置方法

    应用场景:比较某个类两个对象的某种属性大小,返回逻辑真和逻辑假

    在这里插入图片描述

    举例:比较两个人成绩大小
    """
    定义一个学生类,判断一个同学的成绩是否大于另一个
    感觉有点类似于C++运算符重载
    """
    
    class student:
        def __init__(self,name,score):
            self.score=score
            self.name=name
            
        def __gt__(self,other):
            return self.score>=other.score
        
    stu1=student('李华',78)
    stu2=student('李明',80)
    print('李明的成绩高于李华:',stu2.score>stu1.score)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3 多态前置知识:鸭子类型

    命名的来由:

    “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
    在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。
    鸭子类型使得有相同功能的不同类也能实现多态,这是C++不具备的

    鸭子类型举例:

    """
    在鸭子类型中,关注点在于对象的行为,能作什么;
    而不是关注对象所属的类型。
    """
    class person:
        
        def __init__(self,name,age):
            self.name=name
            self.age=age
            
        def printt(self):
            print('%s的年龄为%d'%(self.name,self.age))
            
    
    class Dog:
        def __init__(self,name,weight):
            self.name=name
            self.weight=weight
        def printt(self):
            print('狗狗%s的体重为%d'%(self.name,self.weight))    
    
    def printt(tmp):
        tmp.printt()
    
    
    c1=person('李华',12)
    c2=Dog('乔治', 100)
    printt(c1)
    printt(c2) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    4.super方法、单继承与多继承、方法重写

    概述

    1.单继承与多继承
    2.方法重写: 方法重写就是在继承中子类对于父类已有的功能进行重写,可以通过鸭子类型实现多态
    3.super: 获取当前类父类的代理对象(一般用于子类构造函数对父类元素赋值)

    实例:

    """
    1.单继承与多继承
    2.方法重写: 方法重写就是在继承中子类对于父类已有的功能进行重写,可以通过父类的引用实现多态
    3.super:  获取当前类父类的代理对象(一般用于子类构造函数对父类元素赋值)
    
    
            学生
    人——>           ——> 助教
            老师
            
            
    """
    
    
    
    
    class person:
        
        def __init__(self,sex,name):
            self.sex=sex;
            self.name=name
            
        def Printinfo(self):
            print('{}的性别为{}'.format(self.name,self.sex))
            
    class student(person):
        def __init__(self,sex,name,sno):
            super().__init__(sex,name)
            self.sno=sno
            
        def Printinfo(self):
            print('{}的性别为{},学号为{}'.format(self.name,self.sex,self.sno))
            
    class teacher(person):
        def __init__(self,sex,name,tno):
            super().__init__(sex,name)
            self.tno=tno    
        
        def Printinfo(self):
            print('{}的性别为{},教师号为{}'.format(self.name,self.sex,self.tno))
            
    class assistant(teacher,person):
        pass
    
    
    def Printinfo(tem):
        tem.Printinfo()
        
    c1=teacher('男', '李华', '11230')
    c2=student('女', '李梅', '12345')
    c3=person('男', '李强')
    Printinfo(c1)
    Printinfo(c2)
    Printinfo(c3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    暂时不知python怎么消除多继承二义性,对于助教类先不扩展

    5.type函数,issubclass函数和isinstance函数

    简介:

    1.isinstance 判断一个类是否是指定类或者是指定类的子类
    2.issubclass 判断一个类是否是另一个类的子类
    3.type()函数 获取一个对象所属的类

    小例子:

    """
    1.isinstance  判断一个类是否是指定类或者是指定类的子类
    2.issubclass  判断一个类是否是另一个类的子类
    3.type()函数  获取一个对象所属的类
    """
    
    class person:
        
        def __init__(self,sex,name):
            self.sex=sex;
            self.name=name
            
    class student(person):
        def __init__(self,sex,name,sno):
            super().__init__(sex,name)
            self.sno=sno
    
            
    class flower:
        def __init__(self,colour):
            self.colour=colour
            
        
    c1=person('男','李明')
    c2=student('女','李华','12345')
    c3=flower('red')
    
    print(type(c1))
    print(type(c2))
    print(type(c3))
    
    print('flower类是person类的子类:',issubclass(flower,person))
    print('flower类是person类的子类:',issubclass(student,person))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    6.类方法与静态方法

    简介:

    当一个属性是类所有而不是每个对象所拥有的时候要定义为类方法或静态方法,二者的区别是静态方法不用 写self,即静态方法并不绑定对象,也就无法修改对象的值

    实例:类方法和静态方法实现复数加法

    # -*- coding: utf-8 -*-
    """
    类方法与静态方法:当类的一个方法是类所有而不是对象的方法时,可以定义为类方法或静态方法
    类方法:@calssmethon               绑定了对象
    静态方法:@staticmethod            未绑定对象
    未绑定对象无法修改对象的值
    """
    
    class complex:
        def __init__(self,real=0,image=0):
            self.real=real
            self.image=image
            
        @classmethod#类方法
        def add1(cls,c1,c2):
            c=complex()
            
            c2.real=3
            
            c.real=c1.real+c2.real
            c.image=c1.image+c2.image
            if c.image >=0:
                return str(c.real)+'+'+str(c.image)+'i'
            else:
                return str(c.real)+str(c.image)+'i'
            
            
            
        @staticmethod#静态方法
        def add2(c1,c2):
            c=complex()
            
            #c2.real=1 在静态方法里修改对象的值无法修改成功
            
            c.real=c1.real+c2.real
            c.image=c1.image+c2.image
            if c.image >=0:
                return str(c.real)+'+'+str(c.image)+'i'
            else:
                return str(c.real)+str(c.image)+'i'
    
            
    c1=complex(1,2)
    c2=complex(2,3)
    c3=complex.add1(c1,c2)
    print(c3)
    c4=complex.add1(c1,c2)
    print(c4)
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    7.动态扩展类和__slots__用法

    简介:

    动态扩展类:在不修改原有类的情况下动态的为类添加新的属性或方法
    1.绑定新方法:需要使用 types 模块的 MethodType 方法
    from types import Mythodtype
    2.绑定新属性:
    可以使用__slots__函数限制可绑定的新属性

    绑定新方法例子

    """
    动态扩展类:在不修改原有类的情况下动态的为类添加新的属性或方法
    1.绑定新方法:需要使用 types 模块的 MethodType 方法
    from types import Mythodtype
    2.绑定新属性:
    可以使用__slots__函数限制可绑定的新属性
    """
    from types import MethodType 
    
    class person:
        
        def __init__(self,sex,name):
            self.sex=sex;
            self.name=name
            
    def printname(self):
        print('%s'%self.name)
        
    def printsex(self):
        print('%s'%self.sex)
    
    # 注意 __name__ 的用法
    if  __name__ == '__main__':   
        person.printname=printname
        p1=person('男','李强')
        p2=person('女','李华')
        p1.printsex=MethodType(printsex,p1)
        
    	#给person类绑定printname方法,给对象p1绑定printsex
        p1.printname()
        p2.printname()
        p1.printsex()
       #p2.printsex()  p2 无 printsex 这个功能
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    绑定新属性例子

    class person:
        __slots__=('name')
            
    class teacher(person):
        __slots__=('tno')
    
    class student(person):
        pass
    
    # 子类有限制会继承父类的限制,子类无限制不继承父类限制
    if  __name__ == '__main__':   
        p1=person()
        p1.name='李华'
        
        t1=teacher()
        t1.name='李强'
        t1.tno='123'
        #t1.sno='122'  t1 不允许扩展 sno 会报错
        
        print('%s'%t1.tno)
        
        s1=student()
        s1.name='丽丽'
        s1.tno='123'
        s1.height='12'
        
        print('%s'%s1.height)
        
        # student类无限制,随意扩展
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    8.__del__ 方法和引用计数

    简介:

    使用 __del__ 方法时 , 当要释放一个对象的内存时
    会先检查一个对象的引用计数,只有 count = 0 时才会释放内存

    """
    使用 __del__ 方法时 , 当要释放一个对象的内存时
    会先检查一个对象的引用计数,只有 count = 0 时才会释放内存
    
    我们可以通过 sys 模块中的 getrefcount 来获取一个对象的引用计数
    
    导致引用计数+1的情况:
    1.对象被创建
    2.对象被引用
    3.对象作为参数被传入到一个函数中
    4.对象作为元素被存储在容器中
    
    导致引用计数-1的情况:
    1.对象的别名被显式销毁
    2.对象的别名被赋给了新的对象
    3.一个对象离开了它的作用域(如一个函数执行完后,它里面的局部变量)
    4.对象所存在的容器被销毁,或从容器中删除了对象
    
    """
    import sys
    
    class people:
        def __del__(self):
            print("对象已被销毁")
            
        pass
    
    p1=people() #count = 1
    
    count=sys.getrefcount(p1) # 对象作为参数被传到了一个函数中 count = 2
    print(count)
    
    p2=p1 #对象被引用 count = 3
    
    count=sys.getrefcount(p1)
    print(count)
    
    del p2 #count = 1
    print("-------1--------")
    del p1 #count = 0
    print("-------2--------")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    榜样访谈——曾钰倬:从讲座中收获经验
    XMind 桌面版新手指南
    WARNING: inbound connection timed out (ORA-3136)
    APS高级排产帮助企业构建知识化系统,推动数字化发展
    神经滤镜为什么不能用,ps神经网络滤镜安装包
    高校教务系统登录页面JS分析——南京邮电大学
    bean无法被注入的常见问题和springboot的三种扫描并加载Bean方式
    重生之我是一名程序员 36
    WPF中TextWrapping
    LLM(大语言模型)解码时是怎么生成文本的?
  • 原文地址:https://blog.csdn.net/woshilichunyang/article/details/126060893