Python学习第八课 变量进阶(理解)

变量进阶(理解)

目标

● 变量的引用
● 可变和不可变类型
● 局部变量和全局变量

01.变量的引用

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

1.1 引用的概念

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

1.2 函数的参数和返回值的传递

● 在Python中,函数的实参/返回值都是靠引用来传递的

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)))

02.可变和不可变类型

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

# 列表
my_list = [1, 2, 3]

print("定义列表 %s 后的内存地址为 %d" % (my_list, id(my_list)))
# 新增列表数据
my_list.append(999)
print("新增数据后的列表 %s 的内存地址为 %d" % (my_list, id(my_list)))
# 删除列表数据
my_list.pop(2)
print("删除数据后的列表 %s 的内存地址为 %d" % (my_list, id(my_list)))

my_list.remove(999)
print("删除数据后的列表 %s 的内存地址为 %d" % (my_list, id(my_list)))
# 清空列表数据
my_list.clear()
print("清空数据后的列表 %s 的内存地址为 %d" % (my_list, id(my_list)))
# 重新给列表赋值
my_list = []
print("重新给列表赋值后,列表 %s 的内存地址为 %d" % (my_list, id(my_list)))

# 字典
my_dict = {"name": "小明"}
print("定义字典 %s 后的内存地址为 %d" % (my_dict, id(my_dict)))

# 新增字典键值对
my_dict["age"] = 18
my_dict["phone"] = "12345667"
print("新增键值对后,字典 %s 的内存地址为 %d" % (my_dict, id(my_dict)))
# 删除字键值对
my_dict.pop("name")
print("删除键值对后,字典 %s 的内存地址为 %d" % (my_dict, id(my_dict)))
# 清空字典键值对
my_dict.clear()
print("清空字典后,字典 %s 的内存地址为 %d" % (my_dict, id(my_dict)))
# 给字典重新赋值
my_dict = {}
print("给字典重新赋值后,字典 %s 的内存地址为 %d" % (my_dict, id(my_dict)))

注意
字典的key 只能使用不可变类型的数据
1、可变类型的数据变化,是通过方法来实现的
2、如果给一个可变类型的变量,赋值了一个新的数据,引用会修改
● 变量不再对之前的数据引用
● 变量改为对新赋值的数据引用

哈希(hash)

● Python中内置有一个名字叫做hash(o)的函数
接收一个不可变类型的数据作为参数
返回结果是一个整数
● 哈希是一种算法,其作用就是提取数据的特征码(指纹)
相同的内容得到相同的结果
不同的内容得到不同的结果
● 在Python中,设置字典的键值对时,会首先对 key 进行hash 已决定如何在内存中保存数据,以方便后续对字典的操作(增删改查)
键值对的 key 必须是不可变类型数据
键值对的 value 可以是任意类型的数据

03.局部变量和全局变量

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

3.1 局部变量

● 局部变量是在函数内部定义的变量,只能在函数内部使用
● 函数执行结束后,函数内部的局部变量,会被系统收回
● 不同的函数,可以定义相同的名字的局部变量,但是各用各的不会产生影响

局部变量的作用
● 在函数内部使用,临时保存函数内部需要使用的数据

def demo1():

    # 定义一个局部变量
    num = 10
    print("在demo1 函数中的变量是 %d" % num)


def demo2():
    # print("%d" % num)
    pass


# 在函数内部定义的变量,不能在其他位置使用
# print("%d" % num)
demo1()
demo2()

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

扫描二维码关注公众号,回复: 5953565 查看本文章
3.2 全局变量

● 全局变量是函数外部定义的变量,所有函数内部都可以使用这个变量

# 定义一个全局变量
num = 10

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


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


demo1()
demo2()
print("over!")

注意
函数执行时,需要处理变量时会:
1、首先查找函数内部是否存在指定名称的全局变量,如果有,直接使用
2、如果没有,查找函数外部是否存在指定名称的全局变量,如果有,直接使用
3、如果没有,程序报错

1)函数不能直接修改全局变量的引用
● 全局变量是在函数外部定义的变量(没有蒂尼在某一个函数内),所有函数内部都可以使用这个变量
● 在函数内部,可以通过全局变量的引用获取对应的数据
● 但是,不允许直接修改全局变量的引用——使用赋值语句修改全局变量的值

# 定义一个全局变量
num = 10


def demo1():
    print("demo1" + "-" * 50)
    # 只是定义一个局部变量,不会修改到全局变量,只是变量名相同而已
    num = 100
    print("demo1 == %d" % num)


def demo2():
    print("demo2" + "-" * 50)
    print("demo2 == %d" % num)


demo1()
demo2()
print("over!")

2)在函数内部修改全局变量的值

● 如果在函数中需要修改全局变量的值,需要使用global 进行声明

# 定义一个全局变量
num = 10


def demo1():
    print("demo1" + "-" * 50)

    # global 关键字,告诉Python解释器 num是一个全局变量
    global num
    # 只是定义一个局部变量,不会修改到全局变量,只是变量名相同而已
    num = 100
    print("demo1 == %d" % num)


def demo2():
    print("demo2" + "-" * 50)
    print("demo2 == %d" % num)


demo1()
demo2()
print("over!")

3)全局变量定义的位置

a = 10


def demo():
    print("%d" % a)
    print("%d" % b)
    print("%d" % c)

b = 20
demo()
c = 30

注意
● 由于全局变量c,是在调用之后才定义的,在执行函数时,变量还没有定义,所以程序会报错!

4)全局变量的命名建议
● 为了避免局部变量和全局变量出现混淆,在定义时:建议全局变量前加上g_或者gl_的前缀

猜你喜欢

转载自blog.csdn.net/weixin_42057995/article/details/89300017