•  当函数内部引用一个全局变量时,如果此全局变量为可变类型,那么函数内部是可以改变此全局变量的值,用不用globale申明全局变量都一样。但是如果想给此变量重新赋值则必须要使用global。
l = []
d = {}
def add_value():
d['frank'] = 'yangcaho'
l.append(d)
add_value()
print(l)
print(d) 输出:
[{'frank': 'yangcaho'}]
{'frank': 'yangcaho'}
l = []
d = {}
def add_value():
global l
global d
d['frank'] = 'yangcaho'
l.append(d)
add_value()
print(l)
print(d) 输出:
[{'frank': 'yangcaho'}]
{'frank': 'yangcaho'}
  •  当函数内部引用一个全局变量时,如果此全局变量为不可变类型,那么如果要能够在函数内部改变全局变量的值,就需要用global,不用改变则不需要用global也可以引用
a = 'frank'
def add_value():
global a
a = 'yangchao'
add_value()
print(a) yangchao
a = 'frank'
def add_value():
b = a + 'yangchao'
print(b)
add_value()
print(a) frankyangchao
frank

  结论:可以使用定义在函数外的全局变量的值(假设在函数内没有同名的变量)。但强烈建议尽量避免这样做,因为这使得程序的读者会不清楚这个变量是在哪里定义的。使用global语句可以清楚地表明变量是在外面的块定义的。

一些细微区别

可变对象如list的.paaend()操作与‘+’操作,的一些不同点。

  • 用 ‘+’ 实际上是重新定义一个变量了。但是原列表的内存位置不会变,会开辟一个新的内存,L不是直接在原来l的基础上增加然后指向l
l = ['frank', 'liuilu']
print(id(l))
L = l + ['yangchao']
print(id(L))
print(l)
print(id(l)) 36364616
36365960
['frank', 'liuilu']
36364616
  • 用 append 和 ’ += ‘实际上是在原来变量基础上增加。
l = ['frank', 'liuilu']
print(id(l))
l += ['yangchao']
print(l)
print(id(l)) 43639112
['frank', 'liuilu', 'yangchao']
43639112
  •  一下代码中个很坑的地方:为什么l的值不是[{'age': 1}, {'age': 2}]而是[{'age': 2}, {'age': 2}],因为l中存入的值是d实际是存入了d所指向内存地址。在第二次改变d的值得时候,就是改变了d的指向。于是第一次添加的d的值也会改变。
l = []
d = {}
def add_value():
for i in range(1, 3):
print('第%s次循环' %i)
d['age'] = i
print(d)
print('#' * 10)
print(l)
print('#' * 10)
l.append(d)
print(l)
add_value() 输出结果
第1次循环
{'age': 1}
##########
[]
##########
[{'age': 1}]
第2次循环
{'age': 2}
##########
[{'age': 2}]
##########
[{'age': 2}, {'age': 2}]

  但是函数内如果是用赋值的方式(如下面两种模式),那么函数中的d就不再是全局变量中的d了。所以有了每次赋值操作(即’=‘),每次append的d都是新的值。不会改变原来的值。

l = []
d = {}
def add_value():
for i in range(1, 3):
print('第%s次循环' %i)
d = {'age', i}
print(d)
print('#' * 10)
print(l)
print('#' * 10)
l.append(d)
print(l)
add_value() 第1次循环
{1, 'age'}
##########
[]
##########
[{1, 'age'}]
第2次循环
{2, 'age'}
##########
[{1, 'age'}]
##########
[{1, 'age'}, {2, 'age'}]
l = []
def add_value():
for i in range(1, 3):
d = {}
print('第%s次循环' %i)
d['age'] = i
print(d)
print('#' * 10)
print(l)
print('#' * 10)
l.append(d)
print(l)
add_value() 第1次循环
{'age': 1}
##########
[]
##########
[{'age': 1}]
第2次循环
{'age': 2}
##########
[{'age': 1}]
##########
[{'age': 1}, {'age': 2}]

  总得来讲就是在操作可变对象的时候,只要有 = 就会重新开辟内存创建新变量,诸如list.append() 、list += 、list.pop、dic.update()、dict['key'] = value、实际上都是在原来变量的基础上作修改,如果后面再次引用则会引用每次修改后的值。

  

a = []
b = []
c = {}
d = {}
e = 'frank'
f = 'frank'
print(id(a), id(b), id(c), id(d), id(e), id(f)) 43770760 43770824 31284896 31284968 31302408 31302408

  可见每次创建一个空的可变对象时,都会重新开辟内存,但不可变对象就是指向原来的的地址空间。

python中可变与不可变类型变量中一些较难理解的地方的更多相关文章

  1. python中的可变与不可变对象

    Python中的可变对象和不可变对象 什么是可变/不可变对象 不可变对象,该对象所指向的内存中的值不能被改变.当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一 ...

  2. Python中的可变、不可变对象和赋值技巧序列解包

    可变对象和不可变对象 在python中一切皆对象.在Python中不存在所谓的值传递调用,一切传递都是对象的引用,也可认为是传址. python中,对象分为可变(mutable)和不可变(immuta ...

  3. python中不可变数据类型和可变数据类型

    在学习python过程中我们一定会遇到不可变数据类型和可变数据类型. 1.名词解释 以下所有的内容都是基于内存地址来说的. 不可变数据类型: 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址 ...

  4. Python中可变和不可变类型

    可变类型 列表,字典,集合 不可变类型 数字,字符串,元组 这里的可变不可变,是指内存中的那块内容(value)是否可以被改变 不可变类型 数字 a = 1 b = 1 print(id(a), id ...

  5. php学习笔记5--php中的可变变量,可变函数及匿名函数

    可变变量指的是:将一个变量的值再次当做一个变量名从而得到另外一个变量的值.如:$name = 'dqrcsc';$myname = 'name'; //$myname的值碰巧是另一个变量的变量名ech ...

  6. iOS中怎么判断可变和不可变的坑(更正版)

    iOS中怎么判断可变和不可变的坑 怎么判断NSString和NSMutableString呢 看题 BOOL result = [" isKindOfClass:[NSMutableStri ...

  7. 【翻译】为什么Java中的String不可变

    笔主前言: 众所周知,String是Java的JDK中最重要的基础类之一,在笔主心中的地位已经等同于int.boolean等基础数据类型,是超越了一般Object引用类型的高端大气上档次的存在. 但是 ...

  8. C中參数个数可变的函数

    一.什么是可变參数 我们在C语言编程中有时会遇到一些參数个数可变的函数,比如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一 ...

  9. java中的final与可变类型、不可变类型的关系

    如果你对final和不可变类型的概念与区别有疑问的话,可以打开这篇文章.希望我的解答可以帮到您! 1.不可变类型: 什么是可变类型,什么是不可变类型呢? 首先我们看一下下面的这行代码: String ...

随机推荐

  1. 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 三十║ Nuxt实战:动态路由+同构

    上期回顾 说接上文<二九║ Nuxt实战:异步实现数据双端渲染>,昨天咱们通过项目二的首页数据处理,简单了解到了 nuxt 异步数据获取的作用,以及亲身体验了几个重要文件夹的意义,整篇文章 ...

  2. 文本分布式表示(一):word2vec理论

    Word2vec是Google的Mikolov等人提出来的一种文本分布式表示的方法,这种方法是对神经网络语言模型的“瘦身”, 巧妙地运用层次softmax(hierarchical softmax ) ...

  3. 合肥.NET技术社区首次线下聚会全程回顾【多图】

    2019年3月16日对于合肥.NET来说是一个特别的日子,因为这是合肥.NET技术社区首次非正式线下聚会!这次聚会受场地限制(毕竟是聚餐的形式),即使换成了小椅子后,最多也只能容纳24个人,所以还有一 ...

  4. 精读《V8 引擎 Lazy Parsing》

    1. 引言 本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧! 这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性 ...

  5. js事件循环机制辨析

     对于新接触js语言的人来说,最令人困惑的大概就是事件循环机制了.最开始这也困惑了我好久,花了我几个月时间通过书本,打代码,查阅资料不停地渐进地理解他.接下来我想要和大家分享一下,虽然可能有些许错误的 ...

  6. 【设计模式+原型理解】第三章:javascript五种继承父类方式

    [前言] 我们都知道,面向对象(类)的三大特征:封装.继承.多态 继承:子类继承父类的私有属性和公有方法 封装:把相同的代码写在一个函数中 多态: ->重载:JS严格意义上是没有重载,但可以通过 ...

  7. DSAPI 菜单渲染

    在本节,将演示DSAPI.菜单渲染功能.本功能支持对WINFORM菜单项的任意细节进行处理,使用配色方案进行渲染,默认配色方案为Visual Studio2012的黑色主题风格. 我们先来看一下未使用 ...

  8. 使用Aspose.Words将Word文档转换为Tiff格式图片文件

    用Aspose组件的优点是操作Word文档不需要安装Office就可以实现. 首先需要引用Aspose.Words.dll,链接地址:链接:https://pan.baidu.com/s/1rJvjp ...

  9. 面试常问的几个排序和查找算法,PHP实现

    冒泡,快排,二分查找,都是面试常问的几个算法题目,虽然简单,但是一段时间不用的话就很容易忘记,这里我用PHP实现了一下,温故而知新. 排序 冒泡排序 每一次冒出一个最大的值 function bubb ...

  10. Flask实战第5天:页面跳转和重定向

    GET和POST请求 在网络请求中有许多请求方式,比如GET, POST, DELETE, PUT等,最常用的就是GET和POST GET 只会在服务器上获取资源,不会更改服务器的状态,这种请求方式推 ...