对局部变量的赋值并不会对全局变量产生什么影响,因为它们本来就是两个不相关的变量。
问题2:如果想在上面示例中的函数内部为全局变量重新赋值怎么办?可以在函数内部通过global关键字声明该局部变量就是全局变量:
#!/usr/bin/env python # -*- encoding:utf-8 -*- name = 'Tom' def func4(): global name name = 'Jerry' print(name) print(name) func4() print(name)输出结果:
Tom Jerry Jerry可见全局name的值的确被func4函数内部的操作改变了。
问题3:能不能将全局变量通过传参的方式传递给函数,然后在函数内部对全局变量做修改呢?变量值的改变通常有两种方式:(1) 重新赋值 (2) 改变原有值。要想在函数内部通过重新赋值来改变全局变量的值,则只能通过上面介绍的使用global关键字来完成,通过传参是无法实现的。而要想在函数内部改变全局变量的原有值的属性就要看该参数是值传递还是引用传递了,如果是引用传递则可以在函数内部对全局变量的值进行修改,如果是值传递则不可以实现。具体请看下面的分析。
Python中的变量回收机制:变量存放在内存中
内存是有地址的(门牌号)
变量是对内存地址的引用
Python对内存地址引用次数是有记数的
Python解释器会定期将引用次数为0的内存地址清空--释放
函数名也是变量,函数体就是这个变量的值:
calc = lambda x: x*3
这个话题在几乎所有的编程语言中都会涉及,之所以把它放到最后是因为觉得这个问题对于编程新手来说比较难理解。与 “值传递与引用传递” 相似的概念是 “值拷贝与引用拷贝”。前者主要是指函数调用时传递参数的时候,后者是指把一个变量赋值给其他变量或其他一些专门的拷贝操作(如深拷贝和浅拷贝)的时候。
这里我们需要先来说明下定义变量的过程是怎样的。首先,我们应该知道变量的值是保存在内存中的;以name='Tom'为例,定义变量name的过程是这样的:
在内存中分配一块内存空间;
将变量的值(字符串“Tom”)存放到这块内存空间;
将这块内存空间的地址(门牌号)赋值给变量name;
也就是说变量保存的不是真实的值,而是存放真实值的内存空间的地址。
“值拷贝”和“值传递”比较好理解,就是直接把变量的值在内存中再复制一份;也就是说会分配并占用新的内存空间,因此变量指向的内存空间是新的,与之前的变量及其指向的内存空间没有什么关联了。而“引用拷贝”和“引用传递”仅仅是把变量对内存空间地址的引用复制了一份,也就是说两个变量指向的是同一个内存空间,因此对一个变量的值的修改会影响其他指向这个相同内存空间的变量的值。实际上,向函数传递参数时传递的也是实参的“值拷贝或引用拷贝”。
因此当我们判断一个变量是否被修改时,只需要搞明白该变量所指向的内存地址以及该内存地址对应的内存空间中的值是否发生了改变即可。
示例1: name1 = 'Tom' name2 = name1 name2 = 'Jerry' print('name1: %s' % name1) print('name2: %s' % name2)思考:name1被改变了吗?
分析下上面操作的过程:
定义变量name1:在内存中开辟一块空间,将字符串'Tom'保存到该内存空间,然后name1指向该内存空间的地址;
定义变量name2,并将name1赋值给它:实际上就是让name2也指向name1所指定的内存空间;
为变量name2重新赋一个新值:在内存中开辟一块新的空间,将字符串‘Jerry’保存到该内存空间,然后name2指向该内存空间的地址;
name1指向的内存地址发生改变了吗?-- 没有,因为name1并没有被重新进行赋值操作。
name1所指向的内存空间中的内容改变了吗? -- 没有,并没有对它做什么,并且字符串本就是个常量,是不可能被改变的。