变量进阶
变量的引用
变量 和 数据 是分开存储的,数据保存在内存中的一个地址,变量中保存着数据在内存中的地址,即 引用。
使用 id()
函数可以查看变量中保存数据所在的内存地址。

给变量赋值本质上就是修改数据的引用。
函数的 实参 / 返回值 就是靠 引用 来传递数据的。
def test(num):
print("-" * 50)
print("%d 在函数内的内存地址是 %x" % (num, id(num)))
result = 100
print("返回值 %d 在内存中的地址是 %x" % (result, id(result)))
print("-" * 50)
return result
a = 10
print("调用函数前 a 的内存地址是 %x" % id(a))
r = test(a)
print("调用函数后 a 的内存地址是 %x" % id(a))
print("调用函数后 返回值内存地址是 %x" % id(r))

可变类型 和 不可变类型
可变类型:列表、字典
不可变类型:
- 数字类型
int
、bool
、float
、complex
、long
- 字符串
str
- 元组
tuple
字典的 key
只能使用不可变类型的数据。
哈希哈希
是一种 算法,其作用就是提取数据的 特征码(指纹),相同的内容得到相同的结果,不同的内容得到不同的结果。
Python
中内置有一个名字叫做 hash(o)
的函数。它接收一个 不可变类型 的数据作为 参数,返回一个整数。
设置字典的 键值对 时,会首先对 key
进行 hash
,所以字典的 key
必须是不可变类型。
哈希决定了如何在内存中保存字典的数据,以方便后续对字典的增、删、改、查。

局部变量 和 全局变量
局部变量:定义在函数内部的变量,只能在函数内部使用。
全局变量:在函数外部定义的变量,所有位置都可以使用这个变量。
- 局部变量的生命周期:函数执行期间。
- 不同函数内部可以定义同名的局部变量。
- 函数内部无法直接修改全局变量,只会修改局部变量。想在函数内部修改全局变量,需要用
global
关键字。 - 全局变量命名建议:前面增加
g_
或者gl_
的前缀。 - 代码结构
- shebang
import
- 全局变量
- 函数
- 代码
函数进阶
函数参数和返回值
- 想同时返回多个参数时,可以返回元组。返回元组时,小括号应省略,如
但是通过元组传递结果时,需要找到准确的下标,才能得到想要的结果:def measure(): temp = 39 wetness = 10 return temp, wetness
因此可以定义全局变量来接收元组结果:result = measure() print(result[0]) print(result[1])
这种形式需要 变量数量 与 函数返回数量 一致。gl_temp, gl_wetness = measure() print(gl_temp) print(gl_wetness)
交换两个变量 —— Python 专用,利用元组
a, b = (b, a)
小括号可以省略。
可变参数与不可变参数
在函数内部,针对 参数 使用赋值语句,不会影响调用函数时传递的 实参变量。
针对参数使用赋值语句,会在函数内部修改局部变量的引用,不会影响到外部变量的引用。
def demo(num):
num = 200
gl_num = 99
demo(gl_num)
print(gl_num)
输出结果:99
如果传递的参数是 可变类型,在函数内部使用 方法 修改了数据的内容,会影响到外部的数据:
def mutable(num_list):
num_list.extend([1, 2, 3])
print(num_list)
gl_list = [6, 7, 8]
mutable(gl_list)
print(gl_list)
输出结果:
[6, 7, 8, 1, 2, 3]
[6, 7, 8, 1, 2, 3]
另外,对于列表,+=
相当于 extend
:
def demo(num_list):
num_list += num_list
print(num_list)
gl_list = [1, 2, 3]
demo(gl_list)
print(gl_list)
输出结果:
[1, 2, 3, 1, 2, 3]
[1, 2, 3, 1, 2, 3]
缺省参数
定义函数时,可以给某个参数指定一个默认值,即 缺省参数。调用函数时,如果没有传入缺省参数的值,则在函数内部使用定义函数时指定的 参数默认值,否则使用传入的值。
如
gl_num_list = [6, 3, 9]
gl_num_list.sort() # 缺省参数 reverse = False
gl_num_list.sort(reverse=True)
def print_info(name, gender=True):
gender_text = "男生"
if not gender:
gender_text = "女生"
print("%s 是 %s" % (name, gender_text))
必须保证带有默认值的缺省参数在 参数列表末尾。
错误示例:
def print_info(name, gender=True, title):
多值参数
有时一个函数需要处理的参数个数可能是不确定的,这时就可以用多值参数。
- 参数名前增加 1个
*
可以接收 元组 - 参数名前增加 2个
*
可以接收 字典
在给多值参数命名时,习惯使用以下两个名字
*args
—— 存放 元组 参数,前面有一个*
args
是arguments
的缩写,有变量的含义
**kwargs
—— 存放 字典 参数,前面有两个*
kw
是keyword
的缩写,kwargs
意即键值对参数def demo(num, *nums, **person): print(num) print(nums) print(person) demo(1) demo(1, 2, 3, 4, 5, name="Anne")

多值参数案例 —— 计算任意多个数字的和:
def sum_numbers(*args):
num = 0
for n in args:
num += n
return num
result = sum_numbers(1, 2, 3, 4, 5)
元组和字典的拆包:
在调用带有多值参数的函数时,如果希望:
- 将一个 元组 变量,直接传递给
args
- 将一个 字典 变量,直接传递给
kwargs
就可以使用 拆包,简化参数的传递,方法:
- 在 元组 变量前,增加 一个
*
- 在 字典 变量前,增加 两个
*
def demo(*args, **kwargs): print(args) print(kwargs) gl_nums = (1, 2, 3) gl_dict = {"name": "小明", "age": 18} demo(gl_nums, gl_dict) print('-' * 50) demo(*gl_nums, **gl_dict)
函数的递归
def sum_numbers(num):
if num == 1:
return 1
return num + sum_numbers(num - 1)
print(sum_numbers(100))
输出:5050
