12-python基础知识-面向对象

面向对象

抽象基类(了解)

  • 说明:

    • 抽象基类就是为了统一接口而存在的
    • 抽象类不能进行实例化(创建对象)
    • 继承自抽象类的子类必须实现抽象类中的抽象方法
  • 示例:

    from abc import ABC, abstractmethod
    
    # 抽象基类
    class Animal(ABC):
        # 定义抽象方法:规定接口
        @abstractmethod
        def run(self):
            pass     
        
        
    # 抽象基类无法实例化  
    # a = Animal()
    class Cat(Animal):
        # 子类中必须实现抽象基类的抽象方法,才能实例化
        def run(self):
            print('猫喜欢走猫步')   
            
    c = Cat()           
    

特殊函数

  • 示例1

    d = {'name': 'xiaoming', 'age': 20}
    
    # 返回对象的字符串表示形式
    r = repr(d)
    
    print(r, type(r))
    
    # 执行有效的python代码字符串
    d2 = eval(r)
    
    print(d2, type(d2))
    
    a = 10
    b = 20
    c = eval('a + b')
    print(c)
    
  • 示例2:

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        # print打印对象,str方法转换时都会触发
        def __str__(self):
            print('__str__')
            return '姓名:{} 年龄:{}'.format(self.name, self.age)
    
        # 返回对象的字符串表示形式,使用repr函数处理时会自动触发
        def __repr__(self):
            return "Person('{}', {})".format(self.name, self.age)
        
    p = Person('王大花', 18)
    # print(p)
    # s = str(p)
    
    r = repr(p)
    print(r)
    
    p2 = eval(r)
    print(p2, type(p2))
    

内置方法

  • 构造和析构

    __init__、__del____
    
  • 干预属性操作

    __setattr__、__getattr__、__delattr__
    
  • 支持字典操作

    __setitem__、__getitem__、__delitem__
    
  • 对象支持函数调用

    __call__
    
  • 打印输出或str转换

    __str__
    
  • 对象的字符串表示,调用repr方法时触发

    __repr__
    

运算符重载

  • 算术运算符

    • 示例:
    class Number:
        def __init__(self, num):
            self.num = num
    
        # 对象出现在'+'的左边时会自动触发
        def __add__(self, other):
            print('__add__')
            return self.num + other
    
        # 对象出现在'+'的右边时会自动触发
        def __radd__(self, other):
            print('__radd__')
            return self.num + other
    
        # +=运算时自动触发,若没有实现会调用__add__
        def __iadd__(self, other):
            print('__iadd__')
            # 返回新的Number对象
            # return Number(self.num + other)
            # 返回处理后的原始对象
            self.num += other
            return self
        
    n = Number(10)
    print(id(n))
    
    # ret = n + 20
    # ret = 20 + n
    # print(ret)
    
    n += 50 # n = n + 50
    print(id(n))
     
    
    • 自行测试
    加法:add、radd、iadd
    减法:sub、rsub、isub
    乘法:mul、rmul、imul
    除法:truediv、rtruediv、itruediv
    求余:mod、rmod、imod
    
  • 关系运算符

    class Number:
          def __init__(self, num):
              self.num = num
    
          # 大于 >
          def __gt__(self, other):
              print('__gt__')
              return self.num > other
    
          # 小于 <
          def __lt__(self, other):
              print('__lt__')
              return self.num < other
    
          # 等于 ==, 判断是否相等,当不实现__ne__时,!=运算也会触发
          def __eq__(self, other):
              print('__eq__')
              return self.num == other
    
          # 大于等于 >=
          def __ge__(self, other):
              print('__ge__')
              return self.num >= other
    
          # 小于等于 <=
          def __le__(self, other):
              print('__le__')
              return self.num <= other
    
          # 不等于 !=
          def __ne__(self, other):
              print('__ne__')
              return self.num != other
            
    n = Number(20)
    
    print(n > 10)
    print(n < 10)
    print(n == 10)
    print(n != 10)        
    

内存管理

  • 引用计数

    • python中所有的数据都是通过类来实现的,对象的管理是通过引用计数实现的
    • 当创建一个对象赋值给一个变量时,引用计数为1,当多一个变量指向该对象时,计数值加1;当少一个变量指向对象时,计数值减1。计数值减到0时会调用__del__方法释放存储空间
    • 不可变变量引用计数是没有意义的
    • 示例:
    import sys
    
      # 不可变变量的引用计数没有意义
      a = 10
      print(sys.getrefcount(a))
    
      lt = [1, 2, 3]
      lt2 = lt
      # 本身此时引用计数为1,但是该方法也引用了一次
      print(sys.getrefcount(lt))
      del lt2
      print(sys.getrefcount(lt))
        
    class Person:
        def __del__(self):
            print('对象即将释放')
            
    p = Person()
    print(sys.getrefcount(p))
    del p
    print('over')          
    
  • 函数传参

    • 对不可变变量来说,传递的是值,函数中不可能改变传递的参数
    • 对于可变变量及自定义的类创建的对象,传递的是引用,函数中可以操作原对象
    • 示例:
    def test(a):
    	a += 1
    
    num = 100
    # 对于不可变数据传递的是值
    
    test(num)
    	print(num)
    
    def test2(lt):
    lt[0] = 10
    
    lt = [1, 2, 3]
    test2(lt)
    print(lt)    
    
  • 深浅拷贝

    import copy
    
    lt = [1, 2, [3, 4]]
    # 赋值会增加一个引用,访问的都是同一数据
    
    lt2 = lt
    # 浅拷贝:只拷贝对象本身,里面的元素只会增加一个引用
    # lt2 = lt.copy()
    
    # 专门的拷贝函数,也是浅拷贝,等价于上面的拷贝
    lt2 = copy.copy(lt)
    
    # 深拷贝:拷贝对象本身,对象中的元素也进行拷贝
    # lt2 = copy.deepcopy(lt)
    
    lt[0] = 100
    lt2 = 30
    
    print(lt)
    print(lt2)
    print(id(lt))
    print(id(lt2))
    
    # 判断是否是同一对象的多个引用
    print(lt is lt2)
    

数据持久化存储

  • 说明:持久化存储方案,普通文件、数据库、序列化

  • 示例:

    import pickle
    
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return 'name:{} age:{}'.format(self.name, self.age)
       
       
    xiaoming = Person('xiaoming', 20)
    # print(xiaoming)
    
    # 序列化:会将对象转换为bytes
    # s = pickle.dumps(xiaoming)
    # print(s)
    
    # 反序列化:从bytes中解析出对象
    # xm = pickle.loads(s)
    # print(xm, type(xm)) 
    
    # 直接保存到文件
    # fp = open('data.txt', 'wb')
    # pickle.dump(xiaoming, fp)
    # fp.close()
    
    # 从文件中读取对象
    fp = open('data.txt', 'rb')
    xm = pickle.load(fp)
    print(xm, type(xm))
    

猜你喜欢

转载自blog.csdn.net/weixin_44147782/article/details/85267402