1)Number(数字) (bool布尔类型、int整型、float浮点型、complex复数等都归为Number数字类型)、2)String(字符串) 、3)Tuple (元组) 、4)List(列表)、5)Dictionary (字典)、6)Set(集合)
在第一次赋值声明的时候,会在内存中开辟一块空间,用来存储这个变量被赋予的值,变量被声明后,变量的值就与开辟的内存空间绑定,我们不能修改存储在内存中的值,当我们想给此变量赋新值时,会开辟一块新的内存空间保存新的值。
不可变数据类型有:number、string、tuple
在第一次赋值声明的时候,也会在内存中开辟一块空间,用来存储这个变量被赋予的值。我们能修改存储在内存中的值,当该变量的值发生了改变,它对应的内存地址不发生改变。可变数据类型变量中的值变化,地址不会变。若对变量进行重新赋值,则变量的地址也会改变。
可变数据类型为:list、dict、set
指的是计算机重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个元素(子对象)的引用。
浅拷贝的问题
1)对于可变类型的元素,通过浅拷贝创建的新对象B的元素会随着原对象A的元素改变而改变;对于不可变类型的元素则没有此问题。
2)但是对于原对象A新追加的元素c,新对象B不会增加对元素c的引用;
list_A = [[1, 2], (30, 40)]
list_B = list(list_A)
list1.append(100)
print("list_A:",list_A)
print("list_B:",list_B)
# 输出
list_A: [[1, 2], (30, 40), 100]
list_B: [[1, 2], (30, 40)]
list_A[0].append(3)
print("list_A:",list_A)
print("list_B:",list_B)
# 输出
list_A: [[1, 2, 3], (30, 40), 100]
list_B: [[1, 2, 3], (30, 40)]
浅拷贝的创建方式:
import copy
set1 = {1, 2, 3}
set2 = copy.copy(set1)
print(set2)
print("set1 == set2 ?",set1 == set2)
print("set1 is set2 ?",set1 is set2)
是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。
深拷贝的创建方式:
Python 提供了 copy.deepcopy() 来实现对象的深度拷贝,适用于任何数据类型,具体用法如下:
import copy
list1 = [[1, 2], (30, 40)]
list2 = copy.deepcopy(list1)
list1.append({"name":"ziyi", "age": 30})
print("list1:",list1)
print("list2:",list2)
# 输出
list1: [[1, 2], (30, 40), {'name': 'ziyi', 'age': 30}]
list2: [[1, 2], (30, 40)]
# 可变元素追加子元素
list1[0].append(3)
print("list1:",list1)
print("list2:",list2)
#输出
list1: [[1, 2, 3], (30, 40), {'name': 'ziyi', 'age': 30}]
list2: [[1, 2], (30, 40)]
在函数内部(嵌套)定义另一个函数时,如果内层的函数引用了外层的函数的变量,内层函数作为外层函数的返回,此时相对于外层函数的外部而言,这两个内层和外层函数的整体就是闭包。
def outer_fun(pos=[0,0]):
def inner_fun(direction, step):
new_x = pos[0]+direction[0]*step
new_y = pos[1]+direction[1]*step
pos[0] = new_x
pos[1] = new_y
return pos
return inner_fun
# player实际上就是闭包inner_fun函数的一个实例对象
player = outer_fun()
print(player([1,0],10))
print(player([0,1],20))
print(player([-1,0],10))
作用1:闭包是将外层函数内的局部变量和外层函数的外部连接起来的一座桥梁,此时相当于外层函数的外部可以调用外层函数内的局部变量。
作用2:将外层函数的变量持久地保存在内存中。
原因:原因在于outer_fun是inner_fun的父函数,而inner_fun被赋给了一个全局变量,这导致inner_fun始终在内存中,而inner_fun的存在依赖于outer_fun,因此outer_fun也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收
由于闭包会使得函数中的变量都被保存在内存中,会增加内存消耗,所以不能滥用闭包,否则会造成程序的性能问题,可能导致内存泄露。
1、在需要既可以长久的保存变量又不会造成全局污染的场景,可以使用闭包。因为局部变量无法共享和长久的保存,而全局变量可能造成变量污染
2、函数上方带参数的装饰器,那么一般都会生成闭包。
就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰对象添加新功能的函数。
请看下面示例代码:
import time
# 装饰器
def timmer(func):
def wrapper(*args, **kwargs):
start = time.time()
print("装饰器内部,start={}".format(start))
res = func(*args, **kwargs)
print("res={}".format(res))
stop = time.time()
print("stop - start=".format(stop - start))
return res
return wrapper
# 语法糖:让你开心的语法
# 就是在被装饰对象正上方的单独一行写@装饰器名字
@timmer # index=timmer(index)
def index(x, y, z):
print("index函数内部")
time.sleep(3)
print('index %s %s %s' % (x, y, z))
# 执行被装饰的函数
index(x=1, y=2, z=3)
上面这一行代码相当于执行了以下两行代码,因为在被装饰的函数前一行加上了@装饰的名字器:(@timmer)
# 等号左边是timmer装饰器实例化后的index对象;
# 等号右边是前面定义的index()函数,它作为装饰器函数timmer的一个参数
index=timmer(index)
# 调用index对象
index(x=1, y=2, z=3)
# 从被装饰函数的执行结果看执行过程,具体如下:
# 执行结果
"""装饰器内部,start=1675656150.551987
index函数内部
index 1 2 3
res=None
stop - start=3.0070817470550537"""
# 执行过程
# 1、装饰器函数实例化:index=timmer(index)
# 2、实例化的对象index被调用执行:index(x=1, y=2, z=3)
# 3、调用index对象的wrapper方法,按照里面的代码块执行,这个代码块里面就会调用原来封装的index()函数
load()方法是从json文件读取json,返回字典对象
loads()方法是将字符串形式的json转化为字典对象
以下是具体使用案例
test_json.json文件:
{"name": "广州", "area": "2000wan平米", "population": 2000000, "city": ["东莞", "佛山", "珠海"]}
import json
# 先说load()方法
with open("test_json.json", "r", encoding="utf-8") as f:
# load()方法是从json文件读取json,返回字典对象
data = json.load(f)
print("load()方法加载的文件的json转化为:{},\n类型是{}".format(data, type(data)))
# 输出
# load()方法加载的文件的json转化为:{'name': '广州', 'area': '2000wan平米', 'population': 2000000},
# 类型是
# loads()方法
# loads()方法是将字符串形式的json转化为字典对象
json_str1 = """{"name": "广州", "area": "2000平米", "population": 2000000, "city": ["东莞", "佛山", "珠海"]}"""
data3 = json.loads(json_str1)
print("loads()方法加载的文件的json转化为:data3={},\n类型是{}".format(data3, type(data3)))
# 输出
# loads()方法加载的文件的json转化为:data3={'name': '广州', 'area': '2000平米', 'population': 2000000, 'city': ['东莞', '佛山', '珠海']},
# 类型是
json.dumps是对python的字典对象编码成JSON对象的函数,可以把字典转成JSON字符串。
import json
ob = {'name': '广州', 'area': '2000wan平米', 'population': 2000000, "city": ["东莞", "佛山", "珠海"]}
with open("test_json.json", "w", encoding="utf-8") as f:
# dump()方法是将字典对象转换为JSON对象并写入json文件, ensure_ascii=False 代表中文不转义
json.dump(ob, f, ensure_ascii=False)
# dumps()方法将字典对象转换为JSON字符串, ensure_ascii=False 代表中文不转义
result = json.dumps(ob, ensure_ascii=False)
print(result, type(result))
# 输出
# {"name": "广州", "area": "2000wan平米", "population": 2000000, "city": ["东莞", "佛山", "珠海"]}
#