美文网首页
day16-深拷贝和浅拷贝

day16-深拷贝和浅拷贝

作者: 冯书简 | 来源:发表于2019-06-24 17:58 被阅读0次

    多继承

    1.多继承

    python中的类支持多继承

    class 子类(父类1, 父类2,...):
    pass

    class Fly(object):
        """飞行类"""
        f_num = 10
    
    def __init__(self):
        self.height = 0
        self.speed = 0
        self.time = 0
    
    def start(self, speed):
        self.speed = speed
    
    # print(self.speed)
    
    ​    print('开始飞行')
    
    class Animal(object):
        num = 100
    
    def __init__(self):
        self.age = 0
        self.gender = '公'
    
    @staticmethod
    def eat(food: str):
        print('吃'+food)
    
    class Bird(Animal, Fly):
        pass
    
    b1 = Bird()
    
    # 字段都可以继承
    
    print(Bird.f_num, Bird.num)   # 10, 100
    
    # 方法都可以继承
    
    b1.start(10)
    Bird.eat('肉')
    
    # 只能继承第一个父类的对象属性
    
    # print(b1.age, b1.gender)
    
    # print(b1.height, b1.time, b1.speed)
    

    运算符的重载

    1. 运算符

    python中所有的数据类型本质都是类, 所有的数据本质就是对象。

    在使用运算符对数据进行操作的时候,实质是调用运算符对应的魔法方法;
    运算符前面的数据类型,决定了函数哪个类中对应的魔法方法

    每个运算符都有自己固定的魔法方法, 看某种类型的数据是否支持某种运算符就看这个类型中有没有实现对应的魔法方法
    例如: + - add
    > - gt

    class Student:
        def __init__(self, name, age, score=0):
            self.name = name
            self.age = age
            self.score = score
    
    def __repr__(self):
        return '<%s>' % str(self.__dict__)[1:-1]
    
    # +号对应的魔法方法:实现两个对象求和
    
    # self + other  ->  self.__add__(other)
    
    # 函数的返回值就是运算结果
    
    def __add__(self, other):
        print('self:', self.name)
        print('other:', other.name)
        return self.age + other.age
    
    # *号对应的魔法方法:实现对象乘以整数
    
    def __mul__(self, other):
        return self.age * other
    
    # 注意: >和<只需要重载一个,另外一个自动支持
    
    # self < other
    
    def __lt__(self, other):
        return self.score < other.score
    
    stu1 = Student('小明', 19, 90)
    stu2 = Student('小胡', 20, 89)
    
    print(stu1 == stu2)   # False
    
    print(stu1 + stu2)     # stu1.__add__(stu2)
    
    # print(stu1 > stu2)
    
    print('abc'*4)
    
    print(stu1 * 2)    # stu1.__mul__(2)
    
    all_student = [
        Student('stu1', 17, 90),
        Student('stu2', 20, 89),
        Student('stu3', 12, 70),
        Student('stu4', 40, 81)
    ]
    print(all_student)
    
    # 问题
    
    # all_student.sort()   # TypeError: '<' not supported between instances of 'Student' and 'Student'
    
    # 解决方案一:给key赋值
    
    # all_student.sort(key=lambda item: item.score)
    
    # print(all_student)
    
    # 解决方案二: 重载<运算符
    
    # all_student.sort()
    
    # print(all_student)
    
    print(stu1 < stu2)
    print(stu1 > stu2)
    
    print(max(all_student))
    

    内存管理

    手动内存管理

    内存分为栈区间和堆区间,栈区间中的内存是自动开辟自动释放; 堆上的内存需要程序员写代码申请和释放

    1.内存的开辟

    python中所有的类型就是类,所以所有的数据都是对象。对象都是保存在堆区间;变量是保存在栈区间,
    变量中实际存储的是堆中存储的数据的地址。(变量的本质就是指针)

    注意: 除了数字和字符串对象,其他的数据都是每次需要数据的时候直接在堆中开辟空间。
    数字和字符串会先检查这个数据之前是否保存过,如果保存过就直接用之前的数据,否则才开辟新的内存空间

    from sys import getrefcount
    list1 = [1, 2, 3]
    list2 = [1, 2, 3]
    print(id(list1), id(list2))
    
    list3 = list2
    
    num1 = '100'
    num2 = '100'
    print(id(num1), id(num2))
    
    num1 = 2**1999
    num2 = 2**1999
    print(id(num1), id(num2))
    
    # def change(x, y):
    
    # temp = x
    
    # x = y
    
    # y = temp
    
    #
    #
    
    # a = 10
    
    # b = 20
    
    # change(a, b)
    
    # print(a, b)
    

    2.内存的释放

    python中内存的释放采用的是'垃圾回收机制'自动释放

    a.垃圾回收机制: 1)看一个数据是否需要销毁(是否需要回收),就看这个对象的引用计数是否为0(引用:保存对象地址的数据)。
    2)如果这个对象的引用计数不为零就假设当前对象消失,然后看会不会有其他对象因为它的消失引用计数变成0,
    如果有,就将另外一个对象回收(循环引用解环)

    注意: 用一个变量给另外一个变量赋值,实质赋的是地址

    list1 = [10, 20, 30]
    print(getrefcount(list1))
    
    list2 = list1
    print(getrefcount(list1))
    
    # def yt_getrefcount(obj):
    
    # # obj = list1
    
    # print('获取obj的引用次数')
    
    #
    
    # print(yt_getrefcount(list1))
    
    num = 100
    print(getrefcount(num))
    
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
            self.dog = None
    
    class Dog:
        def __init__(self, name, age, color):
            self.name = name
            self.age = age
            self.color = color
            self.owner = None
    
    p1 = Person('小明', 18)
    dog1 = Dog('财财', 3, '黄色')
    p1.dog = dog1
    dog1.owner = p1
    
    del p1
    del dog1
    
    # 面试题:== 和 is的区别?
    
    # 补充: is的使用 - 判断两个数据的地址是否一样
    
    list1 = [1, 2, 3]
    list2 = [1, 2, 3]
    list3 = list1
    print(list1 == list2, list1 == list3)   # True, True
    print(list1 is list2, list1 is list3)   # False, True
    

    深拷贝和浅拷贝

    import copy
    
    class Person:
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
            self.dog = None
    
    def __repr__(self):
        return '<%s>' % str(self.__dict__)[1:-1]
    
    class Dog:
        def __init__(self, name, color):
            self.name = name
            self.color = color
    
    def __repr__(self):
        return '<%s>' % str(self.__dict__)[1:-1]
    

    使用变量的三种情况:

    1.直接赋值 - 赋的是地址,赋完值两个变量一模一样

    变量1 = 变量2

    list1 = [1, 2, 3]
    list2 = list1
    
    list1.append(10)
    print(list1)   # [1, 2, 3, 10]
    print(list2)   # [1, 2, 3, 10]
    

    2.浅拷贝

    列表[:]、列表.copy()、copy.copy(数据)

    浅拷贝: 直接复制被拷贝的数据产生一个新的地址,将新的地址赋给变量; 如果被拷贝的对象中有子对象,子对象不会被复制

    p1 = Person('小明', 18, '男')
    p1.dog = Dog('大黄', '黄色')
    
    # p2 = p1
    
    print('============浅拷贝==============')
    p2 = copy.copy(p1)
    p2.name = 'Tom'
    p2.dog.color = '褐色'
    print(p1)    # <'name': '小明', 'age': 18, 'gender': '男'>
    print(p2)    # <'name': 'Tom', 'age': 18, 'gender': '男'>
    

    3.深拷贝

    copy.deepcopy(数据)
    深拷贝: 直接复制被拷贝的数据产生一个新的地址,将新的地址赋给变量; 如果被拷贝的对象中有子对象,子对象也会被复制

    print('============深拷贝==============')
    p1 = Person('小明', 18, '男')
    p1.dog = Dog('大黄', '黄色')
    p3 = copy.deepcopy(p1)
    
    p3.name = '小花'
    p3.gender = '女'
    p3.dog.color = '红色'
    
    print(p1)
    print(p3)
    
    a = 10
    b = 257
    c1 = 257
    
    def te():
        c = 10
        d = 257
        print(a is c)
        print(b is d)
        print(id(a),id(b),id(c),id(d))
    
    te()
    print(id(c1), id(b))
    

    相关文章

      网友评论

          本文标题:day16-深拷贝和浅拷贝

          本文链接:https://www.haomeiwen.com/subject/vjaoqctx.html