python | 基础学习(四)变量

十一、变量进阶

1、变量的引用

变量 和 数据 都是保存在 内存 中的;
在python中函数的 参数传递 以及 返回值 都是靠 引用 传递的。

2、引用的概念

在python中,变量 和 数据 是分开存储的;数据保存在内存中的一个位置,变量 保存着数据在内存中的地址。
变量记录着数据的地址,这就叫引用。使用id()函数可以查看变量中保存数据所在的 内存地址
注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是 修改了数据的引用 。变量 不再 对之前的数据引用,改为对新赋值的数据的引用。

#看到赋值语句,首先把注意力放到等号的右侧
#把 数据 看成 小格子变量 看成 便签纸
应用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在函数中,实参是通过 引用 获取数据的。调用函数时,本质上传递的是实参保存数据的引用,而不是实参保存的数据本身。

def test(num):
    print("在函数内部%d对应的内存地址是%d" % (num, id(num)))
    
    # 定义一个字符串变量
    result = "Hello"
    print("函数返回数据'Hello'的内存地址是%d" % id(result))
    
    # 函数返回的是数据的引用,而不是数据本身。
    return result

# 1、定义一个变量
a = 10
# 数据的地址本质上就是一个数字
print("a变量保存数据的内存地址是%d" % id(a))

# 2、调用test函数。
# 如果函数有返回值,但是没有定义变量接收,程序不会报错,但是无法获得返回结果。
r = test(a)  # 函数的返回结果是result,因此r = result。
print("%s的内存地址是%d" % (r, id(r)))

输出:
在这里插入图片描述

3、可变和不可变类型

不可变类型:内存(小格子)中的数据不允许被修改:

数字类型:int, bool, float, complex, long(2,x)
字符串:str
元组:tuple

例如:

a = 1 
a = "Hello" 
a = [1, 2, 3] 
#当给一个已有变量赋予新值时,是在修改变量a的地址,而不是在修改 小格子中原有的数据内容。
a = [4, 5, 6]

可变类型:内存(小格子)中的数据可以被修改:

列表list
字典dict

#字典的key只能使用不可变类型的数据,不能使用列表、字典这两个可变类型数据。
在这里插入图片描述
在这里插入图片描述

哈希(hash)

python中内置有一个名字叫做hash(0)的函数,接受一个 不可变类型的数据作为 参数,返回结果是一个整数。
哈希是一种算法,其作用就是提取数据的 特征码(指纹)
相同的内容 得到 相同的结果,
不同的内容得到 不同的结果。
在python中,设置字典的 键值对时,会首先对key进行hash,以决定如何在内存中保存字典的数据,以方便后续对字典的操作:增、删、改、查
键值对的key必须是不可变类型数据,
键值对的value可以是任意类型的数据
在这里插入图片描述
可以看到 哈希报错情况 与上述 对字典d操作时的报错情况 是一样的。

可变类型的数据变化,是通过 方法 来实现的。如果给一个可变类型的变量赋值一个新的数据,引用 会修改。

变量 不再 对之前的数据引用
变量 改为 对新赋值的数据的引用
例如:
在这里插入图片描述
在这里插入图片描述

4、局部变量和全局变量

局部变量 :是在 函数内部 定义的变量,只能在函数内部使用

函数执行结束后,函数内部的局部变量会被系统回收
不同的函数,可以定义相同名字的局部变量,互相之间不会产生影响。

例如:

def demo1():
	num = 10
	print("在demo1函数内部定义的变量是%d" % num)
print("%d" & num)  # 会报错:在函数内部定义的变量不能在其它位置使用。

局部变量的生命周期 :指变量从 被创建被系统回收 的过程。局部变量在函数执行时才会被创建,函数执行结束后 局部变量会被系统回收。在局部变量的生命周期内,可以用来存储函数内部临时使用到的数据。

全局变量 :是在 函数外部 定义的变量(没有定义在某一个函数内),所有函数 内部 都可以使用这个变量。

在开发时,应该把模块中所有的全局变量都定义在函数上方,这样就可以保证所有的函数都能够正常访问每一个全局变量了。不允许直接修改全局变量的引用——不能使用赋值语句修改全局变量的值。
:在其它语言中,大多 不推荐使用全局变量。因为可变范围太大,导致程序不好维护。

全局变量命名

全局变量命名应该增加g_gl_前缀。例如g_numgl_num
如果局部变量的命名与全局变量的名字相同,pycharm会在局部变量下方显示灰色的虚线。

例如:

num = 20  # 全局变量

def demo1():
    num = 10
    print("num=%d" % num)
demo1()  

def demo2():
    print("num=%d" % num)
demo2()  # 从输出可以看出,全局变量num的数据并没有被修改
# 因此,从demo1的输出可以看出,函数内部的num赋值语句只是新建了一个局部变量。

输出:
在这里插入图片描述
如果想要在函数内部修改全局变量的值,只需要使用global关键字。例如,global num表示声明num为全局变量。global关键字告诉解释器“后面的变量是一个全局变量”,再使用赋值语句时,就不会再创建局部变量。
例如:在上述例子中增加一句global num

num = 20
def demo1():
    global num
    num = 10
    print("num=%d" % num)
demo1()

def demo2():
    print("num=%d" % num)
demo2()

输出:
在这里插入图片描述

5、函数参数和返回值的作用

函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4种 组合形式。具体是否接收参数,是否有返回结果,都是根据实际需求而定的。如果 函数内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部。如果希望一个函数执行完成后向外界汇报执行结果,就可以增加函数的返回值。

无参数,无返回值
无参数,有返回值
有参数,无返回值
有参数,有返回值
在这里插入图片描述

一个函数执行后能否返回多个结果?of course!

def measure:
	...
	return (a, b)  # 利用元组,返回多个值。
	
	#将上句改写为:
	return a, b  # 如果函数返回的类型是元组,小括号()可以省略
	
	#输出结果:
	result = measure()
	print(result)

如果希望单独处理函数返回值的元组元素,可以使用多个变量,一次接受函数的返回结果。变量的个数可以与元组中元素的个数相同。

gl_a, gl_b = measure()
print(gl_a)
print(gl_b)

交换两个数字

有两个整数变量a = 6b = 100,不使用其他变量,交换两个变量的值。
方法一:使用临时变量

c = a
a = b
b = c

方法二:不使用临时变量 ·

a = a + b
b = a - b
a = a - b

方法三:python独有,利用元组

(b, a) = (a, b)

6、函数参数

(1)不可变和可变的参数

在函数内部,针对参数使用赋值语句,会不会影响调用函数时传递的 实参变量?——不会。只要传递的参数使用赋值语句,会在函数内部修改局部变量的引用,不会影响到外部变量的引用。

def demo(num,num_list):
	num = 100
	num_list = [1, 2, 3]
	print(num)
	print(num_list)
gl_num = 99
gl_list = [4, 5, 6]
demo(gl_num,gl_list)  # 100, [1, 2, 3]
print(gl_num)  # 99
print(gl_list)  # [4, 5, 6]

输出:
在这里插入图片描述

在函数内部,针对 可变类型 的数据,使用 方法 修改了数据,会影响

def demo(num_list):
	num_list.append(9)
gl_list = [1, 2, 3]
demo(gl_list)
print(gl_list)  # gl_list发生了变化

输出:
在这里插入图片描述
在python中,列表变量调用+=本质上是在执行列表变量的extend方法,不是先相加再赋值,不会修改变量的引用。

def demo(num, num_list):
    num += num
    num_list += num_list
    print(num)
    print(num_list)
gl_num = 9
gl_list = [4, 5, 6]
demo(gl_num,gl_list)  
print(gl_num)  
print(gl_list) 

在这里插入图片描述

(2)缺省(读作:sheng 三声)参数

定义函数时,可以给 某个参数 指定一个 默认值,具有默认值的参数就叫做 缺省参数
调用函数时,如果没有传入 缺省参数 的值,则在函数内部使用定义函数时就指定的 参数默认值
函数的缺省参数:将常见的值设置为参数的缺省值,从而简化函数的调用。

例如:

a_list.sort() # 默认reverse = False,为升序排序
a_list.sort(reverse = True) # 如果想降序排序,就需要指定参数。

指定函数的缺省参数

在参数后使用赋值语句,如gender = True,可以指定参数的缺省值。
注意
①应该使用最常见的值作为默认值。如果某个参数的值不能确定,则不能设置默认值,应当在具体使用时直接调用。
②在函数参数定义时,缺省参数,也就是有默认值的参数,应当位于参数列表的末尾。否则会报错。

def print_info(name, gender = True):  # 指定`gender`的默认值为True

	gender_text = "男生"
	if not gender:
		gender_text = "女生"
	
	print("%s 是 %s" %(name, gender_text))

(3)多值参数

有时候 一个函数 能够处理的参数个数是不确定的,这个时候就应该使用多值参数

①python中有两种多值参数:
参数名前增加一个*可以接收 元组
参数名前增加两个*可以接收 字典
②一般在给多值参数命名时,习惯使用以下两个名字
*args——是argumrnt的缩写,有变量的含义,前面有一个*
**kwargs——kwkeyword的缩写,kwarg可以记忆 键值对参数。存放 字典 参数,前面有两个**

例:

def demo(num, *nums, **person):
    print(num)
    print(nums)
    print(person)
demo(1)# 调用函数时,不需要指定参数
demo(1, 2, 3, 4, 5, name="Yilia", age=18)

输出:
demo(1)时:
在这里插入图片描述
demo(1, 2, 3, 4, 5, name=“Yilia”, age=18)时:
在这里插入图片描述

def sum_number(*args):
	num = 0
	print(args)
	# 使用循环遍历进行累加
	for i in args:
		num += i
	return num
	
result = sum_number(1, 2, 3, 4, 5)
print(result)

输出:
在这里插入图片描述

def sum_number(args):  # 如果不使用*
	num = 0
	print(args)
	# 使用循环遍历进行累加
	for i in args:
		num += i
	return num
	
result = sum_number((1, 2, 3, 4, 5))
print(result)
result_1 = sum_number(1, 2, 3, 4, 5)
print(result_1)

输出:会看到,如果直接以元组的形式(1, 2, 3, 4, 5)传进5个参数,会报错。如果将整体打包成元组(1, 2, 3, 4, 5),会成功输出结果。
在这里插入图片描述

元组和字典的拆包

在调用带有多值参数的函数时,如果希望:

将一个 元组变量,直接传递给args
将一个 字典变量,直接传递给kwargs

就可以使用拆包,简化参数的传递。拆包的方式是:

在 元组变量前,增加一个*
在字典变量前,增加 两个*

def demo(*args, **kwargs):

	    print(*args)
	    print(**kwargs)
	    
gl_nums = {1, 2, 3}
gl_dict = {"name": "Yillia", "age": 18}

demo(gl_nums, gl_dict)
demo(*gl_nums, **gl_dict)

输出:如果不使用拆包,demo中的内容会作为一个整体传给args。
在这里插入图片描述
如果想不使用拆包也可以正确传递,需要这样输入:

demo(1, 2, 3,“name”: “Yillia”, “age”: 18)

(4)递归

在函数内部,让函数自己调自己。

①函数内部的 代码 是相同的,只是针对 参数 不同,处理的结果不同。
②当参数满足一个条件时,函数不再执行。这个非常重要,通常被称为递归的出口,否则会 出现死循环
③在处理 不确定的循环条件时 格外有用。例如:遍历整个文件目录的结构

例:

def sum_number(num):
	print(num)
	
	# 递归的出口
	if num == 1:
		return  # 执行完return后,下方的代码不会执行
		
	# 自己调自己
	sum_number(num - 1)  
	
sum_number(3)

输出:
在这里插入图片描述
应用:定义一个函数sum_numbers,能够接受num的整数参数,计算1+2+...+num的结果。

def sum_number(num):
	# 出口
	if num == 1:
		return 1
	
	# 只要不满足出口条件,就一直递归
	temp = sum_number(num - 1)  # 这里sum_number()的调用非常关键
	return num + temp
	
a = int(input("请输入num:"))
result = sum_number(a)
print(result)

输出:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值