作为一个由c/c++转过来的菜鸟,刚接触Python的变量的时候很不适应,应为他的行为很像指针,void* ,不知道大家有没有这样的感觉。其实Python是以数据为本,变量可以理解为标签。作为c/c++的菜鸟,把跟踪变量地址的习惯带入Python,举个小例子说明Python的变量,对象,及参数传递。

 '''例子1'''
x = 1
def fun(x):
x = 2
return None fun(x)
print(x)

其实不打印也可以,我们用pycharm单步调试,看一下在每一行执行中,变量x的值的变化,及其地址的变化(其实这句话应该改成:变量x的指向变化更准确)

Python中id()函数,可以返回对象的地址,id()的官方解释是:Return the “identity” of an object,既然是identity,肯定是唯一的;官方又说:CPython implementation detail: This is the address of the object in memory。我们暂时把id()返回值看做是对象在内存中的地址。

第一步:进入debug,在监视窗口,添加对Id(x),和id(y) 的观察,蓝色高亮,表示下一步将执行,我们看到这时,x,y都没有分配地址

第二步:执行下一步,我们发现变量x,开始分配地址, 1392686144,我们记下这个数。

第三步:进入函数中,执行 x = 2语句,我们发现,x的地址已经变成 1392686176,这就是Python 变量的特性,我们不能理解成把变量x赋值为2,而是“名字为x的标签指向对象2”,这样更准确。

第四步:返回fun(x)函数,我们发现X的id()值又变回原来的数字,在这个例子中,我们把局部变量和全局变量用同一个标签指示,当调用函数,进入函数内部执行时,系统会创建堆栈,保留进入函数前的运行环境及数据。进入函数后,有创建了一个同名的标签x,x = 2,把局部标签指向局部对象2,这是局部标签x指向一个新的对象,内存地址肯定变化,当return none,返回函数调用时,堆栈撤销,局部的对象,变量随之撤销,局部标签x也撤销,此时x做回自己,变成全局标签x,依旧指向数字对象1.这就是为什么在函数内部,标签x指向其他对象后,返回调用,又恢复调用前的内存地址。

第一个例子中,从标签x的内存地址变化,帮我们理解Python的变量的行为。

在第二个例子中,我们仍然通过监视标签的内存地址变化,理解参数传递的过程

 '''例子2'''
a = []
def fun(a):
a.append(1)
return None fun(a)
print(a)

第一步:执行完函数调用,参数赋值,蓝色高亮是下一步将要执行的代码。我们发现在这一步,发生了参数赋值,创建堆栈,局部标签x的内存地址与外部标签a的内存地址相同,说明这一步,完成参数赋值,我们是不是可以把Python的“赋值语句”理解为“标签指向”这个动作?从这看,这样理解是可以的。所以“参数赋值”这个动作,可以理解为统一标签指向。

第二步: 当函数返回时,我们发现列表a的地址没有改变,并且列表中元素1得到保留,没有因为局部变量撤销而消失,这回一个典型的通过标签(引用),在局部过程中改变全局变量的例子。Python标签的这种特性是不是很像c++中的引用?是不是很像c中的指针?

总结:Python的变量,我们用标签来理解,参考c的void*,参考c++中的&,Python的赋值动作,可以理解为“标签改变指向”的动作。参数传递过程,是交换标签指向的过程

python的变量,对象的内存地址以及参数传递过程的更多相关文章

  1. 一个对象toString()方法如果没有被重写,那么默认调用它的父类Object的toString()方法,而Object的toString()方法是打印该对象的hashCode,一般hashCode就是此对象的内存地址

    昨天因为要从JFrame控件获取密码,注意到一个问题,那就是用toString方法得到的不一定是你想要的,如下: jPasswordField是JFrame中的密码输入框,如果用下面的方法是得不到密码 ...

  2. JVM运行时数据区及对象在内存中初始化的过程

    JVM运行时数据区 Java虚拟机所管理的内存区域,也称为运行时数据区,分为以下几个运行时数据区,如图所示 程序计数器:当前程序所执行字节码的行号指示器 程序计数器(Program Counter R ...

  3. python中的函数对象的内存地址是多少

    今天和同学讨论一个问题,发现了函数的内存地址和我想象的不一样. 我以为同一个函数,假如给的参数不一样,那么这两个函数的id就不一样. 然后经过实验,发现python为了便于管理函数,所有的函数都放在同 ...

  4. Python中类和对象在内存中是如何保存?

    类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份,大致如下图: 如上图所示,根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个类对象指针,该值 ...

  5. 在python里使用WriteProcessMemory修改内存地址上的值

    import os import sys from ctypes import * windll.kernel32.WriteProcessMemory.argtypes = [c_void_p, c ...

  6. python如何从内存地址上加载pythn对象

    python如何从内存地址上加载pythn对象 在python中我们可以通过id函数来获取某个python对象的内存地址,或者可以通过调用对象的__repr__魔术函数来获取对象的详细信息 def t ...

  7. (内存地址hashcode与对象内容hashcode)分析== 和 equal()方法

    ==.equals()和hashCode()字符串测试 1.hashCode() 是根据 内容 来产生hash值的 2.System.identityHashCode() 是根据 内存地址 来产生ha ...

  8. python获取内存地址上存储的值

    在python中,可以通过id()这个方法来获取对象的内存地址. 但是反过来,怎么获取内存地址上存储的值? 先看一段代码: from ctypes import string_at from sys ...

  9. 优雅的重载toString方法,打印对象内容而不是打印内存地址的方法

    如果直接在日志或者System.out.println中打印java对象,会打印这个对象的内存地址,而不是具体内容. 为了便于调试,一般的做法有2种: 1.重写toStrong方法 2.将对象传入JS ...

随机推荐

  1. 排序算法review<1>--直接插入排序

    简单插入排序的基本思想:对于原待排序记录中的第i(1<=i<=n-1)个元素Ki,保证其前面的i个元素已经是有序的,要在这前i个元素(K0--Ki-1)中找到合适的位置将第i个元素插入,具 ...

  2. linux知识体系

    0. Linux简介与厂商版本 1. Linux开机启动 2. Linux文件管理 3. Linux的架构 4. Linux命令行与命令 5. Linux文件管理相关命令 6. Linux文本流 7. ...

  3. LInux下桥接模式详解二

    上篇文章导入博客园的比较早,而这篇自己在写的时候才发现内部复杂的很,以至于没能按时完成,造成两篇文章的间隔时间有点长! 话不多说,言归正传! 前面的文章介绍了桥接模式下的基础理论知识,其实本节想结合L ...

  4. Purpose of ContextLoaderListener in Spring

    The ApplicationContext is where your Spring beans live. The purpose of the ContextLoaderListener is ...

  5. shell_03

    函数: fanction print_welcome(){ echo welcome now time is `date` } print_welcome 函数调用 print _welcome 00 ...

  6. python web框架 django 添加环境变量

    C:\Users\Administrator.QH-20170325TNQR\AppData\Local\Programs\Python\Python36\Scripts把环境变量加上 可以在本地执行 ...

  7. Java-小技巧-004-jdk时间,jdk8时间,joda,calendar,获取当前时间前一周、前一月、前一年的时间

    1.推荐使用java8 localdate等 线程安全 支持较好 地址 2.joda 一.简述 查看SampleDateFormat源码,叙述有: * Date formats are not syn ...

  8. db-mysql-001- 语句备份表

    1.备份表 CREATE TABLE AAbak( SELECT * FROM AA ); 2.两个已存在表导数据 INSERT INTO AAbak(c1,c2) SELECT c1,c2 FROM ...

  9. js原生函数bind

    /*在javascript中,函数总是在一个特殊的上下文执行(称为执行上下文),如果你将一个对象的函数赋值给另外一个变量的话,这个函数的执行上下文就变为这个变量的上下文了.下面的一个例子能很好的说明这 ...

  10. linux上scp远程复制的使用

    一.实例展示 两台机器IP分别为:A.104.238.161.75,B.43.224.34.73. ------把别的服务器上的资源拿到自己的上边 在A服务器上操作,将B服务器上/home/lk/目录 ...