python入门(8)变量进阶、函数的参数和返回值、递归
一、变量的引用
变量和数据都是保存在内存中的,在python中函数的参数传递以及返回值都是靠引用传递的
- 引用的概念
变量和数据是分开存储的, 数据保存在内存中的一个位置, 变量中保存着数据在内存中的地址, 变量中记录数据的地址,就叫做引用 使用id()函数可以查看变量中保存数据所在的内存地址 **注意:**如果变量已经被定义,当给一个变量赋值的时候,本质上是修改了数据的引用,变量不再对之前的数据引用,变量改为对新赋值的数据引用
案例代码:
def test(num):
print("在函数内部 %d 对应的内存地址是 %d" % (num,id(num)))
result = "hello"
print("函数要返回数据 hello 的内存地址是 %d " % id(result))
return result
a = 10
print("a 变量值为 10 保存数据的内存地址是 %d " % id(a))
r = test(a)
print("%s 的内存地址是 %d " % (r,id(r)))
运行结果:
二、可变和不可变类型
- 不可变类型
内存中的数据不允许被修改 数字类型:int ,bool,float,complex,long(2,x) 字符串:str 元组tuple - 可变类型
内存中的数据可以被修改 列表list 字典dict - 注意
字典中的key只能使用不可变类型的数据 可变类型的数据变化是通过方法来实现的 如果给一个可变类型的变量赋值了一个新的数据,引用会修改,变量不再对之前的数据引用,变量改为对新赋值的数据引用 - hash(哈希)
python中内置有一个名字叫做hash(o) 的函数,接收一个不可变类型的数据作为参数,返回结果是一个整数。 哈希是一种算法,其作用就是提取数据的特征码,相同的内容得到相同的结果,不同的内容得到不同的结果。 在python中,设置字典的键值对时,会首先对key进行hash以决定如何在内存中保存字典的数据,以方便后续对字典的操作:增删查改;键值对的key必须是不可变类型的数据,键值对的value可以是任意类型的数据。
三、局部变量和全局变量
局部变量:在函数内部定义的变量,只能在函数内部使用 全局变量:在函数外部定义的变量(没有定义在某一个函数内),所有函数内部都可以使用这个变量。 提示:在其他开发语言中,大多不推荐使用全局变量—可变范围太大,导致程序不好维护!
1.局部变量
- 局部变量是在函数内部定义的变量,只能在函数内部使用;
- 函数执行结束后,函数内部的局部变量,会被系统回收;
- 不同的函数,可以定义相同的名字的局部变量,但是各用各的不会产生影响
- 局部变量的作用:在函数内部使用,临时保存函数内部需要使用的数据
- 局部变量案例
def demo1():
num = 10
print("在demo1函数内部的变量是 %d" % num)
demo1()
- 局部变量的生命周期
生命周期:是变量从被创建到系统回收的过程 局部变量在函数执行时才会被创建,函数执行结束后局部变量被系统回收 局部变量在生命周期内,可以用来存储函数内部临时使用到的数据
2.全局变量
num = 10
def demo1():
print("demo1 ===》 %d" % num)
def demo2():
print("demo2 ===》 %d" % num)
demo1()
demo2()
- 函数不能直接修改全局变量的引用
全局变量是在函数外部定义的变量(没有定义在某一个函数内),所有函数内部都可以使用这个变量。 在函数内部,可以通过全局变量的引用获取到对应的数据 但是,不允许直接修改全局变量的引用—使用赋值语句修改全局变量的值
num = 10
def demo1():
num = 99
print("demo1 ===》 %d" % num)
def demo2():
print("demo2 ===》 %d" % num)
demo1()
demo2()
运行截图:
- 在函数内部修改全局变量的值
如果在函数中需要修改全局变量,需要使用global进行声明
num = 10
def demo1():
global num
num = 99
print("demo1 ===》 %d" % num)
def demo2():
print("demo2 ===》 %d" % num)
demo1()
demo2()
运行截图:
- 全局变量定义的位置
在开发时,应该把模块中的全局变量都定义在所有函数的上方,就可以保证所有的函数,都能够正常的访问到每一个全局变量了。 shebang标识用哪个解释器解释当前的代码 - 全局变量命名的建议
为了避免局部变量和全局变量出现混淆,在定义全局变量时,有些公司会有一些开发要求,例如:全局变量名前应该增加g_ 或者gl_ 的前缀
gl_num = 10
def demo():
num = 99
print("demo1 ===》 %d" % num)
print("全局变量 ===》 %d" % gl_num)
demo()
运行截图:
四、函数参数和返回值的作用
- 如果函数内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部
- 如果希望一个函数执行完毕后,向外界汇报执行结果,就可以增加函数的返回值
五、函数的返回值
- 函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理。
- 返回值是函数完成工作后,最后给调用者的一个结果
- 在函数中使用return关键字可以返回结果
- 调用函数一方可以使用变量来接收函数的返回结果
- 案例:使用元组同时返回多个变量,温度和湿度测量,同时返回温度和湿度
元组-可以包含多个数据,因此可以使用元组让函数一次返回多个值 如果函数返回的类型是元组,小括号可以省略
def measure():
"""测量温度和湿度"""
print("测量开始。。。")
temp = 39
wetness = 50
print("测量结束。。。")
return temp, wetness
result = measure()
print(result)
- 接收返回元组函数的方式
如果函数返回的类型是元组,同时希望单独的处理元组中的元素,可以使用多个变量,一次接收函数的返回结果,注意:使用多个变量接收结果时,变量的个数应该和元组中元素的个数保持一致。
def measure():
"""测量温度和湿度"""
print("测量开始。。。")
temp = 39
wetness = 50
print("测量结束。。。")
return temp, wetness
gl_temp,gl_wetness = measure()
print(gl_temp)
print(gl_wetness)
a = 6
b = 100
c = a
a = b
b = c
print(a)
print(b)
解法2–不使用其他变量
a = 6
b = 100
a = a + b
b = a - b
a = a - b
print(a)
print(b)
解法3 --python专有
a = 6
b = 100
a,b = b,a
print(a)
print(b)
六、函数的参数
- 无论传递的参数是可变还是不可变的,只要针对参数使用赋值语句,会在函数内部修改局部变量的引用,不会影响到外部变量的引用
def demo(num,num_list):
print("函数内部的代码")
num = 100
num_list = [1,2,3]
print("num = %d " % num)
print(num_list)
print("函数执行完成")
gl_num = 99
gl_num_list = [4,5,6]
demo(gl_num,gl_num_list)
print("gl_num = %d " % gl_num)
print(gl_num_list)
运行截图:
- 如果传递的参数是可变类型,在函数内部,使用方法修改了数据的内容,同样会影响到外部的数据。
def demo(num_list):
print("函数内部的代码")
num_list.append(9)
print(num_list)
print("函数执行完成")
gl_list = [4,5,6]
print(gl_list)
demo(gl_list)
print(gl_list)
运行截图:
- +=
在python中,列表变量调用+=本质上是在执行列表变量的extend方法,不会修改变量的引用。
def demo(num,num_list):
print("函数开始")
num += num
num_list += num_list
print(num)
print(num_list)
print("函数完成")
gl_num = 9
gl_list = [4,5,6]
demo(gl_num,gl_list)
print(gl_num)
print(gl_list)
运行截图:
七、缺省参数
- 定义函数时,可以给某个参数指定一个默认值,具有默认值的参数就叫做缺省参数
- 调用函数时,如果没有传入缺省参数的值,则在函数内部使用定义函数时指定的参数默认值
- 函数的缺省参数,将常见的值设置为参数的缺省值,从而简化函数的调用
- 例如,对列表排序的方法
gl_list = [4,2,7]
gl_list.sort()
print(gl_list)
gl_list.sort(reverse=True)
print(gl_list)
运行截图:
- 指定函数的缺省参数
在参数后使用赋值语句,可以指定参数的缺省值。 提示:缺省参数,需要使用最常见的值作为默认值!如果一个参数的值不能确定,则不应该设置默认值,具体的数值在调用函数时,由外界传递。
def print_info(name,gender=True):
"""
:param name: 班上同学的姓名
:param gender: True 男生 False 女生
"""
gender_text = "男生"
if not gender:
gender_text = "女生"
print("%s 是 %s " % (name,gender_text))
print_info("小明")
print_info("小王")
print_info("小美",False)
- 缺省参数的注意事项
缺省参数的定义位置:必须保证带有默认值的缺省参数在参数列表末尾 错误案例:def print_info(name,gender=True,title) 调用带有多个缺省参数的函数,在调用函数时,如果有多个缺省参数,需要指定参数名,这样解释器才能够知道参数的对应关系。
def print_info(name,gender=True):
"""
:param name: 班上同学的姓名
:param gender: True 男生 False 女生
"""
gender_text = "男生"
if not gender:
gender_text = "女生"
print("%s 是 %s " % (name,gender_text))
print_info("小明")
print_info("小王")
print_info("小美",False)
运行截图:
八、多值参数
1.定义支持多值参数的函数
- 有时可能需要一个函数能够处理的参数个数是不确定的,这个时候,就可以使用多值参数
- python中有两种多值参数:参数名前增加一个
* 可以接收元组,参数名前增加两个* 可以接收字典 - 一般在给多值参数命名时,习惯使用以下两个名字;
*args ----存放元组参数,前面有一个* ,args是arguments的缩写,有变量的含义 **kwargs —存放字典参数,前面有两个* ,kw是keyword的缩写,kwargs可以记忆键值对参数
def demo(num,*nums,**person):
print(num)
print(nums)
print(person)
demo(1,2,3,name = "小明",age = 18)
运行截图:
2.多值参数案例–计算任意多个数字的和
需求:定义一个函数sum_numbers,可接收任意多个整数,功能要求:将传递的所有数字累加并且返回累加结果 代码:
def sum_numbers(*args):
num = 0
print(args)
for n in args:
num += n
return num
result = sum_numbers(1,2,3,4,5)
print(result)
运行截图:
3.元组和字典的拆包
在调用带有多值参数的函数时,如果希望将一个元组变量,直接传递给args,将一个字典变量,直接传递给kwargs,就可以使用拆包,简化参数的传递, 拆包的方式是:在元组变量前,增加一个* ,在字典变量前,增加两个*
def demo(*args,**kwargs):
print(args)
print(kwargs)
gl_list = (1,2,3)
gl_dict = {"name":"小明","age":18}
demo(*gl_dict,**gl_dict)
运行截图:
九、递归
函数调用自身的编程技巧称为递归
1.递归函数的特点
一个函数内部调用自己,函数内部可以调用其他函数,当然在函数内部也可以调用自己
- 代码特点
函数内部的代码是相同的,只是针对参数不同,处理的结果不同 当参数满足一个条件时,函数不再执行(这个非常重要通常被称为递归的出口,否则会出现死循环) - 案例介绍:使用递归打印3,2,1
def sum_sumbers(num):
print(num)
if num == 1:
return
sum_sumbers(num - 1)
sum_sumbers(3)
运行截图: 代码执行流程图:
- 递归案例–计算数字累加
需求:定义一个函数sum_numbers,能够接收一个num的整数参数,计算1+2+3+。。num的结果
def sum_sumbers(num):
if num == 1:
return 1
temp = sum_sumbers(num - 1)
return num + temp
result = sum_sumbers(10)
print(result)
累加运行流程图: 提示:递归是一个编程技巧,初次接触递归会感觉有些吃力,在处理不确定的循环条件时,格外的有用,例如遍历整个文件目录的结构。
|