美文网首页
python面向对象3、内存管理和拷贝

python面向对象3、内存管理和拷贝

作者: 举颗凤梨 | 来源:发表于2019-08-12 20:00 被阅读0次

1.多继承

  • python中的类支持多继承(让一个类同时继承多个类)
  • 多继承的时候,子类只能继承第一个父类中所有的属性和方法,后面的父类中只有字段和方法可以被继承
  • 实际上:子类能继承第一个父类的所有属性和方法,后面的父类,只能继承前面没有的字段和方法(不重名的)
class Animal(object):
    num = 100
    name = 'hh'

    def __init__(self):
        self.age = 0
        self.gender = 'male'

    @classmethod
    def func1(cls):
        print('动物类的类方法')


class Fly(object):
    name = '飞行器'

    def __init__(self):
        self.height = 100
        self.time = 20
        self.spend = 100

    def func1(self):
        print('红红火火')

    def func2(self):
        print('飞行的对象方法')


class Bird(Animal,Fly):
    pass


bird = Bird()
print(Bird.num,Bird.name)
bird.func1()
bird.func2()
print(bird.age)

运算符重载

import copy

python中所有的类型都是类,所以所有的数据都是对象
python中使用任意的运算符都是在调用相应类中的相应方法,每一个运算符对应什么方法是固定
某种数据是否支持某个运算符操作就看这个数据类型中是否实现了对应的方法

2.运算符重载指的是在不同的类中实现同样的运算符对应的函数

类的对象默认情况下只支持:==,!=

class Student:
    def __init__(self, name, age, score=0):
        self.name = name
        self.age = age
        self.score = score

    def __repr__(self):
        return str(self.__dict__)

    # a+b  ->  a.__add__(b)
    # self  ->  当前类的对象,也就是+前面的那个数据
    # other  ->  +后面的那个数据,类型根据运算规则的设计可以是任何类型的数据
    def __add__(self, other):
        # return self.age + other.age
        # return self.score + other.score
        return self.name + other.name, self.age + other.age, self.score + other.score
        # return 'abc'

    def __mul__(self, other):
        list1=[]
        for _ in range(other):
            list1.append(copy.copy(other))
        return list1

    # 大于和小于运算符只需要重载一个,另外一个自动实现
    def __lt__(self, other):
        return self.score < other.score


stu1 = Student('小明', 12, 34)
stu2 = Student('小胡', 15, 67)
stu3 = Student('小胡', 15, 47)

print(stu1 == stu2, stu1 != stu2)   # False True
print(stu1 + stu2)  # return self.age + other.age 27
print(stu1 + stu2)  # return self.score + other.score 101
print(stu1 + stu2)  # return self.name + other.name,self.age + other.age,self.score + other.score   ('小明小胡', 27, 101)
print(stu1 + stu2)  # return 'abc' abc
students = [stu1, stu2, stu3]
students.sort()
print(students)

""" = = = HJR = = = """

from copy import copy, deepcopy
# 支持所有类型的拷贝
class Dog:
    def __init__(self,name,color):
        self.name=name
        self.color=color

    def __repr__(self):
        return '<%s,id:%s>' % (str(self.__dict__)[1:-1],hex(id(self)))


class Person:
    def __init__(self,name,age,dog):
        self.name = name
        self.age = age
        self.dog = dog

    def __repr__(self):
        return '<%s,id:%s>' % (str(self.__dict__)[1:-1],hex(id(self)))


p1 = Person('小米',18,Dog('大黄','黄色'))

1.直接赋值

将变量中的地址直接赋给新的变量,赋值后两个变量的地址相同

p2 = p1
print(id(p1),id(p2))   # 3032819635872 3032819635872
p1.name = '小花'
print(p1.name,p2.name)   # 小花 小花

2.拷贝

不管是浅拷贝还是深拷贝都会对原数据进行赋值产生新的地址
浅拷贝只拷贝当前对象,不会拷贝子对象,还是与原来的子对象相关联
深拷贝拷贝所有,完全与原对象分离

print(id(p1),id(copy(p1)),id(deepcopy(p1)))  # 2045139556000 2045139556168 2045139556728

3.浅拷贝

字符串、列表和元祖的切片;对象.copy();copy模块中的copy方法都是浅拷贝

p3 = copy(p1)
print(p1,p3)   # <'name': '小花', 'age': 18, 'dog': <'name': '大黄', 'color': '黄色',id:0x29a6c9213c8>,id:0x29a6c921668> <'name': '小花', 'age': 18, 'dog': <'name': '大黄', 'color': '黄色',id:0x29a6c9213c8>,id:0x29a6c921668>
p3.dog.name = '哈尼'
p3.name = '小童'
print(p1,p3)   # <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黄色',id:0x285c82e13c8>,id:0x285c82e1668> <'name': '小童', 'age': 18, 'dog': <'name': '哈尼', 'color': '黄色',id:0x285c82e13c8>,id:0x285c82e1940>
# 发现dog中的改变会一同改变


# 4.深拷贝
"""
copy模块中的deepcopy为深拷贝,有且仅有这一个
"""
p4 = deepcopy(p1)
print(p1,p4)   # <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黄色',id:0x15086f915f8>,id:0x15086f916a0> <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黄色',id:0x15086f915f8>,id:0x15086faae10>
p4.dog.name = '大华'
p4.name = '小美'
print(p1,p4)  # <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黄色',id:0x1d71fee15f8>,id:0x1d71fee16a0> <'name': '小美', 'age': 18, 'dog': <'name': '大华', 'color': '黄色',id:0x1d71fefaeb8>,id:0x1d71fefada0>

练习

a = ['color','height','background']
b = [a,'aaa','bbb']
c1 = b
c2 = copy(b)
c3 = deepcopy(b)
a[-1] = ['BG']
b.append('ccc')
# [['color','height',['BG']],'aaa','bbb','ccc']
# [['color','height',['BG']],'aaa','bbb']
# [['color', 'height', 'background'], 'aaa', 'bbb']
# 问题:print(c1),print(c2),print(c3)的打印结果

""" = = = HJR = = = """
from enum import Enum,unique

枚举值的特点:

1.可以通过有意义的属性名直接显示数据
2.每个数据的值不能修改
3.可以做到不同的数据是唯一的

unique确保不同的数据是唯一的
在类中继承Enum可以做到枚举

@unique
class PokerNum(Enum):
    J = 11
    Q = 12
    K = 13


print(PokerNum.J)    # PokerNum.J
print(PokerNum.J.value > PokerNum.Q.value)   # False

""" = = = HJR = = = """

获取引用计数

from sys import getrefcount

1.内存的开辟

内存区间分为栈区间和堆区间;栈区间的内存自动开辟自动释放,堆区间的内存需要程序员手动开辟手动释放;
但是python已经将堆区间内存的开辟和释放自动化

a. 当给变量赋值的时候,系统会先在堆区间中开辟空间将数据存起来,然后再将数据在队中的地址存到变量中,变量存在栈区间;
b. 数字和字符串数据在开辟空间的时候,会先检查内存中之前是否已经有这个数据,
如果有,直接使用之前的数据,不再开辟空间,如果没有,才重新开辟空间

a, b = [1, 2, 3], [1, 2, 3]
print(id(a), id(b), a is b)   # 1567575270024 1567575270088 False
print(id(a[0]),id(b[0]), a[0] is b[0])  # 140726342640464 140726342640464 True
a, b = 10, 10
print(id(a), id(b), a is b)   # 140726342640752 140726342640752 True
a, b = '10', '10'
print(id(a), id(b), a is b)   # 1567575737208 1567575737208 True

2,内存的释放

栈区间:全局栈区间在程序结束后销毁,函数栈区间在函数调用结束后销毁(自动)
堆区间:看一个对象是否销毁,就看这个对象的引用计数是否为0;
如果一个对象的引用计数为0,这个对象就销毁,反之不销毁(垃圾回收机制)
注意:python中针对对象的循环引用,已经做了处理,程序员不需要写额外的代码来解决循环引用的问题

a = [1, 2, 3]
print(getrefcount(a))  # 2 会打印比之前多一个引用,因为函数本身会有一个

def fun(a={}):
    a[1]=3
    return a


print(fun())
print(fun())

相关文章

  • python面向对象3、内存管理和拷贝

    1.多继承 python中的类支持多继承(让一个类同时继承多个类) 多继承的时候,子类只能继承第一个父类中所有的属...

  • Python浅拷贝与深拷贝

    Python浅拷贝与深拷贝 一、可变对象与不可变对象 见Python变量 二、copy模块 对象拷贝是指在内存中创...

  • python 高级 概况

    1、包和模块2、is和==的区别 内存分析3、引用传递和深浅拷贝4、回顾面向对象(二次加深)5...

  • 深、浅拷贝

    说到深浅拷贝,Python和其他语言一样也涉及到内存分配问题,对象的赋值和拷贝有很大差别,赋值是把变量和内存某块连...

  • python高级

    python高级:1、模块和包2、深浅拷贝3、回顾面向对象4、列表生成器5、迭代器6、装饰器7、函数高级8、正则表...

  • 深拷贝和浅拷贝

    什么是深拷贝和浅拷贝 浅拷贝是复制了一个对象的指针,而不是复制对象的内存,新对象和原对象还是同一块内存.而深拷贝会...

  • guorenbao iOS笔试题总结(如有错误,请指正)

    1.深拷贝和浅拷贝的区别。 答:浅拷贝只是对对象的简单拷贝,让几个对象共用一片内存,当内存销毁的时候,指向这片内存...

  • iOS开发:深拷贝和浅拷贝学习笔记

    浅拷贝:浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。 深拷贝:深拷贝是让目标对象指针和源...

  • Python基础入门 - 面向对象

    1. 初识面向对象 1.1 介绍 步骤介绍面向对象的概述面向对象的实现面向对象的应用内存管理进程、线程、协程 概要...

  • Python面向对象基础:编码细节和注意事项!

    在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名...

网友评论

      本文标题:python面向对象3、内存管理和拷贝

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