Python基础之变量进阶
变量的引用
- 变量和数据都是保存在内存中的;
- 在python中函数的参数传递以及返回值都是靠引用传递的。
函数引用的概念
在python中
- 变量和数据时分开存储的;
- 数据保存在内存中的一个位置;
- 变量保存着数据在内存中的地址;
- 变量中记录数据的地址,就叫做引用;
- 使用id()函数可以查看变量中保存数据所在的内存地址。
注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是自改了数据的引用;即变量不再对之前的数据引用;变量改为对新赋值的数据引用。
a = 1
id(a)
140721952793280
id(1)
140721952793280
b = a
id(b)
140721952793280
a = 2
id(a)
140721952793312
id(b)
140721952793280
b = a
id(b)
140721952793312
b = 2
id(b)
140721952793312
函数引用理解
我们可以把变量的名字理解为便签纸,而变量名和数据就相当于把便签纸贴在数据上;
当我们a = b时,就是把a,b两张标签纸贴在了同一个数据上,而如果我们把a重新赋值,就是把a的便签纸撕下来贴在另一个数据上,但b的便签纸位置不变;
函数传参与引用的关系
函数参数的传递,实际传送的是对应实参变量的引用,而不是实参保存的数据;
def test(num):
print("在函数内部%d对应的内存地址是%s" % (num, id(num)))
a = 10
print("a 变量保存数据的内存地址是 %s" % id(a))
test(a)
# a 变量保存数据的内存地址是 140722085962720
# 在函数内部10对应的内存地址是140722085962720
函数返回值与引用
函数的返回值同样也是返回变量的引用,而不是真实的数据;
数据地址本质上就是一个数字;
def test(num):
result = "test_password"
print("函数内返回值result的内存地址是 %s" % id(result))
return result
a = 10
r = test(a)
print("返回的 %s 的内存地址是 %s" % (r, id(r)))
# 函数内返回值result的内存地址是 2333111002800
# 返回的 test_password 的内存地址是 2333111002800
可变类型和不可变类型
修改可变类型 是修改数据的内容,而不会修改变量引用的地址;修改可变类型,要用对象.方法()进行修改;
重新赋值会修改变量引用的地址;
不可变类型,内存中的数据不允许被修改:
- 数字类型;
- 元组;
- 字符串;
可变类型,内存中的数据可以被修改:
- 列表;
- 字典;
可变类型修改和重赋值对引用的影响
可变类型比如列表,字典,对它们进行数据修改时,不会对引用的内存地址造成影响;
只有当我们对变量进行重新赋值之后,才会影响引用;
下面举例仅举列表的例子,字典一样,就不赘述了。
# 列表数据修改和重赋值对引用的影响
a = [1,2,3]
id(a)
1956997579272
a.append(4)
a
[1, 2, 3, 4]
id(a)
1956997579272
a.remove(2)
a
[1, 3, 4]
id(a)
1956997579272
a.clear()
a
[]
id(a)
1956997579272
a = ['a','s','d']
id(a)
1956997945160
字典的key只能使用不可变类型;
注意:可变类型的数据变化,是通过方法来是实现的;
哈希算法
d = {}
d["name"] = "zhangsan"
d
{'name': 'zhangsan'}
d[1] = "整数"
d
{'name': 'zhangsan', 1: '整数'}
d[(1,)] = "元组"
d
{'name': 'zhangsan', 1: '整数', (1,): '元组'}
d[[1,2,3]] = "列表"
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'list'
d[{"age":18}] = "字典"
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'dict'
- Python中内置一个名字叫做hash(o)的函数,它接收一个不可变类型的数据作为参数,返回结果是一个整数;
- 哈希是一种算法,其作用是提取数据的特征码(指纹);相同的数据得到相同的结果,不同的数据得到不同的结果;
- 在python中,设置字典的键值对时,会首先对key进行hash,以决定如何在内存中保存字典的数据,以方便后续的字典的增删改查;
- 字典 键值对的key必须是不可变类型数据;键值对的value可以是任意类型的数据;
哈希算法,只能哈希不可变类型;
因为字典的key要使用哈希,所以,字典的key只能是不可变类型;
hash(1)
1
hash("hello")
2061306992742373012
hash("hello python")
9189581639312291988
hash((1,2))
3713081631934410656
hash([1,2])
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'list'
hash({"age":18})
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'dict'
局部变量和全局变量
局部变量,就是在函数内部定义的变量,仅供函数内部使用;
全局变量,就是在函数外部定义的变量,所有函数内部都可以使用这个变量。
在其他语言中,大多都不推荐使用全局变量,因为可变范围太大,不可控情况多;
局部变量
局部变量介绍
- 局部变量是在函数内部定义的变量,只能在函数内部使用;
- 函数执行完成后,函数内部的局部变量,会被系统回收;
- 不同的函数,可以定义相同的名字的局部变量,彼此之间不会产生影响;
局部变量的作用:在函数内部使用,临时保存函数内部需要使用的数据;
局部变量只能在定义的函数内部使用,不能被函数外部或函数外部函数使用
def demo1():
num = 10
print("demo1内部的局部变量num的值为%d" % num)
# 因为num是num1的局部变量,而demo1外面也没有定义num变量,所以本句运行后会报错,注释掉
# print(num) # NameError: name 'num' is not defined
def demo2():
# 同样的,demo2重吗既没有num的变量,外部也没有定义全局的num变量,运行会报错,注释掉
# print(num) # NameError: name 'num' is not defined
pass
demo1() # demo1内部的局部变量num的值为10
demo2()
局部变量的生命周期
当局部变量被执行时创建;当函数执行完后局部变量被系统回收,生命结束;
局部变量在生命周期内可以用来临时存储信息。
用断点可以验证局部变量的生命周期。
不同函数内的同名局部变量
不同函数间可以定义相同名的局部变量,彼此之间互不关联,这就像1班有一个小明,2班也有一个小明,但他们并不是同一个人;
def demo1():
num = 10
print("demo1内部的局部变量num的值为%d" % num) # demo1内部的局部变量num的值为10
def demo2():
num = 100
print("demo2的num:", num) # demo2的num: 100
demo1()
demo2()
全局变量
全局变量的使用
在所有函数外部定义的变量,就叫做全局变量;
可以给全局所有代码调用,包括全局变量的平行级和下级函数内部;
num = 10
def demo1():
print("demo1的num", num)
def demo2():
print("demo2的num", num)
demo1()
demo2()
print(num)
# demo1的num 10
# demo2的num 10
# 10
函数内部不能直接修改全局变量的值
在函数内部,可以直接通过全局变量的引用获取对用的数据;
但是,在python中,函数内部不能直接修改全局变量的值,如果用全局变量名在函数内部重新赋值,本质上只是创建一个同名局部变量而已;
num = 10
def demo1():
# 这个语句 并不是修改全局变量的值,而是创建一个同名局部变量
num = 90
print("demo1的num", num)
def demo2():
print("demo2的num", num)
demo1()
demo2()
print(num)
# demo1的num 90
# demo2的num 10
# 10
变量查找顺序
注意:函数执行时,需要处理变量时 会:
- 先从函数内部找指定名称的局部变量,如果有,直接使用;
- 函数内部没找到变量,就去函数外部找指定名称的全局变量,如果有,直接使用;
- 还没找到,就报错;
用global在函数内修改全局变量
如果希望在函数内部修改全局变量的值,使用global声明一下变量即可;
global关键字会告诉解释器后面声明的变量是一个全局变量,这样,再使用赋值语句时,就不会创建局部变量了。
num = 10
def demo1():
# 告诉解释器,这个就是全局变量,不用再创建同名局部变量了
global num
num = 90
print("demo1的num", num)
def demo2():
print("demo2的num", num)
demo1()
demo2()
print(num)
# demo1的num 90
# demo2的num 90
# 90
全局变量定义的位置
- 在函数中要使用的变量必须在函数被调用前就被定义好,否则会报错;
- 一般讲所有的全局变量都放在其他函数的上方,这样可以确保每个函数都能正确的使用全局变量。
代码结构顺序:
- shebang
- import 模块
- 全局变量
- 函数定义
- 执行代码
全局变量命名的建议:全局变量建议在变量名前g_变量名 或者gl_变量名。
Python基础之变量进阶的更多相关文章
- python基础篇之进阶
python基础篇之进阶 参考博客:http://www.cnblogs.com/wupeiqi/articles/5115190.html python种类 1. cpython 使用c解释器生产 ...
- 十三. Python基础(13)--生成器进阶
十三. Python基础(13)--生成器进阶 1 ● send()方法 generator.send(value) Resumes the execution, and "sends&qu ...
- python基础8 - 变量2
1. 变量的引用 变量 和 数据 都是保存在 内存 中的 在 Python 中 函数 的 参数传递 以及 返回值 都是靠 引用 传递的 1.1 引用的概念 在 Python 中 变量 和 数据 是分开 ...
- python基础3 - 变量的基本使用和命名
4.变量的基本使用 4.1 变量定义 在 Python 中,每个变量 在使用前都必须赋值,变量 赋值以后 该变量 才会被创建 等号(=)用来给变量赋值 = 左边是变量名 = 右边是存储在变量中的值 变 ...
- Python基础——__name__变量
转自:https://blog.csdn.net/u011511601/article/details/53504355 Python使用缩进对齐组织代码的执行,所有没有缩进的代码,都会在载入时自动执 ...
- Python基础-2 变量与常量
变量与常量 变量:在程序运行过程中,值会发生变化的量 常量:在程序运行过程中,值不会发生变化的量 无论是变量还是常量,在创建时都会在内存中开辟一块空间,用于保存它的值. 这里有一点需要注意的是,在py ...
- Python基础02 变量
Python中的变量有两个特点: 1. 无需声明 a = 1 2. 不与类型绑定 a = 1 a = 'hello world' 变量名只是内存中具体对象的一个引用(reference). 对于 a ...
- 周末班:Python基础之面向对象进阶
面向对象进阶 类型判断 issubclass 首先,我们先看issubclass() 这个内置函数可以帮我们判断x类是否是y类型的子类. class Base: pass class Foo(Base ...
- 周末班:Python基础之函数进阶
迭代器和生成器 迭代和可迭代 什么是迭代(iteration)? 如果给定一个list或tuple,我们要想访问其中的某个元素,我们可以通过下标来,如果我们想要访问所有的元素,那我们可以用for循环来 ...
随机推荐
- luogu 3953 逛公园
noip2017 D1T3 逛公园 某zz选手看到数据范围直接就最短路计数了,结果写错了爆零 题目大意: N个点M条边构成的有向图,且没有自环和重边.其中1号点是起点,N号点是公园的终点,每条边有一个 ...
- 阿里Java开发规约笔记
借助阿里开发规约,回顾一下Java开发编码基础方面的知识,结合自己使用中遇到的问题,记录一下规约中以前翻过的错.有共鸣的问题. 1.覆写方法时要加上@Override注解.重写一个类型T的equals ...
- 重装Eclipse 往其中加Python插件时 遇到不能独立运行c c++ python 代码时修改办法:
鼠标移动到新建项目处 ,右键->run as-> run configuration->选择Enable auto build 即可.
- Hadoop 分布式环境slave节点重启忽然不好使了
Hadoop 分布式环境slaves节点重启: 忽然无法启动DataNode和NodeManager处理: 在master节点: vim /etc/hosts: 修改slave 节点的IP (这个时候 ...
- wrap(),wrapAll(),wrapInner()的区别
wrap从字面上理解就是包裹的意思,这三个函数也都是起到将内部节点进行包裹的作用,但是他们的各自的功能有又大不相同. 1. a.wrap(b) 这个函数的作用是用b将a进行包裹,其中a所选中的可以为 ...
- c#自定义ORM框架---(泛型&反射&实体类扩展属性<附带通用增、删、查、改>)
该教材主要是运用到泛型.反射和实体类扩展属性 步骤一.建立扩展属性类 实体类扩展属性要继承Attribute基类完成 [AttributeUsage(AttributeTargets.Property ...
- [LOJ#10132]异象石
Description Adera 是 Microsoft 应用商店中的一款解谜游戏. 异象石是进入 Adera 中异时空的引导物,在 Adera 的异时空中有一张地图.这张地图上 有 N 个点,有 ...
- 238 Product of Array Except Self 除自身以外数组的乘积
一个长度为 n 的整形数组nums,其中 n > 1,返回一个数组 output ,其中 output[i] 等于nums中除nums[i]以外所有元素的乘积.不用除法 且在O(n)内解决这个问 ...
- node-rsa加密,java解密调试
用NODE RSA JS 加密解密正常,用JAVA RSAUtils工具类加密解密正常.但是用node加密玩的java解密不了.原因:node默认的是 DEFAULT_ENCRYPTION_SCHEM ...
- ubuntu下删除和新建用户(并有su权限)
http://blog.csdn.net/speedme/article/details/8206144ubuntu下删除和新建用户(并有su权限) 如何创建ubuntu新用户?输入:sudo add ...