Python学习笔记——变量进阶

本学习笔记基于 Bilibili视频网站up主—黑马程序员的Python视频教程
链接:https://www.bilibili.com/video/av14184325

变量进阶

1 变量的引用

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

引用的概念

  • 变量 和 数据 是分开存储的
  • 数据 保存在 内存 中的一个位置
  • 变量 中保存着数据在内存中的地址
  • 变量 中记录数据的地址,就叫做***引用***
  • 使用id()函数可以查看变量中保存数据所在的 内存地址

◊注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是 修改了数据的引用

def test(num):
    print('在函数内部 %d 对应的内存地址是 %d' % (num, id(num)))

    # 1> 定义一个字符串变量
    result = 'hello'

    print("函数要返回数据的内存地址是 %d" % id(result))
    # 2> 将字符串变量返回
    return result

# 1. 定义一个数字的变量
a = 10

# 数据的地址本质上就是一个数字
print('a 变量保存数据的内存地址是 %d' % id(a))

# 2. 调用test函数,本质上传递的是实参保存数据的引用,而不是实参保存的数据
# 注意:如果函数有返回值,但是没有定义变量接收
# 程序不会报错,但是无法获得返回结果
r = test(a)
print('%s 的内存地址是 %d' % (r,id(r)))

上述程序的执行结果是:
a 变量保存数据的内存地址是 1908698416
在函数内部 10 对应的内存地址是 1908698416
函数要返回数据的内存地址是 1469963397584
hello 的内存地址是 1469963397584


由结果可知,不论是变量传入函数,还是函数的返回值,只要数据值不变,其地址是不变的。
函数的 实参/返回值 都是是靠 引用 来传递来的

2 可变和不可变类型

  • 不可变类型,内存中的数据不允许被修改:
    • 数字类型 int, bool, float, complex, long(2.x)
    • 字符串 str
    • 元组 tuple
  • 可变类型,内存中的数据可以被修改:
    • 列表 list
    • 字典 dict

| 注意:字典的 key 只能使用不可变类型的数据
使用方法对可变类型的变量进行修改,不会改变其地址

哈希hash

  • python中内置有一个 hash()的函数
    • 接收一个 不可变类型 的数据作为 参数
    • 返回 结果是一个 整数
  • 哈希 是一种 算法,其作用就是提取数据的 特征码(指纹)
  • 设置字典的键值对时,会首先对 key 进行 hash来决定如何在内存中保存字典的数据,以方便后续对字典的操作:增、删、改、查

3 局部变量和全局变量

局部变量:在函数内部定义的变量,只能在函数内部使用
全局变量:在函数外部定义的变量,所有函数内部都可以使用

** 注意!函数执行时处理变量的过程:**

  1. 首先查找 函数内部 是否存在指定名称的 局部变量,如果有就直接使用
  2. 如果没有,查找 函数外部 是否存在 指定名称的 全局变量,如果有就直接使用
  3. 如果仍没有,程序报错

局部变量
局部变量的生命周期:

def demo1():

    # 定义一个局部变量
    # 1> 变量的出生:执行了下方代码后,才会被创建
    # 2> 死亡:函数执行结束后被系统回收
    num = 10

    print('在demo1函数内部的变量是 %d' % num)
    
demo1()
  • 局部变量 是在 函数内部 定义的变量,只能在函数内部使用
  • 函数执行结束后,函数内部的局部变量会被系统回收
  • 不同的函数可以定义相同名字的局部变量,但是彼此之间不会产生影响

全局变量

  • 全局变量是在 函数外部定义 的变量,所有函数都可以使用这个变量
  • 在函数内部,可以 通过全局变量的引用获取对应的数据
  • 无法在函数内部直接修改全局变量的值
在函数内部修改全局变量的值

如果在函数内部需要修改 全局变量 的值,使用 global关键字:

# 全局变量
num = 10


def demo1():

    # 想要修改全局变量的值 - 使用global声明一下变量即可
    # global关键字 会告诉解释器后面的变量是一个全局变量
    global  num
    num = 99
    print('demo1 ==> %d' % num)

def demo2():

    print('demo2 ==> %d' % num)

demo1()
demo2()

程序输出的结果:
demo1 ==> 99 demo2 ==> 99

在编写代码时,我们需要在代码一开始就 定义完成全局变量,否则若在执行函数时变量没有定义,程序就会报错。

代码结构示意图
shebang
import模块
全局变量
执行代码

全局变量命名的建议:
全局变量名之前应该加g_gl_的前缀

4 函数的返回值

利用 元组 返回多个返回值:

def measure():
    """测量温度和湿度"""

    print('begin...')
    temp = 39
    print('over...')
    wetness = 50
    # 元组可以包含多个数据,可以让函数返回多个值
    # return (temp,wetness)可以省略括号
    return temp,wetness

result = measure()
print(result)
# 需要单独的处理温度或者湿度
# 如果函数返回的类型是元组,同时希望单独的处理元组中的元素
# 可以使用多个变量,一次接收函数的返回结果
# 注意:使用多个变量接收结果时,变量的个数应该和元组中元素的个数保持一致
gl_temp, gl_wewtness = measure()

print(gl_temp)
print(gl_wewtness)

交换两个变量的值

a = 6
b = 100

# 解法1: 使用其他变量
c = a
a = b
b = c

# 解法2: 不使用其他变量
a = a + b
b = a - b
a = a - b

# 解法3: Python 专有解法
# 等号右边是元组,只是省略了小括号
a, b = b, a

print(a)
print(b)

5 函数的参数 进阶

不可变 和 可变 的参数
无论传递的参数是 可变(list、dict) 还是 不可变(数字),
只要针对参数使用赋值语句,会在 函数内部 修改 局部变量 的引用,不会影响到 外部变量 的引用。

如果传递的参数是可变类型(list、dict),在函数内部,使用 方法 修改数据的内容,同样会影响到外部实参。

def demo(num_list):
    print('函数内部的代码')

    # 使用方法修改列表的内容
    num_list.append(9)

    print(num_list)

    print('函数执行完成')

gl_list = [1,2,3]
demo(gl_list)
print(gl_list)

这段代码的输出结果是:
函数内部的代码 [1, 2, 3, 9] 函数执行完成 [1, 2, 3, 9]

例外情况: +=

“+=” 符号

  • 对于数字变量而言,是赋值操作,即将左右两边的变量相加再赋值给左边的变量
  • 对于列表变量而言,是方法操作,本质上是在调用列表的 extend方法,即:左边.extend(右边)
    O因此,在函数内部对传入的参数使用 += 符号时,若传入的参数是数字变量,则对外部实参没有影响;如果传入的参数是 列表变量,则会对外部实参有影响。
def demo(num,num_list):
    print('begin')

	#对 数字变量使用 +=
	# num = num + num
    num += num
    
    # 对列表变量使用 += 不是 相加再赋值 !
    # 本质上是在调用列表的 extend 方法
    # num_list.extend(num_list)
    num_list += num_list
    print(num)
    print(num_list)
    print('over')

gl_num = 9
gl_list = [1, 2, 3]
demo(gl_num,gl_list)
print(gl_num)
print(gl_list)

这段代码的输出结果是:

begin
18
[1, 2, 3, 1, 2, 3]
over
9
[1, 2, 3, 1, 2, 3]

缺省参数
具有默认值的参数就是 缺省参数

指定函数的缺省参数:

  • 在参数后使用赋值语句,可以指定参数的缺省值(默认值)
    def func(name, gender=True)
  • 缺省参数的注意事项:
    • 在函数的参数列表中,带有默认值的缺省参数必须放在列表末尾
      错误示例def func(name, gender=True, title)
    • 调用带有多个缺省参数的函数时,需要指定参数名来赋值
      func('小明',gender=False)
def print_info(name, title='学生', gender=True):
    """

    :param tiele: 职位
    :param name: 班上同学的姓名
    :param gender:True 男生  False 女生
    """

    gender_text = '男生'

    if not gender:
        gender_text = '女生'

    print('[%s]%s 是 %s' % (title, name, gender_text))

print_info('小明')
print_info('小美',gender = False)

6 多值参数

有时可以能需要函数处理的参数的个数是不确定的,此时就可以使用多值参数

python中有 两种 多值参数:

  • 参数名前增加 * 可以接收 元组
  • 参数名前增加 ** 可以接收 字典

一般在给多值参数命名时,习惯使用以下两个名字

  • *args – arguments变量的缩写
  • **kwargs – keyword键值对的缩写

多值参数案例:

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)

这段代码的输出结果是:

(1, 2, 3, 4, 5)
15

元组和字典的拆包:
在调用带有多值参数的函数时,如果希望

  • 将一个 元组变量,直接传递给 args
  • 将一个 字典变量,直接传递给 kwargs
    就可以使用 拆包,简化参数的传递:
    • 在元组变量前增加 *
    • 在字典变量前增加 **
7 函数的递归

一个函数 在内部调用自己 就是递归。
代码特点:
函数内部的 代码 时相同的,只是针对参数的不同,处理的结果不同
当 参数 满足一个条件时,函数不再执行(就是 递归的出口)
下面为两个函数递归调用的例子:

def sum_number(num):

    print(num)

    #递归的出口:当参数满足某个条件时,不再执行函数
    if num == 1:
        return
    # 自己调用自己
    sum_number(num - 1)

sum_number(3)
# 定义一个函数计算1 + 2 + ... + num 的结果
def sum_numbers(num):

    # 1. 出口
    if num == 1:
        return 1

    # 2. 数字的累加
    temp = sum_numbers(num - 1)

    return num + temp

result = sum_numbers(100)
print(result)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值