对象可变和不可变&深浅拷贝

1,数据深入了解1

 

name = "xiaoqiang"
age = 24
l = [name,age]
#以name为例
print("唯一表示(内存地址)",id(name))
print("数据类型",type(name))
print("数据成员",dir(name))  #数据类型 = 属性(不可调用) +方法(可调用的)
print("是否可以调用",callable(name))

print("唯一表示(内存地址)",id(age))
print("数据类型",type(age))
print("数据成员",dir(age))  #数据类型 = 属性(不可调用) +方法(可调用的)
print("是否可以调用",callable(age))

print("唯一表示(内存地址)",id(l))
print("数据类型",type(l))
print("数据成员",dir(l))  #数据类型 = 属性(不可调用) +方法(可调用的)
print("是否可以调用",callable(l))

运行结果:

唯一表示(内存地址) 1937148160560
数据类型 <class 'str'>
数据成员 ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
是否可以调用 False
唯一表示(内存地址) 1937142711248
数据类型 <class 'int'>
数据成员 ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
是否可以调用 False
唯一表示(内存地址) 1937148197184
数据类型 <class 'list'>
数据成员 ['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
是否可以调用 False

 

代码:

name = "beifan"
new_name = name # 不是创建新变量, 而是把已有变量,传递过来
new_new_name = name
# 为什么不支持 打变量的变量名? 有N个变量,打算打印哪个?
print(id(name))
print(id(new_name))
print(id(new_new_name))
print("-" * 20)
name = "baili" # 创建新的内存
print(id(name))
print(id(new_name))
print(id(new_new_name))# 变量名 和 内存中的数据,不是强关联

# 1. = 赋值号,用来传递变量,而不是创建变量
# 2. "baili" 写在代码中的时候,已经创建好
# 3. 变量名 和 内存中的数据,不是强关联,可以解除关联,断开联系

运行结果:

2087408588272
2087408588272
2087408588272
--------------------
2087408588336
2087408588272
2087408588272
3. 深拷贝和浅拷贝
copy 复制一个数据对象
代码:
import copy
d={
    "name":"xiaoqiang",
    "age":18,
    "size":[85,85,85]
}
dd=copy.copy(d)
print(d,dd)
print(id(d),id(dd))

运行结果:

{'name': 'xiaoqiang', 'age': 18, 'size': [85, 85, 85]} {'name': 'xiaoqiang', 'age': 18, 'size': [85, 85, 85]}
1958350225280 1958350222208

代码:

import copy
d = {
    "name": "shanxi", "age": 18, "size": [89, 89, 89]
}
dd = copy.copy(d) # 浅拷贝
# dd = copy.deepcopy(d) # 深拷贝
dd['size'].pop()
print("复制的字典", id(d), id(dd)) # 创建新的内存
print("字典中的字符串", id(d['name']), id(dd['name'])) # 没有创建新的内存
print("字典中的整数", id(d['age']), id(dd['age'])) # 没有创建新的内存
print("字典中的列表", id(d['size']), id(dd['size'])) # 没有创建新的内存
# 创建新的内存,还是不创建好?
# 不创建:省内存,效率高
# 创建:非内存,数据完全隔离
print(d)
print(dd)

运行结果:

复制的字典 2056769372032 2056769368960
字典中的字符串 2056772539888 2056772539888
字典中的整数 2056764130064 2056764130064
字典中的列表 2056769689920 2056769689920
{'name': 'shanxi', 'age': 18, 'size': [89, 89]}
{'name': 'shanxi', 'age': 18, 'size': [89, 89]}
结论:
浅拷贝:copy.copy 效率高,开销少,但是数据不隔离
  为什么修改浅拷贝的数据,没有对其他数据进行影响
深拷贝:copy.deepcopy 效率低,开销单,但是数据完全隔离
  所有的变量都是可以深拷贝的吗? 不是
讨论浅拷贝和深拷贝:只针对 可变对象
3,. 图解深浅拷贝
当我们讨论浅拷贝和深拷贝:只针对 可变对象
列表的内存结构
guests = ["Frank", "Claire", "Zoe", True, 42]
new_gueste = copy.copy(guests) # 复制列表 
new_gueste = copy.deepcopy(guests) # 复制列表 及内容成员
只有列表被复制了一份,列表的中内容,没有被复制: 浅拷贝
只有列表被复制了一份,列表的中内容,也被被复制: 深拷贝
4,小实验
变量的id
  name: 1596038932720:173 9B55 68F0
  age:1,596,031,173,392:173 9ADF 0310
  l :1596036038528: 1739B293F80
  name(字符串): 1596038932976:1739B5569F0
  l (列表):1596036038528 :1739B293F80
观察到了什么?
  1. 内置函数id,返回变量的内存地址 (10进制)
  2. 变量在发生变化时,id是否发生变化?
    内存地址没有变,内存中值变了 (对原内存就地完成修改)
    内存地址变了,内存中值也变了 (没有对内存进行修改,而是在新的内存中放置新的值)
对于数据对接,是否支持在原内存进行修改,可以分为:
  可变对象:列表、字典、集合
  不可变对象:数字、字符串、元组
为什么字典要求不可变对象作为key?
  字典是K-V结构,根据K找到V,如果K偷偷变化,就会找错V
知识
Python内存什么时候销毁:
gc(垃圾回收)机制自动完成内存回收(垃圾数据的销毁)
小题:
小强的成绩如下:
小强 = {
    "语文": 70,
    "数学": 65,
    "英语": 66,
    "生物": 69,
    "政治": 78,
    "跳远": [1.2, 1.3, 1.2]
}
大强的语文成绩比小强高20,跳远成绩最后一次是1.5,其他成绩与小强一样
强强的语文成绩比小强高10,其他成绩与小强一样
 
 
使用少的代码完成数据处理,使得下面的代码可以同时打印三个人的成绩
print(小强,大强, 强强)

 

有字符串 a = “aabcdabcd”,写代码计算a出现的次数?
a="aabcdabcd"
print(a.count("a"))

运行结果:

3

 

 
posted @ 2022-12-22 22:40  进一步海阔天空  阅读(8)  评论(0编辑  收藏  举报