# 数据类型:int,float,str,bool,list,tuple.dict,set
# 可变类型:数据所在的内存允许被修改(不使用等号,数据内容可以变化),list,dict,set
# 不可变类型:int,float,str,bool,tuple(不使用等号,数据内容是不可以变化的)
# str类型:使用join,split,replace等对字符串进行操作,是不改变原字符串的,所以字符串是不可变类型
# list,使用append,extend,insert,pop,remove.clear可以改变它的内容
# dict,使用pop,del,clear可以改变它的内容
list1 = [1, 2, 3, 4]
print(id(list1), id(list1[3]))
list1[2] = 4 # 此处只是修改了list[3]的引用地址,list1还是指向原来的地址,变化的是list[3]这个int,不是list
print(id(list1), id(list1[3]))
# 根据以上内容可以理解
tuple1 = (1, 2, 3, list1)
print(tuple1, id(tuple1))
list1[2] = 0
print(tuple1, id(tuple1))
# 使用这种方法可以改变tuple的内容,但是没有改变tuple的引用地址,它还是有3个int一个list的tuple.可变的是list不是tuple
# -----------------------------------------------------------------
# 可变类型做形参,函数内部,不使用=修改形参的引用,所做的修改就会同步到实参中
def func1(list_a):
list_a.append('aaa')
list_a[0] = "a"
list2 = [1, 2, 3]
func1(list2)
print(list2)
# 可变类型做形参,使用=改变了形参的引用,修改不会同步到实参
def func2(list_a):
list_a = ['qqq', 'www']
func2(list2)
print(list2)
# ---------------------------------------------------------------
# 对应列表来说,+=的本质是extend,没有使用=改变引用,所以在函数中使用的会影响实参的值
list3 = [1, 2]
list3 += [3, 4]
print(list3) # [1,2,3,4]
# ------------------------------------------------------------------------
# 交换两个变量的值:
# 常规方法:引入第三个变量
a = 1
b = 2
print(a, b)
c = a
a = b
b = c
print(a, b)
# 数学方法
print(a, b)
a = a + b
b = a - b
a = a - b
print(a, b)
# python特有
a, b = b, a
print(a, b)
# --------------------------------------------------------
# 组包pack:将多个数据值使用逗号链接,组成一个元组
# 拆包unpack:将容器(不一定是元组)中的数据值,使用多个变量分别保存
# 拆包时,变量的个数和容器中的数据个数要保持一致
# 最大的应用就是交换两个变量的值
# 出现=.先计算右边的值,再将右边的值复制给左边
c = b, a # 组包
print(c, type(c))
a, b = c # 拆包
print(a, type(a), b, type(b))
# ------------------------------------------------------------
# 局部变量和全局变量
# 根据变量定义的位置,分为局部变量和全局变量
# 局部变量在函数内部定义,只能在当前函数内部使用,
# 在不同函数中可以定义名字相同的局部变量,函数被调用时局部变量被定义,调用结束后局部变量的值被销毁
# 想要在函数外部使用局部变量的值,需要使用return返回值将局部变量的值传回调用处
def func3():
num = 10
print(num)
return num
num = func3() # 这里的num和函数中的num互不影响
print(num) # 这里打印的是外边这个num的值,函数返回了函数中的num的值,在上一句被赋值给了外边的num
# 全局变量:可以在任意函数中获取全局变量的值
# 如果在函数中存在了和全局变量同名的局部变量,就近原则,函数中使用的是局部变量
# 需要使用global关键字声明此处使用的是全局变量不是同名的局部变量
num1 = 10
def func4():
print(f'func4中的num1:{num1}')
def func5():
num1 = 20
print(f'func5中的num1:{num1}')
def func6():
global num1 # 一旦要使用global,一定要放在函数内部的第一行
print(f'func6修改前的num1:{num1}')
num1 = 30 # 修改了全局变量的值
print(f'func6中的num1:{num1}')
func4()
func5()
func6()
func4() # func6已经改过了全局变量,所以再调用就变了
# -----------------------------------------------------------------------------
# 多个返回值:将多个数据组成容器后进行返回,一般是元组(组包)
def func_sum(a, b):
num1 = a + b
num2 = a - b
return num1, num2
# 使用1,利用元祖特性
result = func_sum(7, 1)
print(result[0], result[1])
# 使用2:直接拆包
x, y = func_sum(7, 2)
print(x, y)
# ------------------------------------------------------
# 函数的传参
def func_sum2(a, b, c):
num1 = a + b
num2 = a - b
num3 = a * b + c
return num1, num2, num3
# 函数的传参方式:
# 位置传参:在函数调用时,按照形参顺序,将函数实参值传递给形参
print(func_sum2(1, 2, 3))
# 关键字传参:函数调用时指定数据给哪个形参
print(func_sum2(c=1, b=3, a=1))
# 混合使用:关键字传参都必须写在位置参数后面
func_sum2(2, c=1, b=1)
# func_sum2(1,2,b=2)这样写是不对的,系统会默认1,2分别赋给a,b
# -----------------------------------------------------------
# 缺省参数
# 定义方式:定义的时候给形参一个默认值,缺省参数要放在普通参数后边
def func_print(name, sex='默认'):
print(name, sex)
func_print('硫磺')
# ------------------------------------------------------
# 多值参数/可变参数/不定长参数:定义函数时不确定参数的具体个数
# 不定长位置参数(不定长元组):在普通参数前边加一个*,可以接收任意多个位置传参的数据
# 形参的类型是元组,不定长参数要写在普通参数后边,通常名为*args
# 不定长关键字阐述(不定长字典):在普通函数前加**
# 形参类型是字典,写在所有参数最后边,通常名为**kwargs
def show(name, age, *args, **kwargs):
print(type(args), args)
print(type(kwargs), kwargs)
show('张三', 16, [333, 3], 6, 'jjj', a=1)
show(a=1, b=2, name='张三', age=20)
# 满足了普通参数后,所有的关键字传参都给了kwargs,普通参数不能缺省
# --------------------------------------------------------------
# 拆包
def my_sum(n):
num_sum = 0
for i in range(1, n + 1):
num_sum += i
print(num_sum)
return num_sum
# 将列表和字典中的数据分别传参
my_list = [1, 2, 3, 4]
my_dict = {'a': 1, 'b': 2}
my_sum(*my_list) # 对列表或元组拆包
my_sum(**my_dict) # 对字典进行拆包
# --------------------------------------------------------------
# 匿名函数:使用lambda关键字定义函数,只能书写一行代码(表达式),不需要return
# 一般不起名,一般不需要主动调用,作为函数的参数使用
# 主动调用时起名(仅用于学习时查看定义是否成功)
def func_0(a):
return a
lam_func1 = lambda: print('hello')
# pep8建议:不要给匿名函数起名,如果一定到将函数值赋值给变量,请使用def
lam_func1()
func_l1 = lambda a, b: print(a * b)
func_l1(1, 2)
# 函数定义时形参只是一个符号,写什么都行,实参传什么类型它就是什么类型
func_l2 = lambda a: print(a.get('age')) # 默认它是字典,函数中进行字典操作,传非字典会因为传过来的数据没有.get而报错
func_l2({'name': '张三', 'age': 12})
func_l3 = lambda a, key: print(a.get(key))
func_l3({'name': '张三', 'age': 12})
# 列表中字典的排序
# 列表的排序默认是对数字和字符串进行大小比较,对于字典来说默认是不知道如何排序的
# 使用sort函数的key参数来实现字典的排序,key需要传递一个函数,一般是匿名函数
# 需要指定根据字典的什么值进行排序,使用匿名函数返回字典的指定键对应值即可
name_list = [{'name': 'zhangsan', 'age': 16}, {'name': 'lisi', 'age': 20},
{'name': 'wangwu', 'age': 30}]
name_list.sort(key=lambda dict1: dict1['name']) # 按照姓名升序
print(name_list)
name_list.sort(key=lambda dict1: dict1['name'], reverse=True) # 按照姓名降序
print(name_list)
# 说明:匿名函数中的参数是列表中的数据,在sort函数内部会调用key参数,从列表中获取匿名函数的返回值进行比大小